diff options
author | Daniel Wilhelm <daniel@wili.li> | 2015-10-02 14:53:20 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2015-10-02 14:53:20 +0200 |
commit | 94db751716dd2851f99b5c4c2981da1d1f4780f8 (patch) | |
tree | e4ffc9f5ae2b2873f267a6e5d3d2092c8aad49a7 | |
parent | 6.10 (diff) | |
download | FreeFileSync-94db751716dd2851f99b5c4c2981da1d1f4780f8.tar.gz FreeFileSync-94db751716dd2851f99b5c4c2981da1d1f4780f8.tar.bz2 FreeFileSync-94db751716dd2851f99b5c4c2981da1d1f4780f8.zip |
6.11
145 files changed, 2280 insertions, 3539 deletions
diff --git a/FreeFileSync/Build/Changelog.txt b/FreeFileSync/Build/Changelog.txt index 5b631823..497ce39f 100644 --- a/FreeFileSync/Build/Changelog.txt +++ b/FreeFileSync/Build/Changelog.txt @@ -1,5 +1,27 @@ -FreeFileSync 6.10 ------------------ +FreeFileSync 6.11 [2014-11-03] +------------------------------ +Updated Recycle Bin access for Windows 10 +New command line option "-edit" to load configuration without executing +Case-insensitive command line argument evaluation +New Explorer context menu options for ffs_gui, ffs_batch files +Added sync variant to folder pair info in log file +Don't process and log folder pair if nothing to do except writing DB file +Fixed liblzma.5.dylib not found during startup (OS X 10.8) +Added version info to application bundles (OS X) +Fixed incorrect warning when configuration contains empty folder pairs +Replaced misleading inotify error message "No space left on device" (Linux) +Fixed FreeFileSync launcher blocking app folder move (OS X) +Updated default main dialog layout +Fixed async error evaluation when creating volume shadow copies +Keep user interface responsive while creating a volume shadow copy +Fixed error when starting asynchronously from a batch script +Show progress of writing log files +Fixed updated file being left deleted when copying permission failed +New Project website: http://www.freefilesync.org/ + + +FreeFileSync 6.10 [2014-10-01] +------------------------------ Fixed crash when accessing recycle bin in compatibility mode (Windows 7, 8) Draw middle grid selection irrespective of focus column Don't show parts of progress graph if nothing to sync diff --git a/FreeFileSync/Build/Help/FreeFileSync.hhc b/FreeFileSync/Build/Help/FreeFileSync.hhc index 1902cb14..f8fda04b 100644 --- a/FreeFileSync/Build/Help/FreeFileSync.hhc +++ b/FreeFileSync/Build/Help/FreeFileSync.hhc @@ -83,10 +83,5 @@ <param name="Local" value="html\Run as Service.html"> </OBJECT> </UL> - <LI> <OBJECT type="text/sitemap"> - <param name="Name" value="Links"> - <param name="Local" value="html\Links.html"> - <param name="ImageNumber" value="19"> - </OBJECT> </UL> </BODY></HTML> diff --git a/FreeFileSync/Build/Help/FreeFileSync.hhp b/FreeFileSync/Build/Help/FreeFileSync.hhp index a9f19ebc..531eb70c 100644 --- a/FreeFileSync/Build/Help/FreeFileSync.hhp +++ b/FreeFileSync/Build/Help/FreeFileSync.hhp @@ -25,7 +25,6 @@ html\Variable Drive Letters.html html\Volume Shadow Copy.html html\RealtimeSync.html html\Run as Service.html -html\Links.html [INFOTYPES] diff --git a/FreeFileSync/Build/Help/html/Command Line.html b/FreeFileSync/Build/Help/html/Command Line.html index 3123ba49..f9b4fb46 100644 --- a/FreeFileSync/Build/Help/html/Command Line.html +++ b/FreeFileSync/Build/Help/html/Command Line.html @@ -110,8 +110,8 @@ and check if synchronization completed successfully: <h3>3. Customize an existing configuration</h3> -<P>You can replace the directories of a given ffs_gui or ffs_batch configuration file by using the <FONT FACE="Courier New, monospace">-leftdir</FONT> -and <FONT FACE="Courier New, monospace">-rightdir</FONT> parameters: +<P>You can replace the directories of a given ffs_gui or ffs_batch configuration file by using the <FONT FACE="Courier New, monospace">-LeftDir</FONT> +and <FONT FACE="Courier New, monospace">-RightDir</FONT> parameters: </P> <div class="greybox"> diff --git a/FreeFileSync/Build/Help/html/FreeFileSync.html b/FreeFileSync/Build/Help/html/FreeFileSync.html index 106b8d3c..ad176beb 100644 --- a/FreeFileSync/Build/Help/html/FreeFileSync.html +++ b/FreeFileSync/Build/Help/html/FreeFileSync.html @@ -54,5 +54,30 @@ <LI><FONT SIZE=4>Synchronization statistics</FONT> </OL> +<BR> + +<H3>FreeFileSync Links</H3> + +<div class="bluebox"> + <div class="bluebox_inner"> + <B>Homepage:</B><BR> + <A HREF="http://www.freefilesync.org/">http://www.freefilesync.org/</A> - feedback, suggestions, bug-reports, official download mirrors<BR> + + <BR> + + <b>Support the project:</b><BR> + + If you like FreeFileSync... + <A HREF="http://www.freefilesync.org/donate.php">Donate now</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="" src="../img/donate.png"> + + <a style="width: 65px; height:51px;display:inline-block;vertical-align:middle;background: url(../img/donate.png) no-repeat;" + title="Donate via PayPal" href="http://www.freefilesync.org/donate.php"></a> + </div> +</div> +<BR CLEAR=LEFT> + </BODY> </HTML>
\ No newline at end of file diff --git a/FreeFileSync/Build/Help/html/Links.html b/FreeFileSync/Build/Help/html/Links.html deleted file mode 100644 index 5f7ca317..00000000 --- a/FreeFileSync/Build/Help/html/Links.html +++ /dev/null @@ -1,29 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> -<HTML> -<HEAD> - <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=windows-1252"> - <TITLE></TITLE> - <link rel="stylesheet" type="text/css" href="base.css" > -</HEAD> -<BODY LANG="de-DE" DIR="LTR"> - -<H2>FreeFileSync Links</H2> - -<div class="bluebox"> - <div class="bluebox_inner"> - <B>Homepage:</B><BR> - <A HREF="http://freefilesync.sf.net/">http://freefilesync.sf.net/</A> - <BR><BR> - - <B>Project on SourceForge:</B> feedback, suggestions and bug-reports<BR> - <A HREF="http://sourceforge.net/projects/freefilesync/">http://sourceforge.net/projects/freefilesync/</A> - <BR><BR> - - <B>If you like FreeFileSync:</B><BR> - <A HREF="http://freefilesync.sourceforge.net/donate.php">Support the project by a donation</A> - </div> -</div> -<BR CLEAR=LEFT> - -</BODY> -</HTML>
\ No newline at end of file diff --git a/FreeFileSync/Build/Help/html/RealtimeSync.html b/FreeFileSync/Build/Help/html/RealtimeSync.html index 6b2e2feb..f021c3de 100644 --- a/FreeFileSync/Build/Help/html/RealtimeSync.html +++ b/FreeFileSync/Build/Help/html/RealtimeSync.html @@ -12,9 +12,8 @@ <FONT SIZE=3><I><SPAN STYLE="font-weight: normal">Automated Synchronization</SPAN></I></FONT> </H2> -<P>The primary purpose of RealtimeSync is to execute a command line each time a directory becomes -available (e. g. insert of a USB-stick) <b>or</b> when it detects changes in one of the monitored directories. Usually this command line will trigger -a FreeFileSync batch job. +<P>The primary purpose of RealtimeSync is to execute a command line each time it detects changes in one of the monitored directories +<b>or</b> when a directory becomes available (e. g. insert of a USB-stick). Usually this command line will trigger a FreeFileSync batch job. </P> <BR> @@ -93,7 +92,7 @@ on the stick. RealtimeSync will also trigger each time files are modified in <FO Write a list of all changes to a log file:<BR> <FONT FACE="Courier New, monospace"> - cmd /c echo %change_action% "%change_path%" >> C:\log.txt + cmd /c echo %change_action% "%change_path%" >> %UserProfile%\Desktop\log.txt </FONT> </div> </div> diff --git a/FreeFileSync/Build/Help/img/donate.png b/FreeFileSync/Build/Help/img/donate.png Binary files differnew file mode 100644 index 00000000..c7fb97c4 --- /dev/null +++ b/FreeFileSync/Build/Help/img/donate.png diff --git a/FreeFileSync/Build/Help/img/filter.png b/FreeFileSync/Build/Help/img/filter.png Binary files differindex f135ca0f..09747e93 100644 --- a/FreeFileSync/Build/Help/img/filter.png +++ b/FreeFileSync/Build/Help/img/filter.png diff --git a/FreeFileSync/Build/Languages/outdated/dutch.lng b/FreeFileSync/Build/Languages/dutch.lng index d9802c29..d8192801 100644 --- a/FreeFileSync/Build/Languages/outdated/dutch.lng +++ b/FreeFileSync/Build/Languages/dutch.lng @@ -1,113 +1,41 @@ <header> <language>Nederlands</language> - <translator>Edwin Dierssen</translator> + <translator>Leo49</translator> <locale>nl_NL</locale> <image>flag_holland.png</image> <plural_count>2</plural_count> <plural_definition>n == 1 ? 0 : 1</plural_definition> </header> -<source>&Show</source> -<target></target> - -<source>Show hidden dialogs and warning messages again?</source> -<target></target> - -<source>Clear filter</source> -<target></target> - -<source>Start comparison</source> -<target></target> - -<source>Show all permanently hidden dialogs and warning messages again</source> -<target></target> - -<source>Show hidden dialogs again</source> -<target></target> - -<source>&Stop</source> -<target></target> - -<source>Bytes copied:</source> -<target></target> - -<source>&Pop-up</source> -<target></target> - -<source>&Versioning</source> -<target></target> - -<source>&Permanent</source> -<target></target> - -<source>C&lear</source> -<target></target> - -<source>Handle daylight saving time</source> -<target></target> - -<source>Consider file times with specified offset as equal</source> -<target></target> - -<source>Ignore time shift (in hours)</source> -<target></target> - -<source>New</source> -<target></target> - -<source>&Reset layout</source> -<target></target> - -<source>Start &synchronization</source> -<target></target> - -<source>Start &comparison</source> -<target></target> - -<source>Clear local filter</source> -<target></target> - -<source>Relative folder</source> -<target></target> - -<source>Multiple folder pairs write to a common subfolder. Please review your configuration.</source> -<target></target> - -<source>Cannot find folder %x.</source> -<target></target> - -<source>&File</source> -<target></target> - -<source>The following folder paths are dependent from each other:</source> +<source>Open configuration for edit without executing.</source> <target></target> <source>Both sides have changed since last synchronization.</source> -<target>Beide zijdes zijn veranderd sinds de laatste synchronisatie.</target> +<target>Beide zijden zijn gewijzigd sinds de laatste synchronisatie.</target> <source>Cannot determine sync-direction:</source> -<target>Kan de synchronisatie-richting niet bepalen:</target> +<target>De synchronisatierichting kan niet worden bepaald:</target> <source>No change since last synchronization.</source> <target>Geen veranderingen sinds de laatste synchronisatie.</target> <source>The database entry is not in sync considering current settings.</source> -<target>De database is niet gesynchroniseerd volgens de huidige instellingen.</target> +<target>De databasevermelding is niet gesynchroniseerd volgens de huidige instellingen.</target> <source>Setting default synchronization directions: Old files will be overwritten with newer files.</source> -<target>Stel standaard synchronisatie richtingen in: Oude bestanden worden door nieuwere bestanden overschreven.</target> +<target>Standaardwaarden instellen voor synchronisatierichtingen: oude bestanden worden overschreven door nieuwere.</target> <source>Checking recycle bin availability for folder %x...</source> -<target>Prullebak beschikbaarheid voor map %x te controleren...</target> +<target>Controleer beschikbaarheid voor de prullenbak map %x...</target> <source>Moving file %x to the recycle bin</source> -<target>Bezig met verplaatsen van bestand %x naar de prullenbak</target> +<target>Verplaatsen van bestand %x naar de prullenbak</target> <source>Moving folder %x to the recycle bin</source> -<target>Bezig met verplaatsen van map %x naar de prullenbak</target> +<target>Verplaatsen van de map %x naar de prullenbak</target> <source>Moving symbolic link %x to the recycle bin</source> -<target>Bezig met verplaatsen van snelkoppeling %x naar de prullenbak</target> +<target>Verplaatsen symbolische koppeling %x naar de prullenbak</target> <source>Deleting file %x</source> <target>Verwijderen van bestand %x</target> @@ -116,34 +44,34 @@ <target>Verwijderen van map %x</target> <source>Deleting symbolic link %x</source> -<target>Verwijderen van snelkoppeling %x</target> +<target>Symbolische koppeling %x verwijderen</target> <source>The recycle bin is not available for the following folders. Files will be deleted permanently instead:</source> -<target>De prullenbak is niet beschikbaar voor de volgende mappen. Bestanden zullen permanent verwijderd worden:</target> +<target>De prullenbak is niet beschikbaar voor de volgende mappen. De bestanden worden permanent verwijderd:</target> <source>An exception occurred</source> -<target>Er heeft een uitzondering plaatsgevonden</target> +<target>Een uitzondering is opgetreden</target> <source>A directory path is expected after %x.</source> -<target>Een bestandslocatie pad is verwacht na %x.</target> +<target>Een mappad wordt na %x verwacht.</target> <source>Syntax error</source> -<target>Syntax fout</target> +<target>Syntaxisfout</target> <source>Cannot open file %x.</source> -<target>Kan bestand %x niet openen.</target> +<target>Het bestand %x kan niet geopend worden.</target> <source>File %x does not contain a valid configuration.</source> -<target>Bestand %x bevat geen valide configuratie.</target> +<target>Het bestand %x bevat geen geldige configuratie.</target> <source>Unequal number of left and right directories specified.</source> -<target>Oneven nummer van linker en rechter bestandslocaties gespecificeerd.</target> +<target>Ongelijk aantal linker- en rechter- mappen opgegeven.</target> <source>The config file must not contain settings at directory pair level when directories are set via command line.</source> -<target>Het configuratiebestand mag geen instellingen bevatten voor een bestandslocatie level als bestandslocaties in de command line ingesteld zijn.</target> +<target>Het configuratiebestand mag geen instellingen op mappaarniveau bevatten, als de directories via de opdrachtregel zijn ingesteld.</target> <source>Directories cannot be set for more than one configuration file.</source> -<target>Bestandslocaties kunnen niet voor meer dan een configuratiebestand gemaakt worden.</target> +<target>Mappen kunnen niet worden gebruikt voor meer dan één configuratiebestand.</target> <source>Command line</source> <target>Opdrachtregel</target> @@ -152,70 +80,73 @@ <target>Syntax:</target> <source>global config file:</source> -<target>Globaal configuratiebestand:</target> +<target>globaal configuratiebestand:</target> <source>config files:</source> <target>configuratiebestanden:</target> <source>directory</source> -<target>bestandslocatie</target> +<target>directory</target> <source>Path to an alternate GlobalSettings.xml file.</source> -<target>Pad naar alternatief GlobalSettings.xml bestand.</target> +<target>Bestandspad naar alternatieve GlobalSettings.xml.</target> <source>Any number of FreeFileSync .ffs_gui and/or .ffs_batch configuration files.</source> -<target>Elk aantal FreeFileSync .ffs_gui en/of .ffs_batch configuratiebestanden.</target> +<target>Een willekeurig aantal FreeFileSync. ffs_gui en/of .ffs_batch configuratiebestanden.</target> <source>Any number of alternative directory pairs for at most one config file.</source> -<target>Willekeurig aantal gekoppelde mappen voor één configuratie bestand.</target> +<target>Een willekeurig aantal alternatieve directoryparen voor maximaal een configuratiebestand.</target> <source>Cannot find the following folders:</source> -<target>Kan de volgende mappen niet vinden:</target> +<target>De volgende map kon niet worden gevonden:</target> <source>You can ignore this error to consider each folder as empty. The folders then will be created automatically during synchronization.</source> -<target>U kunt deze foutmelding negeren om elke map als leeg te markeren. De mappen worden dan automatisch aangemaakt tijdens de synchronisatie.</target> +<target>Deze fout kan worden genegeerd, om de mappen als leeg te zien en de folders automatisch te creëren wanneer u synchroniseert.</target> <source>A folder input field is empty.</source> -<target>Een map invoerveld is leeg.</target> +<target>Invoerveld van een map is leeg.</target> <source>The corresponding folder will be considered as empty.</source> -<target>De overeenkomstige map zal als leeg worden beschouwd.</target> +<target>De betreffende map wordt als leeg beschouwd.</target> + +<source>The following folder paths are dependent from each other:</source> +<target>De volgende mappaden zijn afhankelijk van elkaar:</target> <source>File %x has an invalid date.</source> -<target>Bestand %x heeft een ongeldige datum.</target> +<target>Het bestand %x heeft een ongeldige datum.</target> <source>Date:</source> <target>Datum:</target> <source>Files %x have the same date but a different size.</source> -<target>Bestanden %x hebben dezelfde datums maar een afwijkende grootte.</target> +<target>De bestanden %x hebben hetzelfde datum, maar de grootte is verschillend.</target> <source>Size:</source> <target>Grootte:</target> <source>Content comparison was skipped for excluded files %x.</source> -<target>Vergelijking voor uitgesloten bestanden %x is overgeslagen.</target> +<target>De vergelijking van de uitgesloten bestanden %x werd overgeslagen.</target> <source>Items differ in attributes only</source> -<target>Items verschillen alleen in attributen</target> +<target>De items verschillen alleen in de kenmerken</target> <source>Resolving symbolic link %x</source> -<target>Bezig met vinden van snelkoppeling %x</target> +<target>Symbolische link %x oplossen</target> <source>Comparing content of files %x</source> -<target>De inhoud van %x bestanden wordt vergeleken</target> +<target>Vergelijkt de inhoud van bestanden %x</target> <source>Generating file list...</source> -<target>Genereren van bestandslijst...</target> +<target>Maak bestandslijst...</target> <source>Starting comparison</source> -<target>Vergelijking starten</target> +<target>Start vergelijking</target> <source>Calculating sync directions...</source> -<target>Synchronisatie richtingen calculeren...</target> +<target>Berekenen sync richtingen...</target> <source>Out of memory.</source> -<target>Onvoldoende geheugen.</target> +<target>Onvoldoende werkgeheugen.</target> <source>Item exists on left side only</source> <target>Item bestaat alleen aan de linkerkant</target> @@ -224,25 +155,25 @@ <target>Item bestaat alleen aan de rechterkant</target> <source>Left side is newer</source> -<target>De linkerkant is nieuwer</target> +<target>Linkerkant is nieuwer</target> <source>Right side is newer</source> -<target>De rechterkant is nieuwer</target> +<target>Rechterkant is nieuwer</target> <source>Items have different content</source> -<target>De items hebben een andere inhoud</target> +<target>Items hebben verschillende inhoud</target> <source>Both sides are equal</source> -<target>Beide kanten zijn gelijk</target> +<target>Beide zijden zijn gelijk</target> <source>Conflict/item cannot be categorized</source> -<target>Conflict/item kan niet worden gecategoriseerd</target> +<target>Conflict/item niet kan worden gecategoriseerd</target> <source>Copy new item to left</source> -<target>Kopieër nieuw item naar de linkerkant</target> +<target>Kopieer nieuw item naar links</target> <source>Copy new item to right</source> -<target>Kopieër nieuw item naar de rechterkant</target> +<target>Kopieer nieuw item naar rechts</target> <source>Delete left item</source> <target>Verwijder linker item</target> @@ -251,10 +182,10 @@ <target>Verwijder rechter item</target> <source>Move file on left</source> -<target>Verplaats bestand aan de linkerkant</target> +<target>Verplaats linker bestand</target> <source>Move file on right</source> -<target>Verplaats bestand aan de rechterkant</target> +<target>Verplaats rechter bestand</target> <source>Overwrite left item</source> <target>Overschrijf linker item</target> @@ -263,21 +194,21 @@ <target>Overschrijf rechter item</target> <source>Do nothing</source> -<target>Geen actie ondernemen</target> +<target>Niets doen</target> <source>Update attributes on left</source> -<target>Update attributen aan de linkerkant</target> +<target>Update kenmerken aan de linkerzijde</target> <source>Update attributes on right</source> -<target>Update attributen aan de rechterkant</target> +<target>Update kenmerken aan de rechterzijde</target> <source> <pluralform>1 byte</pluralform> <pluralform>%x bytes</pluralform> </source> <target> -<pluralform>1 byte</pluralform> -<pluralform>%x bytes</pluralform> +<pluralform>1 Byte</pluralform> +<pluralform>%x Bytes</pluralform> </target> <source>%x MB</source> @@ -290,7 +221,7 @@ <target>%x GB</target> <source>Cannot load file %x.</source> -<target>Kan bestand %x niet laden.</target> +<target>Kan bestand %x niet inlezen.</target> <source>Database file %x is incompatible.</source> <target>Databasebestand %x is niet compatibel.</target> @@ -302,121 +233,124 @@ <target>Databasebestand %x bestaat nog niet.</target> <source>Database file is corrupt:</source> -<target>Databasebestand is corrupt:</target> +<target>Databasebestand is beschadigd:</target> <source>Cannot write file %x.</source> <target>Kan bestand %x niet schrijven.</target> <source>Cannot read file %x.</source> -<target>Kan bestand %x niet vinden.</target> +<target>Kan het bestand %x niet lezen.</target> <source>Database files do not share a common session.</source> -<target>Databasebestanden delen geen gezamelijke sessie.</target> +<target>Database bestanden kunnen geen gemeenschappelijke sessie delen.</target> <source>Searching for folder %x...</source> -<target>Bezig met zoeken naar map %x...</target> +<target>Zoek naar map %x...</target> <source>Cannot read file attributes of %x.</source> -<target>Kan bestandskenmerken van %x niet uitlezen.</target> +<target>Kan de bestandskenmerken niet lezen van %x.</target> <source>Cannot get process information.</source> -<target>Kan geen procesinformatie verkrijgen.</target> +<target>Kan geen procesinformatie krijgen.</target> <source>Waiting while directory is locked:</source> -<target>Wachten terwijl directory gelocked is:</target> +<target>Wachten terwijl de direcory is vergrendeld:</target> <source>Lock owner:</source> -<target>Lock eigenaar:</target> +<target>Vergrendel eigenaar:</target> <source> <pluralform>1 sec</pluralform> <pluralform>%x sec</pluralform> </source> <target> -<pluralform>1 sec</pluralform> -<pluralform>%x sec</pluralform> +<pluralform>1 Sek.</pluralform> +<pluralform>%x Sek.</pluralform> </target> <source>Detecting abandoned lock...</source> -<target>Detecteren van achter gelaten lock...</target> +<target>Opsporen van verlaten vergrendeling...</target> <source>Creating file %x</source> -<target>Bestand %x wordt aangemaakt</target> +<target>Bestand %x maken</target> <source>Items processed:</source> -<target>Onderdelen verwerkt:</target> +<target>Items verwerkt:</target> <source>Items remaining:</source> -<target>Onderdelen te gaan:</target> +<target>Overgebleven items:</target> <source>Total time:</source> <target>Totale tijd:</target> <source>Error parsing file %x, row %y, column %z.</source> -<target>Fout bij het parsen van bestand %x, rij %y, kolom %z.</target> +<target>Fout bij het analyseren van bestand %x, rij %y, kolom %z.</target> <source>Cannot set directory lock for %x.</source> -<target>Kan locatie %x niet op slot zetten.</target> +<target>De mapvergrendeling voor %x kan niet ingesteld worden.</target> <source>Scanning:</source> -<target>Doorzoekt:</target> +<target>Scannen:</target> <source> <pluralform>1 thread</pluralform> <pluralform>%x threads</pluralform> </source> <target> -<pluralform>1 thread</pluralform> -<pluralform>%x threads</pluralform> +<pluralform>1 Thread</pluralform> +<pluralform>%x Threads</pluralform> </target> <source>Encoding extended time information: %x</source> -<target>Coderen uitgebreide tijdinformatie: %x</target> +<target>Codering van langere tijdinformatie: %x</target> <source>/sec</source> <target>/sec</target> <source>%x items/sec</source> -<target>%x items per seconde</target> +<target>%x items/sec</target> <source>Show in Explorer</source> -<target>Toon in Verkenner</target> +<target>In Explorer weergeven</target> <source>Open with default application</source> -<target>Open met standaardapplicatie</target> +<target>Openen met standaardtoepassing</target> <source>Browse directory</source> -<target>Verken map</target> +<target>Blader in directory</target> <source>Cannot access the Volume Shadow Copy Service.</source> -<target>Kan de Volume Shadow Copy Service niet benaderen.</target> +<target>Geen toegang tot het Volume Shadow Copy Service.</target> <source>Please use FreeFileSync 64-bit version to create shadow copies on this system.</source> -<target>Gebruik alstublieft de FreeFileSync 64-bit versie om schaduwkopieën te maken op dit systeem.</target> +<target>Gebruik FreeFileSync 64-bits versie voor het maken van schaduwkopieën op dit systeem.</target> <source>Cannot determine volume name for %x.</source> -<target>Kan volumenaam voor %x niet bepalen.</target> +<target>Kan de volumenaam niet vaststellen voor %x.</target> <source>Volume name %x is not part of file path %y.</source> -<target>Schijfnaam %x is geen deel van bestandspad %y.</target> +<target>Volumenaam %x behoort niet tot bestandspad %y.</target> <source>Stop requested: Waiting for current operation to finish...</source> -<target>Stop aangegeven: Wachten tot de huidige handeling klaar is...</target> +<target>Stop opgevraagd: wachten totdat de huidige bewerking is voltooit...</target> <source>Unable to create time stamp for versioning:</source> -<target>Aanmaken van timestamp voor versiebeheer mislukt:</target> +<target>Kan geen tijdstempel maken voor versiebeheer:</target> <source>&Open...</source> -<target>&Open...</target> +<target>&Openen...</target> <source>Save &as...</source> -<target>Ops&laan als...</target> +<target>Opslaan &als...</target> <source>&Quit</source> -<target>&Afsluiten</target> +<target>&Stoppen</target> + +<source>&File</source> +<target>&Bestand</target> <source>&View help</source> -<target>Help &bekijken</target> +<target>&Help weergeven</target> <source>&About</source> <target>&Over</target> @@ -431,13 +365,13 @@ <target>1. Selecteer mappen om te bekijken.</target> <source>2. Enter a command line.</source> -<target>2. Geef een opdrachtregel in.</target> +<target>2. Een opdrachtregel invoeren.</target> <source>3. Press 'Start'.</source> -<target>3. Klik op 'Start'.</target> +<target>3. Druk op 'Start'.</target> <source>To get started just import a .ffs_batch file.</source> -<target>Importeer een .ffs_batch bestand om te beginnen.</target> +<target>Om te beginnen gewoon een .ffs_batch-bestand importeren.</target> <source>Folders to watch:</source> <target>Mappen om te bekijken:</target> @@ -446,22 +380,22 @@ <target>Map toevoegen</target> <source>Remove folder</source> -<target>Verwijder map</target> +<target>Map verwijderen</target> <source>Browse</source> -<target>Verkennen</target> +<target>Bladeren</target> <source>Select a folder</source> <target>Selecteer een map</target> <source>Idle time (in seconds):</source> -<target>Stationaire tijd (in seconden):</target> +<target>Inactieve tijd (in seconden):</target> <source>Idle time between last detected change and execution of command</source> -<target>Tijd tussen de laatste gedetecteerde verandering en de uitvoering van het commando</target> +<target>Inactieve tijd tussen laatste gedetecteerde wijziging en uitvoering van de opdracht</target> <source>Command line:</source> -<target>Command line:</target> +<target>Opdrachtregel:</target> <source> The command is triggered if: @@ -469,16 +403,16 @@ The command is triggered if: - new folders arrive (e.g. USB stick insert) </source> <target> -De opdracht word geactiveerd als: -- bestanden of subfolders veranderen -- nieuwe folders worden gevonden (bijvoorbeeld bij invoeging van USB stick) +De opdracht wordt geactiveerd als: +- bestanden of submappen wijzigen +- nieuwe mappen verschijnen (b.v. USB-stick wordt geplaatst) </target> <source>&Start</source> <target>&Start</target> <source>About</source> -<target>Informatie</target> +<target>Over</target> <source>Build: %x</source> <target>Build: %x</target> @@ -487,13 +421,13 @@ De opdracht word geactiveerd als: <target>Alle bestanden</target> <source>Automated Synchronization</source> -<target>Automatische Synchronisatie</target> +<target>Automatische synchronisatie</target> <source>Directory monitoring active</source> -<target>Bestandslocatie controle actief</target> +<target>Directory controle actief</target> <source>Waiting until all directories are available...</source> -<target>Wachten tot alle bestandslocaties beschikbaar zijn...</target> +<target>Wacht totdat alle directories beschikbaar zijn...</target> <source>Error</source> <target>Fout</target> @@ -502,22 +436,22 @@ De opdracht word geactiveerd als: <target>&Herstellen</target> <source>&Show error</source> -<target>Laat &fouten zien</target> +<target>&Toon fout</target> <source>Incorrect command line:</source> -<target>Incorrectie command line:</target> +<target>Onjuiste opdrachtregel:</target> <source>&Retry</source> -<target>&Opnieuw proberen</target> +<target>&Probeer opnieuw</target> <source>File content</source> <target>Bestandsinhoud</target> <source>File time and size</source> -<target>Bestandstijd- en grootte</target> +<target>Datum en grootte bestand</target> <source>Two way</source> -<target>Twee kanten op</target> +<target>Twee richtingen</target> <source>Mirror</source> <target>Spiegelen</target> @@ -532,61 +466,64 @@ De opdracht word geactiveerd als: <target>Meerdere...</target> <source>Moving file %x to %y</source> -<target>Bezig met verplaatsen van bestand %x naar %y</target> +<target>Bestand %x verplaatsen naar %y</target> <source>Moving folder %x to %y</source> -<target>Bezig met verplaatsen van map %x naar %y</target> +<target>Map %x verplaatsen naar %y</target> <source>Moving symbolic link %x to %y</source> -<target>Bezig met verplaatsen van snelkoppeling %x naar %y</target> +<target>Symbolische link %x verplaatsen naar %y</target> <source>Removing old versions...</source> -<target>Bezig met verwijderen van oude versies...</target> +<target>Verwijderen van oude versies...</target> <source>Creating symbolic link %x</source> -<target>Snelkoppeling %x wordt aangemaakt</target> +<target>Creëren symbolische link %x</target> <source>Creating folder %x</source> -<target>Map %x wordt aangemaakt</target> +<target>Map %x maken</target> <source>Overwriting file %x</source> -<target>Bezig met overschrijven van bestand %x</target> +<target>Overschrijven bestand %x</target> <source>Overwriting symbolic link %x</source> -<target>Bezig met overschrijven van snelkoppeling %x</target> +<target>Symbolische link %x overschrijven</target> <source>Verifying file %x</source> -<target>Verifieert bestand %x</target> +<target>Controleren van bestand %x</target> <source>Updating attributes of %x</source> -<target>Attributen bijwerken van %x</target> +<target>Kenmerken van %x bijwerken</target> <source>Creating a Volume Shadow Copy for %x...</source> -<target>Aanmaken van een Volume Shadow Copy voor %x...</target> +<target>Maken van een volume schaduwkopie voor %x...</target> <source>Data verification error: %x and %y have different content.</source> -<target>Data verificatie fout: %x en %y hebben een verschillende inhoud.</target> +<target>Gegevens verificatiefout: %x en %y hebben verschillende inhoud.</target> <source>Target folder %x already existing.</source> -<target>Doelmap %x bestaat al.</target> +<target>Doelmap %x bestaat reeds.</target> + +<source>Cannot find folder %x.</source> +<target>Kan de map %x niet vinden.</target> <source>Target folder input field must not be empty.</source> -<target>Doelmap mag niet leeg zijn.</target> +<target>Het invoerveld van de doelmap moet niet leeg zijn.</target> <source>Source folder %x not found.</source> <target>Bronmap %x niet gevonden.</target> <source>Please enter a target folder for versioning.</source> -<target>Selecteer alstublieft een doelmap voor versiebeheer.</target> +<target>Geef een doelmap voor versiebeheer.</target> <source>The following items have unresolved conflicts and will not be synchronized:</source> <target>De volgende items hebben onopgeloste conflicten en zullen niet worden gesynchroniseerd:</target> <source>The following folders are significantly different. Make sure you are matching the correct folders for synchronization.</source> -<target>De volgende mappen zijn heel verschillend. Wees er zeker van dat dit de goede mappen zijn voor synchronisatie.</target> +<target>De volgende mappen zijn beduidend verschillend. Zorg ervoor dat u de juiste mappen voor synchronisatie geselecteerd hebt.</target> <source>Not enough free disk space available in:</source> -<target>Niet genoeg vrije schijfruimte beschikbaar op:</target> +<target>Er is onvoldoende vrije schijfruimte beschikbaar in:</target> <source>Required:</source> <target>Vereist:</target> @@ -594,11 +531,14 @@ De opdracht word geactiveerd als: <source>Available:</source> <target>Beschikbaar:</target> +<source>Multiple folder pairs write to a common subfolder. Please review your configuration.</source> +<target>Meerdere map-paren schrijven naar een gemeenschappelijk submap. Controleer uw configuratie.</target> + <source>Synchronizing folder pair:</source> -<target>Bezig met synchroniseren van folder paar:</target> +<target>Synchroniseren van map-paar:</target> <source>Generating database...</source> -<target>Genereren van database...</target> +<target>Genereren database...</target> <source>job name</source> <target>taaknaam</target> @@ -607,37 +547,37 @@ De opdracht word geactiveerd als: <target>Synchronisatie gestopt</target> <source>Synchronization completed with errors</source> -<target>Synchronisatie is met fouten afgerond</target> +<target>Synchronisatie met fouten voltooid</target> <source>Synchronization completed with warnings</source> -<target>Synchronisatie afgerond met waarschuwingen</target> +<target>Synchronisatie met waarschuwingen voltooid</target> <source>Nothing to synchronize</source> <target>Niets om te synchroniseren</target> <source>Synchronization completed successfully</source> -<target>Synchronisatie succesvol</target> +<target>Synchronisatie succesvol voltooid</target> <source>Saving log file %x...</source> -<target>Opslaan van logbestand %x...</target> +<target>Opslaan logbestand %x...</target> <source>Stopped</source> <target>Gestopt</target> <source>You can switch to FreeFileSync's main window to resolve this issue.</source> -<target>U kunt naar het hoofdvenster overschakelen om dit probleem op te lossen.</target> +<target>U kunt overschakelen naar het hoofdvenster van FreeFileSync om dit probleem op te lossen.</target> <source>&Don't show this warning again</source> -<target>Laat deze &waarschuwing niet meer zien</target> +<target>&Deze waarschuwing niet opnieuw weergeven</target> <source>&Ignore</source> <target>&Negeren</target> <source>&Switch</source> -<target>&Omschakelen</target> +<target>&Wisselen</target> <source>Switching to FreeFileSync's main window</source> -<target>Overschakelen naar FreeFileSync's hoofdvenster</target> +<target>Overschakelen naar het hoofdvenster van FreeFileSyncs</target> <source> <pluralform>Automatic retry in 1 second...</pluralform> @@ -649,16 +589,16 @@ De opdracht word geactiveerd als: </target> <source>&Ignore subsequent errors</source> -<target>&Negeer volgende foutmeldingen</target> +<target>&Latere fouten negeren</target> <source>Retrying operation...</source> -<target>Handeling opnieuw proberen...</target> +<target>Bewerking opnieuw proberen...</target> <source>Serious Error</source> -<target>Serieuze Error</target> +<target>Ernstige fout</target> <source>Check for Program Updates</source> -<target>Controleer op programma updates</target> +<target>Controleer voor programma-updates</target> <source>A new version of FreeFileSync is available:</source> <target>Er is een nieuwe versie van FreeFileSync beschikbaar:</target> @@ -667,19 +607,19 @@ De opdracht word geactiveerd als: <target>Nu downloaden?</target> <source>&Download</source> -<target>&Download</target> +<target>&Downloaden</target> <source>FreeFileSync is up to date.</source> -<target>U gebruikt de nieuwste versie van FreeFileSync.</target> +<target>FreeFileSync is actueel.</target> <source>Unable to connect to sourceforge.net.</source> <target>Kan geen verbinding maken met sourceforge.net.</target> <source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source> -<target>Kan huidige FreeFileSync versienummer niet online vinden. Wilt u handmatig controleren?</target> +<target>Kan online niet het actuele FreeFileSync versienummer vinden. Wilt u handmatig controleren?</target> <source>&Check</source> -<target>&Check</target> +<target>&Controleren</target> <source>Symlink</source> <target>Symlink</target> @@ -693,8 +633,11 @@ De opdracht word geactiveerd als: <source>Name</source> <target>Naam</target> +<source>Relative folder</source> +<target>Relatieve map</target> + <source>Base folder</source> -<target>Hoofdmap</target> +<target>Basismap</target> <source>Size</source> <target>Grootte</target> @@ -703,7 +646,7 @@ De opdracht word geactiveerd als: <target>Datum</target> <source>Extension</source> -<target>Extensie</target> +<target>Uitbreiding</target> <source>Category</source> <target>Categorie</target> @@ -712,13 +655,13 @@ De opdracht word geactiveerd als: <target>Actie</target> <source>Drag && drop</source> -<target>Drag en drop</target> +<target>Slepen && neerzetten</target> <source>Local comparison settings</source> -<target>Lokale vergelijkings instellingen</target> +<target>Lokale vergelijking instellingen</target> <source>Local synchronization settings</source> -<target>Lokale synchronisatie instellingen</target> +<target>Lokale synchronisatie-instellingen</target> <source>Local filter</source> <target>Lokale filter</target> @@ -730,25 +673,34 @@ De opdracht word geactiveerd als: <target>Geen</target> <source>Remove local settings</source> -<target>Verwijder lokale instellingen</target> +<target>Lokale instellingen verwijderen</target> + +<source>Clear local filter</source> +<target>Verwijder lokale filter</target> <source>Copy</source> -<target>Kopiëren</target> +<target>Kopieer</target> <source>Paste</source> <target>Plakken</target> <source>Local Synchronization Settings</source> -<target>Lokale synchronisatie instellingen</target> +<target>Lokale synchronisatie-instellingen</target> <source>&New</source> <target>&Nieuw</target> <source>&Save</source> -<target>O&pslaan</target> +<target>&Opslaan</target> <source>Save as &batch job...</source> -<target>Opslaan als &batch opdracht...</target> +<target>Opslaan als &batchverwerking...</target> + +<source>Start &comparison</source> +<target>Start &vergelijking</target> + +<source>Start &synchronization</source> +<target>Start &synchronisatie</target> <source>&Options</source> <target>&Opties</target> @@ -757,52 +709,58 @@ De opdracht word geactiveerd als: <target>&Taal</target> <source>&Find...</source> -<target>&Zoek...</target> +<target>&Vinden...</target> + +<source>&Reset layout</source> +<target>&Reset lay-out</target> <source>&Export file list...</source> -<target>&Exporteer bestandslijst...</target> +<target>&Exporteren bestandslijst...</target> <source>&Tools</source> <target>&Gereedschap</target> <source>&Check for new version</source> -<target>&Controleer voor nieuwe versie</target> +<target>&Controleren op nieuwe versie</target> <source>&Check now</source> -<target>&Controleer nu</target> +<target>&Nu conroleren</target> <source>Check &automatically once a week</source> -<target>Controleer &automatisch eens per week</target> +<target>Controleer eens per week &automatisch</target> <source>Cancel</source> <target>Annuleren</target> <source>Compare</source> -<target>Vergelijk</target> +<target>Vergelijken</target> <source>Synchronize</source> -<target>Synchroniseer</target> +<target>Synchroniseren</target> <source>Add folder pair</source> -<target>Voeg gekoppelde mappen toe</target> +<target>Map-paar toevoegen</target> <source>Remove folder pair</source> -<target>Verwijder gekoppelde mappen</target> +<target>Verwijder map-paar</target> <source>Swap sides</source> -<target>Wissel zijdes</target> +<target>Verwisselen van zijden</target> <source>Close search bar</source> -<target>Sluit zoekbalk</target> +<target>Sluit de zoekbalk</target> <source>Find:</source> -<target>Zoek:</target> +<target>Zoeken:</target> <source>Match case</source> <target>Hoofdlettergevoelig</target> +<source>New</source> +<target>Nieuw</target> + <source>Open...</source> -<target>Open...</target> +<target>Openen...</target> <source>Save</source> <target>Opslaan</target> @@ -811,25 +769,25 @@ De opdracht word geactiveerd als: <target>Opslaan als...</target> <source>View type:</source> -<target>Laat type zien:</target> +<target>Weergavetype:</target> <source>Select view:</source> -<target>Selecteer uiterlijk:</target> +<target>Selecteer weergave:</target> <source>Statistics:</source> <target>Statistieken:</target> <source>Number of files and folders that will be deleted</source> -<target>Aantal bestanden en mappen die verwijderd zullen worden</target> +<target>Aantal bestanden en mappen die worden verwijderd</target> <source>Number of files that will be overwritten</source> -<target>Aantal bestanden die overschreven zullen worden</target> +<target>Aantal bestanden die worden overschreven</target> <source>Number of files and folders that will be created</source> -<target>Aantal bestanden en mappen die zullen worden aangemaakt</target> +<target>Aantal bestanden en mappen die worden gemaakt</target> <source>Total bytes to copy</source> -<target>Aantal bytes om te kopiëren</target> +<target>Totaal aantal te kopiëren bytes</target> <source>Use local settings:</source> <target>Gebruik lokale instellingen:</target> @@ -838,13 +796,22 @@ De opdracht word geactiveerd als: <target>Selecteer een variant:</target> <source>Identify equal files by comparing modification time and size.</source> -<target>Identificeer gelijke bestanden door bewerkingstijd en grootte te vergelijken.</target> +<target>Identificeer gelijke bestanden door het vergelijken van wijzigingen in tijd en grootte.</target> <source>Identify equal files by comparing the file content.</source> -<target>Identificeer gelijke bestanden door de bestandsinhoud te vergelijken.</target> +<target>Identificeer gelijke bestanden door het vergelijken van de bestandsinhoud.</target> + +<source>Ignore time shift (in hours)</source> +<target>Negeer tijdverschuiving (in uren)</target> + +<source>Consider file times with specified offset as equal</source> +<target>Overweeg bestand-tijden met gespecificeerde verspringing als gelijkwaardig te beschouwen</target> + +<source>Handle daylight saving time</source> +<target>Zomertijd gebruiken</target> <source>Symbolic links:</source> -<target>Snelkoppelingen:</target> +<target>Symbolische koppelingen:</target> <source>More information</source> <target>Meer informatie</target> @@ -853,16 +820,16 @@ De opdracht word geactiveerd als: <target>Lokale instellingen:</target> <source>Include:</source> -<target>Meerekenen:</target> +<target>Omvatten:</target> <source>Exclude:</source> -<target>Uitsluiten:</target> +<target>Uitgesloten:</target> <source>Show examples</source> -<target>Laat voorbeelden zien</target> +<target>Toon voorbeelden</target> <source>Time span:</source> -<target>Tijdspanne:</target> +<target>Tijdsduur:</target> <source>File size:</source> <target>Bestandsgrootte:</target> @@ -873,11 +840,14 @@ De opdracht word geactiveerd als: <source>Maximum:</source> <target>Maximum:</target> +<source>C&lear</source> +<target>&Wissen</target> + <source>Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair.</source> -<target>Selecteer filter regels om bepaalde bestanden uit te sluiten van synchronisatie. Geef bestandspaden in die relatief zijn aan hun corresponderende folderparen.</target> +<target>Selecteer filterregels om bepaalde bestanden uit te sluiten van synchronisatie. Voer bestandspaden in ten opzichte van hun bijbehorend map-paar.</target> <source>Detect moved files</source> -<target>Detecteer verplaatste bestanden</target> +<target>Verplaatste bestanden detecteren</target> <source> - Requires and creates database files @@ -885,58 +855,67 @@ De opdracht word geactiveerd als: - Not supported by all file systems </source> <target> -- Vereist en creeërt database bestanden -- Detectie actief na eerste synchronisatie +- Vereist en maakt database bestanden. +- Detectie actief na intitiële syncronisatie - Niet ondersteund door alle bestandssystemen </target> <source>Detect synchronization directions with the help of database files</source> -<target>Detecteer synchronisatierichtingen met behulp van databasebestanden</target> +<target>Detecteren van synchronisatie richtingen met behulp van databasebestanden</target> <source>Delete files:</source> -<target>Verwijder bestanden:</target> +<target>Bestanden verwijderen:</target> + +<source>&Permanent</source> +<target>&Permanent</target> <source>Delete or overwrite files permanently</source> -<target>Bestanden definitief verwijderen of overschrijven</target> +<target>Bestanden permanent verwijderen of overschrijven</target> <source>&Recycle bin</source> -<target>&Prullebak</target> +<target>&Prullenbak</target> <source>Back up deleted and overwritten files in the recycle bin</source> -<target>Maak een backup van verwijderde en overschreven bestanden in de prullenbak</target> +<target>Back-up de verwijderde en overschreven bestanden in de prullenbak</target> + +<source>&Versioning</source> +<target>&Versiebeheer</target> <source>Move files to a user-defined folder</source> -<target>Verplaats bestanden naar een gebruikers gedefineerde map</target> +<target>Verplaats bestanden naar een door de gebruiker gedefinieerde map</target> <source>Naming convention:</source> -<target>Naamgevingsconventie</target> +<target>Naamgevingsconventie:</target> <source>Handle errors:</source> <target>Fouten afhandelen:</target> <source>Hide all error and warning messages</source> -<target>Verberg alle fout- en waarschuwingsberichten</target> +<target>Verberg alle foutberichten en waarschuwingen</target> + +<source>&Pop-up</source> +<target>&Pop-up</target> <source>Show pop-up on errors or warnings</source> -<target>Laat pop-up zien bij foutmeldingen of waarschuwingen</target> +<target>Toon pop-up bij fouten of waarschuwingen</target> <source>On completion:</source> -<target>Bij voltooiing:</target> +<target>Na voltooiing:</target> <source>OK</source> <target>OK</target> <source>Start synchronization now?</source> -<target>Start de synchronisatie nu?</target> +<target>Synchronisatie nu starten?</target> <source>Variant:</source> <target>Variant:</target> <source>&Don't show this dialog again</source> -<target>Laat deze dialoog &niet meer zien</target> +<target>&Dit dialoogvenster niet opnieuw weergeven</target> <source>Items found:</source> -<target>Onderdelen gevonden:</target> +<target>Gevonden objecten:</target> <source>Time remaining:</source> <target>Resterende tijd:</target> @@ -945,10 +924,13 @@ De opdracht word geactiveerd als: <target>Verstreken tijd:</target> <source>Synchronizing...</source> -<target>Synchroniseert...</target> +<target>Synchroniseren...</target> <source>Minimize to notification area</source> -<target>Minimaliseer naar systeemvak</target> +<target>Minimaliseren naar systeemvak</target> + +<source>Bytes copied:</source> +<target>Gekopieerde bytes:</target> <source>Close</source> <target>Sluiten</target> @@ -960,64 +942,67 @@ De opdracht word geactiveerd als: <target>Stop</target> <source>Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x</source> -<target>Maak een batchbestand voor onbeheerde synchronisatie. Om te starten dubbelklikt u dit bestand of rooster in een taakplanner: %x</target> +<target>Creërt een batch-bestand om zonder toezicht te synchroniseren. Dubbelklikt u op het bestand om te starten of maak een opdracht in de taakplanner: %x</target> + +<source>&Stop</source> +<target>&Stop</target> <source>Stop synchronization at first error</source> -<target>Stop synchronisatie bij eerste foutmelding</target> +<target>Synchronisatie bij eerste fout stoppen</target> <source>Run minimized</source> -<target>Draai geminimaliseerd</target> +<target>Geminimaliseerd uitvoeren</target> <source>Save log:</source> -<target>Bewaar logbestand:</target> +<target>Logbestand opslaan:</target> <source>Limit:</source> -<target>Beperk:</target> +<target>Limiet:</target> <source>Limit maximum number of log files</source> -<target>Limiteer maximaal aantal log bestanden</target> +<target>Maximaal aantal logboekbestanden limiteren</target> <source>How can I schedule a batch job?</source> -<target>Hoe kan ik een batch opdracht inroosteren?</target> +<target>Hoe kan ik een batchverwerking plannen?</target> <source>The following settings are used for all synchronization jobs.</source> -<target>De volgende instellingen worden gebruikt voor alle synchronisaties.</target> +<target>De volgende instellingen worden gebruikt voor alle synchronisatie opdrachten.</target> <source>Fail-safe file copy</source> -<target>Fail-safe bestandskopie</target> +<target>Fail-safe bestand kopiëren</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> -Kopiëer naar een tijdelijk bestand (*.ffs_tmp) voor je het doel overschrijft. -Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. +Kopiëren naar een tijdelijk bestand (*.ffs_tmp) voordat het doel wordt overschreven. +Dit garandeert een consistente status zelfs in het geval van een ernstige fout. </target> <source>(recommended)</source> <target>(aanbevolen)</target> <source>Copy locked files</source> -<target>Kopiëer vergrendelde bestanden</target> +<target>Vergrendelde bestanden kopiëren</target> <source>Copy shared or locked files using the Volume Shadow Copy Service.</source> -<target>Kopiëer gedeelde of vergrendelde bestanden met behulp van de Volume Shadow Copy Service.</target> +<target>Gedeelde of vergrendelde bestanden met behulp van de Volume Schaduw copy-Service kopiëren.</target> <source>(requires administrator rights)</source> -<target>(vereist administrator rechten)</target> +<target>(vereist beheerdersrechten)</target> <source>Copy file access permissions</source> -<target>Kopiëer toegangsrechten van bestand.</target> +<target>Toegangsmachtigingen om bestanden te kopiëren</target> <source>Transfer file and folder permissions.</source> -<target>Draag bestands- en maprechten over.</target> +<target>Overdracht van bestands- en mapmachtigingen.</target> <source>Automatic retry on error:</source> -<target>Probeer automatisch opnieuw bij foutmelding:</target> +<target>Automatisch opnieuw proberen bij fouten:</target> <source>Retry count:</source> -<target>Aantal pogingen:</target> +<target>Aantal herhaalpogingen:</target> <source>Delay (in seconds):</source> <target>Vertraging (in seconden):</target> @@ -1026,16 +1011,22 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Contextmenu aanpassen:</target> <source>Description</source> -<target>Omschrijving</target> +<target>Beschrijving</target> + +<source>Show hidden dialogs again</source> +<target>Verborgen dialoogvensters weergeven</target> + +<source>Show all permanently hidden dialogs and warning messages again</source> +<target>Alle permanent verborgen dialogen en waarschuwingsberichten opnieuw weergeven</target> <source>&Default</source> <target>&Standaard</target> <source>Source code written in C++ using:</source> -<target>Broncode geschreven in C++ met behulp van:</target> +<target>Broncode werd in C++ geschreven met:</target> <source>If you like FreeFileSync</source> -<target>Indien FreeFileSync u bevalt</target> +<target>Als FreeFileSync je bevalt</target> <source>Donate with PayPal</source> <target>Doneer met PayPal</target> @@ -1047,37 +1038,37 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Homepage</target> <source>Email</source> -<target>E-mail</target> +<target>Email</target> <source>Published under the GNU General Public License</source> <target>Gepubliceerd onder de GNU General Public License</target> <source>Many thanks for localization:</source> -<target>Veel dank voor de vertalingen:</target> +<target>Hartelijk dank voor de lokalisatie:</target> <source>Save as Batch Job</source> <target>Opslaan als batch opdracht</target> <source>Delete Items</source> -<target>Verwijder items</target> +<target>Items verwijderen</target> <source>Options</source> <target>Opties</target> <source>Select Time Span</source> -<target>Selecteer tijdspanne</target> +<target>Selecteer tijdsduur</target> <source>&Preferences...</source> <target>&Voorkeuren...</target> <source>Folder Pairs</source> -<target>Map koppelingen</target> +<target>Map-paren</target> <source>Find</source> -<target>Vind</target> +<target>Zoeken</target> <source>View Settings</source> -<target>Instellingen</target> +<target>Instellingen bekijken</target> <source>Overview</source> <target>Overzicht</target> @@ -1086,16 +1077,19 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Configuratie</target> <source>Main Bar</source> -<target>Hoofdbalk</target> +<target>Hoofd balk</target> + +<source>Start comparison</source> +<target>Vergelijking starten</target> <source>Comparison settings</source> -<target>Vergelijksinstellingen</target> +<target>Vergelijkings-instellingen</target> <source>Synchronization settings</source> -<target>Synchronisatieinstellingen</target> +<target>Synchronisatie-instellingen</target> <source>Start synchronization</source> -<target>Start synchronisatie</target> +<target>Synchronisatie starten</target> <source>Confirm</source> <target>Bevestigen</target> @@ -1105,8 +1099,8 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <pluralform>Do you really want to execute the command %y for %x items?</pluralform> </source> <target> -<pluralform>Wilt u echt het commando %y uitvoeren voor 1 item?</pluralform> -<pluralform>Wilt u echt het commando %y uitvoeren voor %x items?</pluralform> +<pluralform>Wilt u echt het commando %y voor één item uitvoeren?</pluralform> +<pluralform>Wilt u echt het commando %y voor %x items uitvoeren?</pluralform> </target> <source>&Execute</source> @@ -1117,8 +1111,8 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <pluralform>%x directories</pluralform> </source> <target> -<pluralform>1 map</pluralform> -<pluralform>%x mappen</pluralform> +<pluralform>1 directory</pluralform> +<pluralform>%x directories</pluralform> </target> <source> @@ -1135,21 +1129,21 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <pluralform>Showing %y of %x rows</pluralform> </source> <target> -<pluralform>Bezig met%y van 1 rij laten zien</pluralform> -<pluralform>Bezig met %y van %x rijen laten zien</pluralform> +<pluralform>%y van 1 rij weergeven</pluralform> +<pluralform>%y van %x rijen weergeven</pluralform> </target> <source>Set direction:</source> -<target>Stel richting in:</target> +<target>Richting instellen:</target> <source>multiple selection</source> <target>meervoudige selectie</target> <source>Include via filter:</source> -<target>Invoegen via filter:</target> +<target>Via filter bijvoegen:</target> <source>Exclude via filter:</source> -<target>Sluit via filter uit:</target> +<target>Uitsluiten via filter:</target> <source>Include temporarily</source> <target>Tijdelijk opnemen</target> @@ -1161,25 +1155,25 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Verwijderen</target> <source>Include all</source> -<target>Alles opnemen</target> +<target>Omvat alle</target> <source>Exclude all</source> -<target>Alles uitsluiten</target> +<target>Alle uitgesloten</target> <source>Show icons:</source> -<target>Laat pictogrammen zien:</target> +<target>Pictogrammen weergeven:</target> <source>Small</source> <target>Klein</target> <source>Medium</source> -<target>Middel</target> +<target>Medium</target> <source>Large</source> <target>Groot</target> <source>Select time span...</source> -<target>Selecteer tijdsspanne...</target> +<target>Selecteer tijdsduur...</target> <source>Show "%x"</source> <target>Toon "%x"</target> @@ -1188,19 +1182,19 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Laatste sessie</target> <source>Folder Comparison and Synchronization</source> -<target>Mappen vergelijken en synchroniseren</target> +<target>Map vergelijken en synchroniseren</target> <source>Configuration saved</source> <target>Configuratie opgeslagen</target> <source>FreeFileSync batch</source> -<target>FreeFileSync taak</target> +<target>FreeFileSync Batch</target> <source>Do you want to save changes to %x?</source> <target>Wilt u de wijzigingen in %x opslaan?</target> <source>Never save &changes</source> -<target>Sla &veranderingen nooit op</target> +<target>&wijzigingen nooit opslaan</target> <source>Do&n't save</source> <target>&Niet opslaan</target> @@ -1209,79 +1203,82 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Verwijder geselecteerde configuraties</target> <source>Synchronization Settings</source> -<target>Synchronisatie instellingen</target> +<target>Synchronisatie-instellingen</target> + +<source>Clear filter</source> +<target>Filter wissen</target> <source>Show files that exist on left side only</source> -<target>Toon bestanden die alleen aan de linkerzijde bestaan</target> +<target>Toon bestanden die bestaan alleen aan de linkerkant</target> <source>Show files that exist on right side only</source> -<target>Toon bestanden die alleen aan de rechterzijde bestaan</target> +<target>Toon bestanden die bestaan alleen aan de rechterkant</target> <source>Show files that are newer on left</source> -<target>Toon bestanden die aan de linkerzijde nieuwer zijn</target> +<target>Bestanden die nieuwer zijn aan de linkerzijde weergeven</target> <source>Show files that are newer on right</source> -<target>Toon bestanden die aan de rechterzijde nieuwer zijn</target> +<target>Bestanden die nieuwer zijn aan de rechterzijde weergeven</target> <source>Show files that are equal</source> -<target>Toon bestanden die gelijk zijn</target> +<target>Bestanden die gelijk zijn weergeven</target> <source>Show files that are different</source> -<target>Toon bestanden die verschillend zijn</target> +<target>Bestanden die verschillend zijn weergeven</target> <source>Show conflicts</source> -<target>Toon conflicten</target> +<target>Conflicten weergeven</target> <source>Show files that will be created on the left side</source> -<target>Toon bestanden die aan de linkerzijde aangemaakt zullen worden</target> +<target>Bestanden die gemaakt worden aan de linkerkant weergeven</target> <source>Show files that will be created on the right side</source> -<target>Toon bestanden die aan de rechterzijde aangemaakt zullen worden</target> +<target>Bestanden die gemaakt worden aan de rechterkant weergeven</target> <source>Show files that will be deleted on the left side</source> -<target>Toon bestanden die van de linkerzijde verwijderd zullen worden</target> +<target>Bestanden die worden verwijderd aan de linker kant weergeven</target> <source>Show files that will be deleted on the right side</source> -<target>Toon bestanden die van de rechterzijde verwijderd zullen worden</target> +<target>Bestanden die worden verwijderd op de rechterkant weergeven</target> <source>Show files that will be overwritten on left side</source> -<target>Toon bestanden die aan de linkerzijde overschreven zullen worden</target> +<target>Bestanden die overschreven worden aan de linkerzijde weergeven</target> <source>Show files that will be overwritten on right side</source> -<target>Toon bestanden die aan de rechterzijde overschreven zullen worden</target> +<target>Bestanden die overschreven worden aan de rechterzijde weergeven</target> <source>Show files that won't be copied</source> -<target>Toon bestanden die niet gekopiëerd zullen worden</target> +<target>Bestanden weergeven die niet gekopieerd worden</target> <source>Show filtered or temporarily excluded files</source> -<target>Laat gefilterde of tijdelijk uitgesloten bestanden zien</target> +<target>Toon gefilterde of tijdelijk uitgesloten bestanden</target> <source>Set as default</source> -<target>Instellen als standaard</target> +<target>Als standaard instellen</target> <source>Filter</source> <target>Filter</target> <source>All files are in sync</source> -<target>Alle bestanden zijn gesynchroniseerd</target> +<target>Alle bestanden zijn in synchronisatie</target> <source>Cannot find %x</source> -<target>Kan %x niet vinden</target> +<target>Kan %x niet vinden.</target> <source>Comma-separated values</source> <target>Door komma gescheiden waarden</target> <source>File list exported</source> -<target>Bestandslijst geëxporteerd</target> +<target>Bestandenlijst geëxporteerd</target> <source>Searching for program updates...</source> -<target>Bezig met zoeken naar programma updates...</target> +<target>Programma-updates zoekt...</target> <source>Close progress dialog</source> -<target>Sluit voortgangsvenster</target> +<target>Voortgang dialoogvenster sluiten</target> <source>Standby</source> -<target>Stand-by</target> +<target>Standby</target> <source>Log off</source> <target>Afmelden</target> @@ -1293,7 +1290,7 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Slaapstand</target> <source>Scanning...</source> -<target>Doorzoekt...</target> +<target>Scannen...</target> <source>Comparing content...</source> <target>Inhoud vergelijken...</target> @@ -1305,10 +1302,10 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Waarschuwing</target> <source>Select all</source> -<target>Selecteer alles</target> +<target>Alles selecteren</target> <source>Paused</source> -<target>Gepauzeerd</target> +<target>Onderbroken</target> <source>Initializing...</source> <target>Initialiseren...</target> @@ -1323,19 +1320,19 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Voortgang</target> <source>Log</source> -<target>Log</target> +<target>Logboek</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>Wilt u dit item echt naar de prullenbak verplaatsen?</pluralform> -<pluralform>Wilt u echt de volgende %x items naar de prullenbak verplaatsen?</pluralform> +<pluralform>Wilt u het volgende item echt naar de prullenbak verplaatsen?</pluralform> +<pluralform>Wilt u de volgende %x items echt naar de prullenbak verplaatsen?</pluralform> </target> <source>Move</source> -<target>Verplaats</target> +<target>Verplaatsen</target> <source> <pluralform>Do you really want to delete the following item?</pluralform> @@ -1343,41 +1340,47 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. </source> <target> <pluralform>Wilt u het volgende item echt verwijderen?</pluralform> -<pluralform>Wilt u echt de volgende %x items verwijderen?</pluralform> +<pluralform>Wilt u de volgende %x items echt verwijderen?</pluralform> </target> <source>Preferences</source> <target>Voorkeuren</target> <source>Copy NTFS permissions</source> -<target>Kopiëer NTFS permissies</target> +<target>Kopiëren van NTFS-machtigingen</target> <source>Integrate external applications into context menu. The following macros are available:</source> -<target>Integreer externe applicaties in het context menu. De volgende macros zijn beschikbaar:</target> +<target>Externe applicaties integreren in het contextmenu. De volgende macro's zijn beschikbaar:</target> <source>- full file or folder name</source> -<target>- volledige bestands- of mapnaam</target> +<target>- volledige bestands- of map-naam</target> <source>- folder part only</source> -<target>- alleen het map gedeelte</target> +<target>- alleen map-deel</target> <source>- Other side's counterpart to %item_path%</source> -<target>- Tegenhanger van de andere kant naar %item_path%</target> +<target>- Andere kant van de tegenhanger naar %item_path%</target> <source>- Other side's counterpart to %item_folder%</source> -<target>- Tegenhanger van de andere kant naar %item_folder%</target> +<target>- Andere kant van de tegenhanger naar %item_folder%</target> + +<source>Show hidden dialogs and warning messages again?</source> +<target>Verborgen vensters en waarschuwingsberichten opnieuw weergeven?</target> + +<source>&Show</source> +<target>&Toon</target> <source>Identify and propagate changes on both sides. Deletions, moves and conflicts are detected automatically using a database.</source> -<target>Identificeer en pas veranderingen toe aan beide kanten. Verwijderingen, verplaatsingen en conflicten worden automatisch gevonden met behulp van een database.</target> +<target>Identificeren en doorgeven van veranderingen aan beide kanten. Verwijderingen, verplaatsingen en conflicten worden automatisch gedetecteerd met behulp van een database.</target> <source>Create a mirror backup of the left folder by adapting the right folder to match.</source> -<target>Maak een spiegelbackup van de linkermap door te zorgen dat de rechtermap gelijk is.</target> +<target>Maak een spiegel-backup van de linkermap, door de rechtermap aan te aanpassen.</target> <source>Copy new and updated files to the right folder.</source> -<target>Kopiëer nieuwe en geupdate bestanden naar de rechtermap.</target> +<target>Nieuwe en bijgewerkte bestanden naar de rechter map kopiëren.</target> <source>Configure your own synchronization rules.</source> -<target>Configureer uw eigen synchronisatieregels.</target> +<target>Configureer uw eigen synchronisatie regels.</target> <source>Exclude</source> <target>Uitsluiten</target> @@ -1416,22 +1419,22 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Vervangen</target> <source>Move files and replace if existing</source> -<target>Verplaats bestanden en overschrijf bestaande bestanden</target> +<target>Verplaats bestanden en vervang bestaande</target> <source>Time stamp</source> <target>Tijdstempel</target> <source>Append a time stamp to each file name</source> -<target>Voeg een timestamp toe aan elke bestandsnaam</target> +<target>Aan elke bestandsnaam een tijdstempel toevoegen</target> <source>Comparison</source> -<target>Vergelijkingen</target> +<target>Vergelijking</target> <source>Synchronization</source> <target>Synchronisatie</target> <source>Leave as unresolved conflict</source> -<target>Beschouw als onopgelost conflict</target> +<target>Laten als onopgelost conflicht</target> <source>File</source> <target>Bestand</target> @@ -1449,28 +1452,28 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Percentage</target> <source>Cannot monitor directory %x.</source> -<target>Kan locatie %x niet controleren.</target> +<target>Kan map %x niet bewaken.</target> <source>Conversion error:</source> -<target>Converteerfout:</target> +<target>Conversie fout:</target> <source>Cannot delete file %x.</source> <target>Kan bestand %x niet verwijderen.</target> <source>The file is locked by another process:</source> -<target>Het bestand is in gebruik door een ander proces:</target> +<target>Het bestand is vergrendeld door een ander proces:</target> <source>Cannot move file %x to %y.</source> -<target>Kan bestand %x niet verplaatsen naar %y.</target> +<target>Het bestand %x kan niet naar %y verplaatst worden.</target> <source>Cannot delete directory %x.</source> -<target>Kan bestand %x niet verwijderen.</target> +<target>De map %x kan niet verwijderd worden.</target> <source>Cannot write file attributes of %x.</source> -<target>Kan bestandskenmerken van %x niet schrijven.</target> +<target>De bestandskenmerken voor %x kunnen niet geschreven worden.</target> <source>Cannot write modification time of %x.</source> -<target>Kan wijzigingstijd van %x niet toevoegen.</target> +<target>De modificatie-tijd van %x kan niet geschreven worden.</target> <source>Cannot read security context of %x.</source> <target>Kan de beveiligingscontext van %x niet lezen.</target> @@ -1479,34 +1482,34 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <target>Kan de beveiligingscontext van %x niet schrijven.</target> <source>Cannot read permissions of %x.</source> -<target>Kan de bevoegdheden van %x niet lezen.</target> +<target>Kan de aangegeven machtigingen van %x niet lezen.</target> <source>Cannot write permissions of %x.</source> -<target>Kan de bevoegdheden van %x niet schrijven.</target> +<target>Kan de aangegeven machtigingen van %x niet schrijven.</target> <source>Cannot create directory %x.</source> -<target>Kan map %x niet aanmaken.</target> +<target>Kan de map %x niet maken.</target> <source>Cannot create symbolic link %x.</source> -<target>Kan snelkoppeling %x niet aanmaken.</target> +<target>Kan de symbolische koppeling %x niet maken.</target> <source>Cannot find system function %x.</source> -<target>Kan systeemfunctie %x niet vinden.</target> +<target>Kan de systeemfunctie %x niet vinden.</target> <source>Cannot copy file %x to %y.</source> -<target>Kan bestand %x niet kopiëren naar %y.</target> +<target>Kan bestand %x niet kopieëren naar %y.</target> <source>Type of item %x is not supported:</source> -<target>Type van bestand %x is niet ondersteund:</target> +<target>Dit itemtype %x wordt niet ondersteund:</target> <source>Cannot resolve symbolic link %x.</source> -<target>Kan snelkoppeling %x niet vinden.</target> +<target>Kan de symbolische koppeling %x niet oplossen.</target> <source>Cannot open directory %x.</source> -<target>Kan map %x niet openen.</target> +<target>Kan de folder %x niet openen.</target> <source>Cannot enumerate directory %x.</source> -<target>Kan map %x niet opsommen.</target> +<target>Kan de folder %x niet opsommen.</target> <source>%x TB</source> <target>%x TB</target> @@ -1519,8 +1522,8 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. <pluralform>%x min</pluralform> </source> <target> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> +<pluralform>1 min.</pluralform> +<pluralform>%x min.</pluralform> </target> <source> @@ -1542,32 +1545,32 @@ Dit garandeert een consistente staat, zelfs in het geval van een serieuze fout. </target> <source>Unable to register to receive system messages.</source> -<target>Registreren voor het verkrijgen van systeemmeldingen is niet mogelijk.</target> +<target>Niet in staat om de ontvangen systeemberichten te registreren.</target> <source>Cannot set privilege %x.</source> -<target>Kan privilege %x niet instellen.</target> +<target>Kan geen privileges %x instellen.</target> <source>Unable to suspend system sleep mode.</source> -<target>Niet in staat om slaapstand uit te stellen.</target> +<target>Niet in staat om de systeem slaapstand op te schorten.</target> <source>Cannot change process I/O priorities.</source> -<target>Kan de I/O prioriteiten niet aanpassen.</target> +<target>De input/output prioriteiten kunnen niet gewijzigd worden.</target> <source>Unable to move %x to the recycle bin.</source> -<target>Kan %x niet verplaatsen naar de prullenbak.</target> +<target>Niet in staat om %x naar de prullenbak te verplaatsen.</target> <source>Checking recycle bin failed for folder %x.</source> -<target>Controleren van prullenbak voor map %x mislukt.</target> +<target>Controle van de prullenbak voor map %x is mislukt.</target> <source>Cannot determine final path for %x.</source> -<target>Kan pad voor %x niet vaststellen.</target> +<target>Kan niet het uiteindelijke pad voor %x bepalen.</target> <source>Error Code %x:</source> <target>Foutcode %x:</target> <source>Cannot read the following XML elements:</source> -<target>Kan de volgende XML elementen niet lezen:</target> +<target>Kan de volgende XML onderdelen niet lezen:</target> <source>Configuration file %x loaded partially only.</source> -<target>Configuratiebestand %x alleen deels geladen.</target> +<target>Configuratiebestand %x alleen gedeeltelijk ingelezen.</target> diff --git a/FreeFileSync/Build/Languages/german.lng b/FreeFileSync/Build/Languages/german.lng index bfcbaf8e..55c249eb 100644 --- a/FreeFileSync/Build/Languages/german.lng +++ b/FreeFileSync/Build/Languages/german.lng @@ -7,6 +7,15 @@ <plural_definition>n == 1 ? 0 : 1</plural_definition> </header> +<source>Cannot copy symbolic link %x to %y.</source> +<target>Der Symbolische Link %x kann nicht nach %y kopiert werden.</target> + +<source>Unable to connect to freefilesync.org.</source> +<target>Es kann keine Verbindung zu freefilesync.org aufgebaut werden.</target> + +<source>Open configuration for edit without executing.</source> +<target>Konfiguration zum Editieren öffnen ohne auszuführen.</target> + <source>Both sides have changed since last synchronization.</source> <target>Beide Seiten wurden seit der letzten Synchronisation verändert.</target> @@ -217,6 +226,9 @@ <source>%x GB</source> <target>%x GB</target> +<source>Cannot load file %x.</source> +<target>Die Datei %x kann nicht geladen werden.</target> + <source>Database file %x is incompatible.</source> <target>Die Datenbankdatei %x ist nicht kompatibel.</target> @@ -268,6 +280,9 @@ <source>Creating file %x</source> <target>Erstelle Datei %x</target> +<source>Saving log file %x...</source> +<target>Speichere Protokolldatei %x...</target> + <source>Items processed:</source> <target>Verarbeitete Elemente:</target> @@ -295,9 +310,6 @@ <pluralform>%x Threads</pluralform> </target> -<source>Encoding extended time information: %x</source> -<target>Speichere erweiterte Zeitinformation: %x</target> - <source>/sec</source> <target>/sek</target> @@ -319,9 +331,6 @@ <source>Please use FreeFileSync 64-bit version to create shadow copies on this system.</source> <target>Bitte benutzen Sie die FreeFileSync 64-Bit Version, um Schattenkopien auf diesem System zu erstellen.</target> -<source>Cannot load file %x.</source> -<target>Die Datei %x kann nicht geladen werden.</target> - <source>Cannot determine volume name for %x.</source> <target>Der Laufwerksname für %x kann nicht bestimmt werden.</target> @@ -498,21 +507,21 @@ Die Befehlszeile wird ausgelöst, wenn: <source>Data verification error: %x and %y have different content.</source> <target>Verifizierungsfehler: %x und %y haben unterschiedlichen Inhalt.</target> -<source>Cannot find folder %x.</source> -<target>Der Ordner %x wurde nicht gefunden.</target> - <source>Target folder %x already existing.</source> <target>Der Zielordner %x existiert bereits.</target> +<source>Cannot find folder %x.</source> +<target>Der Ordner %x wurde nicht gefunden.</target> + <source>Target folder input field must not be empty.</source> <target>Das Eingabefeld für den Zielordner darf nicht leer sein.</target> -<source>Please enter a target folder for versioning.</source> -<target>Bitte geben Sie einen Zielorder für die Versionierung ein.</target> - <source>Source folder %x not found.</source> <target>Der Quellordner %x wurde nicht gefunden.</target> +<source>Please enter a target folder for versioning.</source> +<target>Bitte geben Sie einen Zielorder für die Versionierung ein.</target> + <source>The following items have unresolved conflicts and will not be synchronized:</source> <target>Die folgenden Elemente haben ungelöste Konflikte und werden nicht synchronisiert werden:</target> @@ -555,9 +564,6 @@ Die Befehlszeile wird ausgelöst, wenn: <source>Synchronization completed successfully</source> <target>Synchronisation erfolgreich abgeschlossen</target> -<source>Saving log file %x...</source> -<target>Speichere Protokolldatei %x...</target> - <source>Stopped</source> <target>Unterbrochen</target> @@ -609,9 +615,6 @@ Die Befehlszeile wird ausgelöst, wenn: <source>FreeFileSync is up to date.</source> <target>FreeFileSync ist auf dem neuesten Stand.</target> -<source>Unable to connect to sourceforge.net.</source> -<target>Es kann keine Verbindung zu Sourceforge.net 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> @@ -837,23 +840,23 @@ Die Befehlszeile wird ausgelöst, wenn: <source>Maximum:</source> <target>Maximum:</target> -<source>C&lear</source> -<target>&Löschen</target> - <source>Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair.</source> <target>Wählen Sie Filterregeln aus, um einzelne Dateien von der Synchronisation auszuschließen. Geben Sie Dateipfade relativ zu ihrem zugehörigen Ordnerpaar an.</target> +<source>C&lear</source> +<target>&Löschen</target> + <source>Detect moved files</source> <target>Verschobene Dateien erkennen</target> <source> -- Requires and creates database files - Detection active after initial sync +- Requires and creates database files - Not supported by all file systems </source> <target> +- Erkennung nach erstmaliger Synchronisation aktiv. - Benötigt und erstellt Datenbankdateien. -- Erst nach einmaliger Synchronisation aktiv. - Wird nicht von allen Dateisystemen unterstützt. </target> @@ -1067,12 +1070,12 @@ Dadurch wird ein konsistenter Datenstand auch im schweren Fehlerfall garantiert. <source>View Settings</source> <target>Ansichtseinstellungen</target> -<source>Overview</source> -<target>Ãœbersicht</target> - <source>Configuration</source> <target>Konfiguration</target> +<source>Overview</source> +<target>Ãœbersicht</target> + <source>Main Bar</source> <target>Hauptleiste</target> @@ -1451,9 +1454,6 @@ Dadurch wird ein konsistenter Datenstand auch im schweren Fehlerfall garantiert. <source>Cannot monitor directory %x.</source> <target>Das Verzeichnis %x kann nicht überwacht werden.</target> -<source>Conversion error:</source> -<target>Fehler bei Konvertierung:</target> - <source>Cannot delete file %x.</source> <target>Die Datei %x kann nicht gelöscht werden.</target> @@ -1487,9 +1487,6 @@ Dadurch wird ein konsistenter Datenstand auch im schweren Fehlerfall garantiert. <source>Cannot create directory %x.</source> <target>Das Verzeichnis %x kann nicht erstellt werden.</target> -<source>Cannot create symbolic link %x.</source> -<target>Der Symbolische Link %x kann nicht erstellt werden.</target> - <source>Cannot find system function %x.</source> <target>Die Systemfunktion %x wurde nicht gefunden.</target> diff --git a/FreeFileSync/Build/Languages/norwegian.lng b/FreeFileSync/Build/Languages/norwegian.lng index e8fd452b..914184dc 100644 --- a/FreeFileSync/Build/Languages/norwegian.lng +++ b/FreeFileSync/Build/Languages/norwegian.lng @@ -7,12 +7,31 @@ <plural_definition>n == 1 ? 0 : 1</plural_definition> </header> +<source>Cannot copy symbolic link %x to %y.</source> +<target></target> + +<source> +- Detection active after initial sync +- Requires and creates database files +- Not supported by all file systems +</source> +<target></target> + <source>C&lear</source> <target></target> <source>Consider file times with specified offset as equal</source> <target></target> +<source>Unable to connect to freefilesync.org.</source> +<target></target> + +<source>Removing old log files exceeding limit...</source> +<target></target> + +<source>Open configuration for edit without executing.</source> +<target></target> + <source>Both sides have changed since last synchronization.</source> <target>Begge sider er endret siden siste synkronisering.</target> @@ -223,6 +242,9 @@ <source>%x GB</source> <target>%x GB</target> +<source>Cannot load file %x.</source> +<target>Kan ikke lese filen %x.</target> + <source>Database file %x is incompatible.</source> <target>Databasefilen %x er inkompatibel.</target> @@ -274,6 +296,9 @@ <source>Creating file %x</source> <target>Oppretter filen %x</target> +<source>Saving log file %x...</source> +<target>Lagrer rapport %x...</target> + <source>Items processed:</source> <target>Mapper behandlet:</target> @@ -301,9 +326,6 @@ <pluralform>%x trÃ¥der</pluralform> </target> -<source>Encoding extended time information: %x</source> -<target>Oppretter udvidet tidsinformasjon: %x</target> - <source>/sec</source> <target>/sek</target> @@ -325,9 +347,6 @@ <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> -<source>Cannot load file %x.</source> -<target>Kan ikke lese filen %x.</target> - <source>Cannot determine volume name for %x.</source> <target>Kan ikke bestemme volumnavn for %x.</target> @@ -504,21 +523,21 @@ Kommandoen utføres hvis: <source>Data verification error: %x and %y have different content.</source> <target>Godkjennelsesfeil: %x og %y har forskellig innhold</target> -<source>Cannot find folder %x.</source> -<target>Finner ikke mappen %x.</target> - <source>Target folder %x already existing.</source> <target>Destinasjonsmappen %x finnes allerede.</target> +<source>Cannot find folder %x.</source> +<target>Finner ikke mappen %x.</target> + <source>Target folder input field must not be empty.</source> <target>Destinasjonsmappen skal angis.</target> -<source>Please enter a target folder for versioning.</source> -<target>Angi mappe til versionering.</target> - <source>Source folder %x not found.</source> <target>Kildemappen %x ble ikke funnet.</target> +<source>Please enter a target folder for versioning.</source> +<target>Angi mappe til versionering.</target> + <source>The following items have unresolved conflicts and will not be synchronized:</source> <target>Følgende mapper har uløste konflikter og synkroniseres ikke:</target> @@ -561,9 +580,6 @@ Kommandoen utføres hvis: <source>Synchronization completed successfully</source> <target>Synkronisering gjennomført</target> -<source>Saving log file %x...</source> -<target>Lagrer rapport %x...</target> - <source>Stopped</source> <target>Avbrutt</target> @@ -615,9 +631,6 @@ Kommandoen utføres hvis: <source>FreeFileSync is up to date.</source> <target>FreeFileSync er oppdatert.</target> -<source>Unable to connect to sourceforge.net.</source> -<target>Kan ikke kontakte sourceforge.net.</target> - <source>Cannot find current FreeFileSync version number online. Do you want to check manually?</source> <target>Kunne ikke finne FreeFileSync's versjonsnummer online. Vil du kontrollere manuelt?</target> @@ -846,17 +859,6 @@ Kommandoen utføres hvis: <source>Detect moved files</source> <target>Gjennkjenn flyttede filer</target> -<source> -- Requires and creates database files -- Detection active after initial sync -- Not supported by all file systems -</source> -<target> -- Krever og oppretter databasefiler -- Gjennkjennelse aktiv etter første synk -- Understøtter ikke alle filsystemer -</target> - <source>Detect synchronization directions with the help of database files</source> <target>Gjennkjenn synkretninger ved hjelp av databasefiler</target> @@ -1064,12 +1066,12 @@ This guarantees a consistent state even in case of a serious error. <source>View Settings</source> <target>Visninger</target> -<source>Overview</source> -<target>Oversikt</target> - <source>Configuration</source> <target>Innstilling</target> +<source>Overview</source> +<target>Oversikt</target> + <source>Main Bar</source> <target>Hovedlinje</target> @@ -1448,9 +1450,6 @@ This guarantees a consistent state even in case of a serious error. <source>Cannot monitor directory %x.</source> <target>Kan ikke overvÃ¥ke mappen %x.</target> -<source>Conversion error:</source> -<target>Konverteringsfeil:</target> - <source>Cannot delete file %x.</source> <target>Kan ikke slette filen %x.</target> @@ -1484,9 +1483,6 @@ This guarantees a consistent state even in case of a serious error. <source>Cannot create directory %x.</source> <target>Kan ikke opprette mappen %x.</target> -<source>Cannot create symbolic link %x.</source> -<target>Kan ikke opprette symbolsk link %x.</target> - <source>Cannot find system function %x.</source> <target>Kan ikke finne systemfunksjonen %x.</target> diff --git a/FreeFileSync/Source/FreeFileSync.vcxproj b/FreeFileSync/Source/FreeFileSync.vcxproj index f8b130ad..0f469f34 100644 --- a/FreeFileSync/Source/FreeFileSync.vcxproj +++ b/FreeFileSync/Source/FreeFileSync.vcxproj @@ -208,7 +208,7 @@ <ClCompile Include="..\..\wx+\tooltip.cpp" /> <ClCompile Include="..\..\wx+\zlib_wrap.cpp" /> <ClCompile Include="..\..\zen\dst_hack.cpp" /> - <ClCompile Include="..\..\zen\file_handling.cpp" /> + <ClCompile Include="..\..\zen\file_access.cpp" /> <ClCompile Include="..\..\zen\file_io.cpp" /> <ClCompile Include="..\..\zen\file_traverser.cpp" /> <ClCompile Include="..\..\zen\format_unit.cpp" /> diff --git a/FreeFileSync/Source/Makefile b/FreeFileSync/Source/Makefile index ced7374a..f44202c6 100644 --- a/FreeFileSync/Source/Makefile +++ b/FreeFileSync/Source/Makefile @@ -69,7 +69,7 @@ CPP_LIST+=lib/versioning.cpp CPP_LIST+=lib/ffs_paths.cpp CPP_LIST+=../../zen/xml_io.cpp CPP_LIST+=../../zen/recycler.cpp -CPP_LIST+=../../zen/file_handling.cpp +CPP_LIST+=../../zen/file_access.cpp CPP_LIST+=../../zen/file_io.cpp CPP_LIST+=../../zen/file_traverser.cpp CPP_LIST+=../../zen/zstring.cpp diff --git a/FreeFileSync/Source/RealtimeSync/Makefile b/FreeFileSync/Source/RealtimeSync/Makefile index cd888bcf..4cdcb607 100644 --- a/FreeFileSync/Source/RealtimeSync/Makefile +++ b/FreeFileSync/Source/RealtimeSync/Makefile @@ -27,7 +27,7 @@ CPP_LIST+=../lib/resolve_path.cpp CPP_LIST+=../lib/ffs_paths.cpp CPP_LIST+=../../../zen/xml_io.cpp CPP_LIST+=../../../zen/dir_watcher.cpp -CPP_LIST+=../../../zen/file_handling.cpp +CPP_LIST+=../../../zen/file_access.cpp CPP_LIST+=../../../zen/file_io.cpp CPP_LIST+=../../../zen/file_traverser.cpp CPP_LIST+=../../../zen/zstring.cpp diff --git a/FreeFileSync/Source/RealtimeSync/RealtimeSync.vcxproj b/FreeFileSync/Source/RealtimeSync/RealtimeSync.vcxproj index fefe060a..adcc161d 100644 --- a/FreeFileSync/Source/RealtimeSync/RealtimeSync.vcxproj +++ b/FreeFileSync/Source/RealtimeSync/RealtimeSync.vcxproj @@ -210,7 +210,7 @@ <ClCompile Include="..\..\..\zen\debug_memory_leaks.cpp" /> <ClCompile Include="..\..\..\zen\dir_watcher.cpp" /> <ClCompile Include="..\..\..\zen\dst_hack.cpp" /> - <ClCompile Include="..\..\..\zen\file_handling.cpp" /> + <ClCompile Include="..\..\..\zen\file_access.cpp" /> <ClCompile Include="..\..\..\zen\file_io.cpp" /> <ClCompile Include="..\..\..\zen\file_traverser.cpp" /> <ClCompile Include="..\..\..\zen\format_unit.cpp" /> diff --git a/FreeFileSync/Source/RealtimeSync/application.cpp b/FreeFileSync/Source/RealtimeSync/application.cpp index 068a7cef..85c89f6b 100644 --- a/FreeFileSync/Source/RealtimeSync/application.cpp +++ b/FreeFileSync/Source/RealtimeSync/application.cpp @@ -6,7 +6,7 @@ #include "application.h" #include "main_dlg.h" -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/thread.h> #include <zen/dll.h> #include <wx/event.h> @@ -70,7 +70,7 @@ bool Application::OnInit() //SEM_FAILCRITICALERRORS at startup. This is to prevent error mode dialogs from hanging the application." ::SetErrorMode(SEM_FAILCRITICALERRORS); - setAppUserModeId(L"RealtimeSync", L"SourceForge.RealtimeSync"); //noexcept + setAppUserModeId(L"RealtimeSync", L"Zenju.RealtimeSync"); //noexcept //consider: RealtimeSync.exe, RealtimeSync_Win32.exe, RealtimeSync_x64.exe wxToolTip::SetMaxWidth(-1); //disable tooltip wrapping -> Windows only diff --git a/FreeFileSync/Source/RealtimeSync/application.h b/FreeFileSync/Source/RealtimeSync/application.h index 3752f824..90180d23 100644 --- a/FreeFileSync/Source/RealtimeSync/application.h +++ b/FreeFileSync/Source/RealtimeSync/application.h @@ -12,15 +12,15 @@ class Application : public wxApp { public: - virtual bool OnInit(); - virtual int OnExit(); - virtual int OnRun(); - virtual bool OnExceptionInMainLoop() { throw; } //just re-throw and avoid display of additional messagebox: it will be caught in OnRun() + bool OnInit() override; + int OnExit() override; + int OnRun () override; + bool OnExceptionInMainLoop() override { throw; } //just re-throw and avoid display of additional messagebox: it will be caught in OnRun() void onQueryEndSession(wxEvent& event); private: void onEnterEventLoop(wxEvent& event); - //virtual wxLayoutDirection GetLayoutDirection() const { return wxLayout_LeftToRight; } + //wxLayoutDirection GetLayoutDirection() const override { return wxLayout_LeftToRight; } }; #endif // REALTIMESYNCAPP_H diff --git a/FreeFileSync/Source/RealtimeSync/main_dlg.cpp b/FreeFileSync/Source/RealtimeSync/main_dlg.cpp index 934e9215..121f5486 100644 --- a/FreeFileSync/Source/RealtimeSync/main_dlg.cpp +++ b/FreeFileSync/Source/RealtimeSync/main_dlg.cpp @@ -12,8 +12,7 @@ #include <wx+/font_size.h> #include <wx+/popup_dlg.h> #include <wx+/image_resources.h> -#include <zen/assert_static.h> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/build_info.h> #include "xml_proc.h" #include "tray_menu.h" @@ -93,7 +92,7 @@ MainDialog::MainDialog(wxDialog* dlg, const Zstring& cfgFileName) Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::OnKeyPressed), nullptr, this); //prepare drag & drop - dirpathFirst.reset(new DirectoryName<wxTextCtrl>(*m_panelMainFolder, *m_buttonSelectDirMain, *m_txtCtrlDirectoryMain, m_staticTextFinalPath)); + dirpathFirst = zen::make_unique<DirectoryName<wxTextCtrl>>(*m_panelMainFolder, *m_buttonSelectDirMain, *m_txtCtrlDirectoryMain, m_staticTextFinalPath); //--------------------------- load config values ------------------------------------ xmlAccess::XmlRealConfig newConfig; @@ -202,7 +201,7 @@ void MainDialog::OnMenuAbout(wxCommandEvent& event) #endif build += zen::is64BitBuild ? L" x64" : L" x86"; - assert_static(zen::is32BitBuild || zen::is64BitBuild); + static_assert(zen::is32BitBuild || zen::is64BitBuild, ""); showNotificationDialog(this, DialogInfoType::INFO, PopupDialogCfg(). setTitle(_("About")). diff --git a/FreeFileSync/Source/RealtimeSync/main_dlg.h b/FreeFileSync/Source/RealtimeSync/main_dlg.h index d70aac27..b77ee045 100644 --- a/FreeFileSync/Source/RealtimeSync/main_dlg.h +++ b/FreeFileSync/Source/RealtimeSync/main_dlg.h @@ -36,17 +36,17 @@ private: void loadConfig(const Zstring& filepath); - virtual void OnClose (wxCloseEvent& event) { Destroy(); } - virtual void OnShowHelp (wxCommandEvent& event); - virtual void OnMenuAbout (wxCommandEvent& event); - virtual void OnAddFolder (wxCommandEvent& event); - virtual void OnRemoveFolder (wxCommandEvent& event); - virtual void OnRemoveTopFolder(wxCommandEvent& event); - virtual void OnKeyPressed (wxKeyEvent& event); - virtual void OnStart (wxCommandEvent& event); - virtual void OnConfigSave (wxCommandEvent& event); - virtual void OnConfigLoad (wxCommandEvent& event); - virtual void OnMenuQuit (wxCommandEvent& event) { Close(); } + void OnClose (wxCloseEvent& event ) override { Destroy(); } + void OnShowHelp (wxCommandEvent& event) override; + void OnMenuAbout (wxCommandEvent& event) override; + void OnAddFolder (wxCommandEvent& event) override; + void OnRemoveFolder (wxCommandEvent& event); + void OnRemoveTopFolder(wxCommandEvent& event) override; + void OnKeyPressed (wxKeyEvent& event); + void OnStart (wxCommandEvent& event) override; + void OnConfigSave (wxCommandEvent& event) override; + void OnConfigLoad (wxCommandEvent& event) override; + void OnMenuQuit (wxCommandEvent& event) override { Close(); } void onFilesDropped(zen::FileDropEvent& event); void setConfiguration(const xmlAccess::XmlRealConfig& cfg); diff --git a/FreeFileSync/Source/RealtimeSync/monitor.cpp b/FreeFileSync/Source/RealtimeSync/monitor.cpp index b8cd57e8..4c17467e 100644 --- a/FreeFileSync/Source/RealtimeSync/monitor.cpp +++ b/FreeFileSync/Source/RealtimeSync/monitor.cpp @@ -7,7 +7,7 @@ #include "monitor.h" #include <ctime> #include <set> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/dir_watcher.h> #include <zen/thread.h> #include <zen/tick_count.h> @@ -75,7 +75,7 @@ WaitResult waitForChanges(const std::vector<Zstring>& dirpathPhrases, //throw Fi if (!ftDirExists.get()) return WaitResult(dirpathFmt); - watches.push_back(std::make_pair(dirpathFmt, std::make_shared<DirWatcher>(dirpathFmt))); //throw FileError + watches.emplace_back(dirpathFmt, std::make_shared<DirWatcher>(dirpathFmt)); //throw FileError } catch (FileError&) { @@ -171,7 +171,7 @@ void waitForMissingDirs(const std::vector<Zstring>& dirpathPhrases, //throw File allExisting = false; //wait some time... const int refreshInterval = rts::UI_UPDATE_INTERVAL / 2; - assert_static(CHECK_DIR_INTERVAL * 1000 % refreshInterval == 0); + static_assert(CHECK_DIR_INTERVAL * 1000 % refreshInterval == 0, ""); for (int i = 0; i < CHECK_DIR_INTERVAL * 1000 / refreshInterval; ++i) { onRefreshGui(dirpathFmt); //may throw! diff --git a/FreeFileSync/Source/RealtimeSync/monitor.h b/FreeFileSync/Source/RealtimeSync/monitor.h index 5fd8fb4b..77fe4740 100644 --- a/FreeFileSync/Source/RealtimeSync/monitor.h +++ b/FreeFileSync/Source/RealtimeSync/monitor.h @@ -25,8 +25,8 @@ struct MonitorCallback MONITOR_PHASE_WAITING, }; virtual void setPhase(WatchPhase mode) = 0; - virtual void executeExternalCommand() = 0; - virtual void requestUiRefresh() = 0; + virtual void executeExternalCommand () = 0; + virtual void requestUiRefresh () = 0; virtual void reportError(const std::wstring& msg) = 0; //automatically retries after return! }; void monitorDirectories(const std::vector<Zstring>& dirpathPhrases, diff --git a/FreeFileSync/Source/RealtimeSync/tray_menu.cpp b/FreeFileSync/Source/RealtimeSync/tray_menu.cpp index 7cf1919f..2a59902f 100644 --- a/FreeFileSync/Source/RealtimeSync/tray_menu.cpp +++ b/FreeFileSync/Source/RealtimeSync/tray_menu.cpp @@ -122,7 +122,7 @@ private: CONTEXT_ABORT = wxID_EXIT }; - virtual wxMenu* CreatePopupMenu() + wxMenu* CreatePopupMenu() override { wxMenu* contextMenu = new wxMenu; @@ -268,7 +268,7 @@ rts::AbortReason rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& conf MonitorCallbackImpl(const wxString& jobname, const Zstring& cmdLine) : trayIcon(jobname), cmdLine_(cmdLine) {} - virtual void setPhase(WatchPhase mode) + void setPhase(WatchPhase mode) override { switch (mode) { @@ -281,12 +281,12 @@ rts::AbortReason rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& conf } } - virtual void executeExternalCommand() + void executeExternalCommand() override { auto cmdLineExp = expandMacros(cmdLine_); try { - shellExecute2(cmdLineExp, EXEC_TYPE_SYNC); //throw FileError + shellExecute(cmdLineExp, EXEC_TYPE_SYNC); //throw FileError } catch (const FileError& e) { @@ -294,19 +294,19 @@ rts::AbortReason rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& conf } } - virtual void requestUiRefresh() + void requestUiRefresh() override { if (updateUiIsAllowed()) trayIcon.doUiRefreshNow(); //throw AbortMonitoring } - virtual void reportError(const std::wstring& msg) + void reportError(const std::wstring& msg) override { trayIcon.setMode(TRAY_MODE_ERROR); trayIcon.clearShowErrorRequested(); //wait for some time, then return to retry - assert_static(15 * 1000 % UI_UPDATE_INTERVAL == 0); + static_assert(15 * 1000 % UI_UPDATE_INTERVAL == 0, ""); for (int i = 0; i < 15 * 1000 / UI_UPDATE_INTERVAL; ++i) { trayIcon.doUiRefreshNow(); //throw AbortMonitoring diff --git a/FreeFileSync/Source/RealtimeSync/xml_proc.cpp b/FreeFileSync/Source/RealtimeSync/xml_proc.cpp index 3457f8f2..04edbf86 100644 --- a/FreeFileSync/Source/RealtimeSync/xml_proc.cpp +++ b/FreeFileSync/Source/RealtimeSync/xml_proc.cpp @@ -5,7 +5,7 @@ // ************************************************************************** #include "xml_proc.h" -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <wx/filefn.h> #include <wx+/string_conv.h> #include "../lib/process_xml.h" diff --git a/FreeFileSync/Source/algorithm.cpp b/FreeFileSync/Source/algorithm.cpp index b5791f90..37f627ee 100644 --- a/FreeFileSync/Source/algorithm.cpp +++ b/FreeFileSync/Source/algorithm.cpp @@ -6,8 +6,9 @@ #include "algorithm.h" #include <set> +#include <unordered_map> #include <stdexcept> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/recycler.h> #include <zen/stl_tools.h> #include <zen/scope_guard.h> @@ -336,7 +337,7 @@ private: { if (fileObj.getFileId<LEFT_SIDE>() != FileId()) { - auto rv = exLeftOnly.insert(std::make_pair(fileObj.getFileId<LEFT_SIDE>(), &fileObj)); + auto rv = exLeftOnly.emplace(fileObj.getFileId<LEFT_SIDE>(), &fileObj); assert(rv.second); if (!rv.second) //duplicate file ID! rv.first->second = nullptr; @@ -346,7 +347,7 @@ private: { if (fileObj.getFileId<RIGHT_SIDE>() != FileId()) { - auto rv = exRightOnly.insert(std::make_pair(fileObj.getFileId<RIGHT_SIDE>(), &fileObj)); + auto rv = exRightOnly.emplace(fileObj.getFileId<RIGHT_SIDE>(), &fileObj); assert(rv.second); if (!rv.second) //duplicate file ID! rv.first->second = nullptr; @@ -728,15 +729,15 @@ void zen::setSyncDirectionRec(SyncDirection newDirection, FileSystemObject& fsOb struct Recurse: public FSObjectVisitor { Recurse(SyncDirection newDir) : newDir_(newDir) {} - virtual void visit(const FilePair& fileObj) + void visit(const FilePair& fileObj) override { SetNewDirection::execute(const_cast<FilePair&>(fileObj), newDir_); //phyiscal object is not const in this method anyway } - virtual void visit(const SymlinkPair& linkObj) + void visit(const SymlinkPair& linkObj) override { SetNewDirection::execute(const_cast<SymlinkPair&>(linkObj), newDir_); // } - virtual void visit(const DirPair& dirObj) + void visit(const DirPair& dirObj) override { SetNewDirection::execute(const_cast<DirPair&>(dirObj), newDir_); // } @@ -783,9 +784,9 @@ void zen::setActiveStatus(bool newStatus, zen::FileSystemObject& fsObj) struct Recurse: public FSObjectVisitor { Recurse(bool newStat) : newStatus_(newStat) {} - virtual void visit(const FilePair& fileObj) {} - virtual void visit(const SymlinkPair& linkObj) {} - virtual void visit(const DirPair& dirObj) + void visit(const FilePair& fileObj) override {} + void visit(const SymlinkPair& linkObj) override {} + void visit(const DirPair& dirObj) override { if (newStatus_) inOrExcludeAllRows<true>(const_cast<DirPair&>(dirObj)); //object is not physically const here anyway @@ -1164,7 +1165,7 @@ void categorize(const std::set<FileSystemObject*>& rowsIn, recExists = recycleBinExists(baseDirPf, [&] { callback.reportStatus(msg); /*may throw*/ }); //throw FileError }, callback); - hasRecyclerBuffer.insert(std::make_pair(baseDirPf, recExists)); + hasRecyclerBuffer.emplace(baseDirPf, recExists); return recExists; #elif defined ZEN_LINUX || defined ZEN_MAC @@ -1203,7 +1204,7 @@ struct ItemDeleter : public FSObjectVisitor //throw FileError, but nothrow cons } } - virtual void visit(const FilePair& fileObj) + void visit(const FilePair& fileObj) override { notifyFileDeletion(fileObj.getFullPath<side>()); @@ -1213,7 +1214,7 @@ struct ItemDeleter : public FSObjectVisitor //throw FileError, but nothrow cons zen::removeFile(fileObj.getFullPath<side>()); //throw FileError } - virtual void visit(const SymlinkPair& linkObj) + void visit(const SymlinkPair& linkObj) override { notifySymlinkDeletion(linkObj.getFullPath<side>()); @@ -1228,7 +1229,7 @@ struct ItemDeleter : public FSObjectVisitor //throw FileError, but nothrow cons } } - virtual void visit(const DirPair& dirObj) + void visit(const DirPair& dirObj) override { notifyDirectoryDeletion(dirObj.getFullPath<side>()); //notfied twice; see below -> no big deal @@ -1293,7 +1294,7 @@ void zen::deleteFromGridAndHD(const std::vector<FileSystemObject*>& rowsToDelete throw std::logic_error("Programming Error: Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__)); //build up mapping from base directory to corresponding direction config - hash_map<const BaseDirPair*, DirectionConfig> baseDirCfgs; + std::unordered_map<const BaseDirPair*, DirectionConfig> baseDirCfgs; for (auto it = folderCmp.begin(); it != folderCmp.end(); ++it) baseDirCfgs[&** it] = directCfgs[it - folderCmp.begin()]; diff --git a/FreeFileSync/Source/application.cpp b/FreeFileSync/Source/application.cpp index 9056d962..3ca0c53c 100644 --- a/FreeFileSync/Source/application.cpp +++ b/FreeFileSync/Source/application.cpp @@ -6,7 +6,7 @@ #include "application.h" #include <memory> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/dll.h> #include <wx/tooltip.h> #include <wx/log.h> @@ -102,7 +102,7 @@ std::vector<Zstring> getCommandlineArgs(const wxApp& app) { if (iterStart != cmdLine.end()) { - args.push_back(Zstring(iterStart, it)); + args.emplace_back(iterStart, it); iterStart = cmdLine.end(); //expect consecutive blanks! } } @@ -120,7 +120,7 @@ std::vector<Zstring> getCommandlineArgs(const wxApp& app) } } if (iterStart != cmdLine.end()) - args.push_back(Zstring(iterStart, cmdLine.end())); + args.emplace_back(iterStart, cmdLine.end()); if (!args.empty()) args.erase(args.begin()); //remove first argument which is exe path by convention: http://blogs.msdn.com/b/oldnewthing/archive/2006/05/15/597984.aspx @@ -155,7 +155,7 @@ bool Application::OnInit() //SEM_FAILCRITICALERRORS at startup. This is to prevent error mode dialogs from hanging the application." ::SetErrorMode(SEM_FAILCRITICALERRORS); - setAppUserModeId(L"FreeFileSync", L"SourceForge.FreeFileSync"); //noexcept + setAppUserModeId(L"FreeFileSync", L"Zenju.FreeFileSync"); //noexcept //consider: FreeFileSync.exe, FreeFileSync_Win32.exe, FreeFileSync_x64.exe wxToolTip::SetMaxWidth(-1); //disable tooltip wrapping -> Windows only @@ -270,7 +270,7 @@ void Application::onQueryEndSession(wxEvent& event) void runGuiMode (const Zstring& globalConfigFile); -void runGuiMode (const Zstring& globalConfigFile, const XmlGuiConfig& guiCfg, const std::vector<Zstring>& referenceFiles); +void runGuiMode (const Zstring& globalConfigFile, const XmlGuiConfig& guiCfg, const std::vector<Zstring>& referenceFiles, bool startComparison); void runBatchMode(const Zstring& globalConfigFile, const XmlBatchConfig& batchCfg, const Zstring& referenceFile, FfsReturnCode& returnCode); void showSyntaxHelp(); @@ -294,28 +294,36 @@ void Application::launch(const std::vector<Zstring>& commandArgs) raiseReturnCode(returnCode, FFS_RC_ABORTED); }; + auto equalNoCase = [](const Zstring& lhs, const Zstring& rhs) { return utfCvrtTo<wxString>(lhs).CmpNoCase(utfCvrtTo<wxString>(rhs)) == 0; }; + //parse command line arguments std::vector<Zstring> leftDirs; std::vector<Zstring> rightDirs; std::vector<std::pair<Zstring, XmlType>> configFiles; //XmlType: batch or GUI files only Opt<Zstring> globalConfigFile; + bool openForEdit = false; { + const Zchar optionEdit [] = Zstr("-edit"); const Zchar optionLeftDir [] = Zstr("-leftdir"); const Zchar optionRightDir[] = Zstr("-rightdir"); - auto syntaxHelpRequested = [](const Zstring& arg) + auto syntaxHelpRequested = [&](const Zstring& arg) { auto it = std::find_if(arg.begin(), arg.end(), [](Zchar c) { return c != Zchar('/') && c != Zchar('-'); }); + if (it == arg.begin()) return false; //require at least one prefix character + const Zstring argTmp(it, arg.end()); - return argTmp == Zstr("help") || - argTmp == Zstr("h") || + return equalNoCase(argTmp, Zstr("help")) || + equalNoCase(argTmp, Zstr("h")) || argTmp == Zstr("?"); }; for (auto it = commandArgs.begin(); it != commandArgs.end(); ++it) if (syntaxHelpRequested(*it)) return showSyntaxHelp(); - else if (*it == optionLeftDir) + else if (equalNoCase(*it, optionEdit)) + openForEdit = true; + else if (equalNoCase(*it, optionLeftDir)) { if (++it == commandArgs.end()) { @@ -324,7 +332,7 @@ void Application::launch(const std::vector<Zstring>& commandArgs) } leftDirs.push_back(*it); } - else if (*it == optionRightDir) + else if (equalNoCase(*it, optionRightDir)) { if (++it == commandArgs.end()) { @@ -356,10 +364,10 @@ void Application::launch(const std::vector<Zstring>& commandArgs) switch (getXmlType(filepath)) //throw FileError { case XML_TYPE_GUI: - configFiles.push_back(std::make_pair(filepath, XML_TYPE_GUI)); + configFiles.emplace_back(filepath, XML_TYPE_GUI); break; case XML_TYPE_BATCH: - configFiles.push_back(std::make_pair(filepath, XML_TYPE_BATCH)); + configFiles.emplace_back(filepath, XML_TYPE_BATCH); break; case XML_TYPE_GLOBAL: globalConfigFile = filepath; @@ -409,9 +417,8 @@ void Application::launch(const std::vector<Zstring>& commandArgs) mainCfg.firstPair.dirpathPhraseRight = rightDirs[0]; } else - mainCfg.additionalPairs.push_back(FolderPairEnh(leftDirs [i], - rightDirs[i], - nullptr, nullptr, FilterConfig())); + mainCfg.additionalPairs.emplace_back(leftDirs[i], rightDirs[i], + nullptr, nullptr, FilterConfig()); } return true; }; @@ -433,7 +440,7 @@ void Application::launch(const std::vector<Zstring>& commandArgs) if (!replaceDirectories(guiCfg.mainCfg)) return; - runGuiMode(globalConfigFilePath, guiCfg, std::vector<Zstring>()); + runGuiMode(globalConfigFilePath, guiCfg, std::vector<Zstring>(), !openForEdit); } } else if (configFiles.size() == 1) @@ -441,7 +448,7 @@ void Application::launch(const std::vector<Zstring>& commandArgs) const Zstring filepath = configFiles[0].first; //batch mode - if (configFiles[0].second == XML_TYPE_BATCH) + if (configFiles[0].second == XML_TYPE_BATCH && !openForEdit) { XmlBatchConfig batchCfg; try @@ -461,14 +468,14 @@ void Application::launch(const std::vector<Zstring>& commandArgs) return; runBatchMode(globalConfigFilePath, batchCfg, filepath, returnCode); } - //GUI mode: single config + //GUI mode: single config (ffs_gui *or* ffs_batch) else { XmlGuiConfig guiCfg; try { std::wstring warningMsg; - readConfig(filepath, guiCfg, warningMsg); //throw FileError + readAnyConfig({ filepath }, guiCfg, warningMsg); //throw FileError if (!warningMsg.empty()) showNotificationDialog(nullptr, DialogInfoType::WARNING, PopupDialogCfg().setDetailInstructions(warningMsg)); @@ -484,7 +491,7 @@ void Application::launch(const std::vector<Zstring>& commandArgs) //what about simulating changed config due to directory replacement? //-> propably fine to not show as changed on GUI and not ask user to save on exit! - runGuiMode(globalConfigFilePath, guiCfg, { filepath }); //caveat: guiCfg and filepath do not match if directories were set/replaced via command line! + runGuiMode(globalConfigFilePath, guiCfg, { filepath }, !openForEdit); //caveat: guiCfg and filepath do not match if directories were set/replaced via command line! } } //gui mode: merged configs @@ -515,7 +522,7 @@ void Application::launch(const std::vector<Zstring>& commandArgs) notifyError(e.toString(), std::wstring()); return; } - runGuiMode(globalConfigFilePath, guiCfg, filepaths); + runGuiMode(globalConfigFilePath, guiCfg, filepaths, !openForEdit); } } @@ -525,9 +532,10 @@ void runGuiMode(const Zstring& globalConfigFile) { MainDialog::create(globalConf void runGuiMode(const Zstring& globalConfigFile, const xmlAccess::XmlGuiConfig& guiCfg, - const std::vector<Zstring>& referenceFiles) + const std::vector<Zstring>& referenceFiles, + bool startComparison) { - MainDialog::create(globalConfigFile, nullptr, guiCfg, referenceFiles, /*bool startComparison = */true); + MainDialog::create(globalConfigFile, nullptr, guiCfg, referenceFiles, startComparison); } @@ -538,18 +546,22 @@ void showSyntaxHelp() setDetailInstructions(_("Syntax:") + L"\n\n" + L"FreeFileSync.exe " + L"\n" + - L" [" + _("global config file:") + L" GlobalSettings.xml]\n" + - L" [" + _("config files:") + L" *.ffs_gui/*.ffs_batch]\n" + - L" [-leftdir " + _("directory") + L"] [-rightdir " + _("directory") + L"]" + L"\n\n" + + L" [" + _("global config file:") + L" GlobalSettings.xml]" + L"\n" + + L" [" + _("config files:") + L" *.ffs_gui/*.ffs_batch]" + L"\n" + + L" [-LeftDir " + _("directory") + L"] [-RightDir " + _("directory") + L"]" + L"\n" + + L" [-Edit]" + L"\n\n" + _("global config file:") + L"\n" + _("Path to an alternate GlobalSettings.xml file.") + L"\n\n" + _("config files:") + L"\n" + - _("Any number of FreeFileSync .ffs_gui and/or .ffs_batch configuration files.") + L"\n\n" + _("Any number of FreeFileSync .ffs_gui and/or .ffs_batch configuration files.") + L"\n\n" + + + L"-LeftDir " + _("directory") + L" -RightDir " + _("directory") + L"\n" + + _("Any number of alternative directory pairs for at most one config file.") + L"\n\n" + - L"-leftdir " + _("directory") + L" -rightdir " + _("directory") + L"\n" + - _("Any number of alternative directory pairs for at most one config file."))); + L"-Edit" + L"\n" + + _("Open configuration for edit without executing."))); } diff --git a/FreeFileSync/Source/application.h b/FreeFileSync/Source/application.h index defc1e17..ce0284e8 100644 --- a/FreeFileSync/Source/application.h +++ b/FreeFileSync/Source/application.h @@ -19,10 +19,10 @@ public: Application() : returnCode(zen::FFS_RC_SUCCESS) {} private: - virtual bool OnInit(); - virtual int OnExit(); - virtual int OnRun(); - virtual bool OnExceptionInMainLoop() { throw; } //just re-throw and avoid display of additional messagebox: it will be caught in OnRun() + bool OnInit() override; + int OnExit() override; + int OnRun() override; + bool OnExceptionInMainLoop() override { throw; } //just re-throw and avoid display of additional messagebox: it will be caught in OnRun() void onEnterEventLoop(wxEvent& event); void onQueryEndSession(wxEvent& event); diff --git a/FreeFileSync/Source/comparison.cpp b/FreeFileSync/Source/comparison.cpp index e4495802..08d5ee71 100644 --- a/FreeFileSync/Source/comparison.cpp +++ b/FreeFileSync/Source/comparison.cpp @@ -69,9 +69,8 @@ std::vector<ResolvedFolderPair> resolveDirectoryNames(const std::vector<FolderPa std::vector<ResolvedFolderPair> output; for (const FolderPairCfg& fpCfg : cfgList) - output.push_back(ResolvedFolderPair( - getFormattedDirectoryPath(fpCfg.dirpathPhraseLeft), - getFormattedDirectoryPath(fpCfg.dirpathPhraseRight))); + output.emplace_back(getFormattedDirectoryPath(fpCfg.dirpathPhraseLeft), + getFormattedDirectoryPath(fpCfg.dirpathPhraseRight)); warn_static("get volume by name for idle HDD! => call async getFormattedDirectoryPath, but currently not thread-safe") return output; } @@ -142,7 +141,7 @@ void checkFolderDependency(const std::vector<ResolvedFolderPair>& folderPairs, b { std::vector<std::pair<Zstring, Zstring>> dependentDirs; - auto areDependent = [](const Zstring& lhs, const Zstring& rhs) + auto havePathDependency = [](const Zstring& lhs, const Zstring& rhs) { return EqualFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())), //note: this is NOT an equivalence relation! Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length()))); @@ -151,8 +150,8 @@ void checkFolderDependency(const std::vector<ResolvedFolderPair>& folderPairs, b for (const ResolvedFolderPair& fp : folderPairs) if (!fp.dirpathLeft.empty() && !fp.dirpathRight.empty()) //empty folders names may be accepted by user { - if (areDependent(fp.dirpathLeft, fp.dirpathRight)) //test wheter leftDirectory begins with rightDirectory or the other way round - dependentDirs.push_back(std::make_pair(fp.dirpathLeft, fp.dirpathRight)); + if (havePathDependency(fp.dirpathLeft, fp.dirpathRight)) //test wheter leftDirectory begins with rightDirectory or the other way round + dependentDirs.emplace_back(fp.dirpathLeft, fp.dirpathRight); } if (!dependentDirs.empty()) @@ -201,7 +200,7 @@ ComparisonBuffer::ComparisonBuffer(const std::set<DirectoryKey>& keysToRead, Pro callback_(pcb), itemsReported(0) {} - virtual void reportStatus(const std::wstring& statusMsg, int itemsTotal) + void reportStatus(const std::wstring& statusMsg, int itemsTotal) override { callback_.updateProcessedData(itemsTotal - itemsReported, 0); //processed bytes are reported in subfunctions! itemsReported = itemsTotal; @@ -210,7 +209,7 @@ ComparisonBuffer::ComparisonBuffer(const std::set<DirectoryKey>& keysToRead, Pro //callback_.requestUiRefresh(); //already called by reportStatus() } - virtual HandleError reportError(const std::wstring& msg, size_t retryNumber) + HandleError reportError(const std::wstring& msg, size_t retryNumber) override { switch (callback_.reportError(msg, retryNumber)) { @@ -808,11 +807,11 @@ void zen::compare(xmlAccess::OptionalDialogs& warnings, std::vector<std::pair<ResolvedFolderPair, FolderPairCfg>> totalWorkLoad; for (size_t i = 0; i < cfgList.size(); ++i) - totalWorkLoad.push_back(std::make_pair(resInfo.resolvedPairs[i], cfgList[i])); + totalWorkLoad.emplace_back(resInfo.resolvedPairs[i], cfgList[i]); //lock (existing) directories before comparison if (createDirLocks) - dirLocks = make_unique<LockHolder>(resInfo.existingDirs, warnings.warningDirectoryLockFailed, callback); + dirLocks = zen::make_unique<LockHolder>(resInfo.existingDirs, warnings.warningDirectoryLockFailed, callback); try { @@ -822,9 +821,9 @@ void zen::compare(xmlAccess::OptionalDialogs& warnings, for (const auto& w : totalWorkLoad) { if (dirAvailable(w.first.dirpathLeft)) //only traverse *currently existing* directories: at this point user is aware that non-ex + empty string are seen as empty folder! - dirsToRead.insert(DirectoryKey(w.first.dirpathLeft, w.second.filter.nameFilter, w.second.handleSymlinks)); + dirsToRead.emplace(w.first.dirpathLeft, w.second.filter.nameFilter, w.second.handleSymlinks); if (dirAvailable(w.first.dirpathRight)) - dirsToRead.insert(DirectoryKey(w.first.dirpathRight, w.second.filter.nameFilter, w.second.handleSymlinks)); + dirsToRead.emplace(w.first.dirpathRight, w.second.filter.nameFilter, w.second.handleSymlinks); } FolderComparison outputTmp; //write to output as a transaction! diff --git a/FreeFileSync/Source/file_hierarchy.h b/FreeFileSync/Source/file_hierarchy.h index d4e92cde..1468750e 100644 --- a/FreeFileSync/Source/file_hierarchy.h +++ b/FreeFileSync/Source/file_hierarchy.h @@ -12,6 +12,7 @@ #include <string> #include <memory> #include <functional> +#include <unordered_set> #include <zen/zstring.h> #include <zen/fixed_list.h> #include <zen/stl_tools.h> @@ -77,14 +78,14 @@ template <> struct SelectParam<LEFT_SIDE> { template <class T> - static T& get(T& left, T& right) { return left; } + static T& ref(T& left, T& right) { return left; } }; template <> struct SelectParam<RIGHT_SIDE> { template <class T> - static T& get(T& left, T& right) { return right; } + static T& ref(T& left, T& right) { return right; } }; @@ -96,18 +97,11 @@ class FileSystemObject; //------------------------------------------------------------------ -/* -ERD: - DirContainer 1 --> 0..n DirContainer - DirContainer 1 --> 0..n FileDescriptor - DirContainer 1 --> 0..n LinkDescriptor -*/ - struct DirContainer { //------------------------------------------------------------------ typedef std::map<Zstring, DirContainer, LessFilename> DirList; // - typedef std::map<Zstring, FileDescriptor, LessFilename> FileList; //key: shortName + typedef std::map<Zstring, FileDescriptor, LessFilename> FileList; //key: file name typedef std::map<Zstring, LinkDescriptor, LessFilename> LinkList; // //------------------------------------------------------------------ @@ -118,19 +112,18 @@ struct DirContainer //convenience DirContainer& addSubDir(const Zstring& shortName) { - //use C++11 emplace when available return dirs[shortName]; //value default-construction is okay here - //return dirs.insert(std::make_pair(shortName, DirContainer())).first->second; + //return dirs.emplace(shortName, DirContainer()).first->second; } void addSubFile(const Zstring& shortName, const FileDescriptor& fileData) { - files.insert(std::make_pair(shortName, fileData)); + files.emplace(shortName, fileData); } void addSubLink(const Zstring& shortName, const LinkDescriptor& linkData) { - links.insert(std::make_pair(shortName, linkData)); + links.emplace(shortName, linkData); } }; @@ -142,8 +135,8 @@ struct DirContainer | FileSystemObject HierarchyObject /|\ /|\ - _______________|______________ ______|______ - | | | | | + _______________|_______________ ______|______ + | | | | | SymlinkPair FilePair DirPair BaseDirPair ------------------------------------------------------------------*/ @@ -212,7 +205,7 @@ protected: void removeEmptyRec(); private: - virtual void notifySyncCfgChanged() {} + virtual void notifySyncCfgChanged() {}; HierarchyObject (const HierarchyObject&) = delete; //this class is referenced by it's child elements => make it non-copyable/movable! HierarchyObject& operator=(const HierarchyObject&) = delete; @@ -264,12 +257,9 @@ public: int getFileTimeTolerance() const { return fileTimeTolerance_; } unsigned int getTimeShift() const { return optTimeShiftHours_; } - virtual void flip(); + void flip() override; private: - BaseDirPair (const BaseDirPair&) = delete; //this class is referenced by HierarchyObject => make it non-copyable/movable! - BaseDirPair& operator=(const BaseDirPair&) = delete; - const HardFilter::FilterRef filter_; //filter used while scanning directory: represents sub-view of actual files! const CompareVariant cmpVar_; const int fileTimeTolerance_; @@ -321,9 +311,8 @@ DerefIter<typename FolderComparison::const_iterator, const BaseDirPair> inline b DerefIter<typename FolderComparison::const_iterator, const BaseDirPair> inline end (const FolderComparison& vect) { return vect.end (); } //------------------------------------------------------------------ -class FSObjectVisitor +struct FSObjectVisitor { -public: virtual ~FSObjectVisitor() {} virtual void visit(const FilePair& fileObj) = 0; virtual void visit(const SymlinkPair& linkObj) = 0; @@ -357,7 +346,7 @@ private: ObjectMgr (const ObjectMgr& rhs) = delete; ObjectMgr& operator=(const ObjectMgr& rhs) = delete; //it's not well-defined what copying an objects means regarding object-identity in this context - static hash_set<const ObjectMgr*>& activeObjects() { static hash_set<const ObjectMgr*> inst; return inst; } //external linkage (even in header file!) + static std::unordered_set<const ObjectMgr*>& activeObjects() { static std::unordered_set<const ObjectMgr*> inst; return inst; } //external linkage (even in header file!) }; //------------------------------------------------------------------ @@ -431,6 +420,9 @@ protected: void setSynced(const Zstring& shortName); private: + FileSystemObject (const FileSystemObject&) = delete; + FileSystemObject& operator=(const FileSystemObject&) = delete; + virtual void removeObjectL() = 0; virtual void removeObjectR() = 0; @@ -459,7 +451,7 @@ class DirPair : public FileSystemObject, public HierarchyObject friend class HierarchyObject; public: - virtual void accept(FSObjectVisitor& visitor) const; + void accept(FSObjectVisitor& visitor) const override; CompareDirResult getDirCategory() const; //returns actually used subset of CompareFilesResult @@ -472,15 +464,15 @@ public: syncOpBuffered(SO_DO_NOTHING), syncOpUpToDate(false) {} - virtual SyncOperation getSyncOperation() const; + SyncOperation getSyncOperation() const override; void setSyncedTo(const Zstring& shortName); //call after sync, sets DIR_EQUAL private: - virtual void flip(); - virtual void removeObjectL(); - virtual void removeObjectR(); - virtual void notifySyncCfgChanged() { syncOpUpToDate = false; FileSystemObject::notifySyncCfgChanged(); HierarchyObject::notifySyncCfgChanged(); } + void flip () override; + void removeObjectL() override; + void removeObjectR() override; + void notifySyncCfgChanged() override { syncOpUpToDate = false; FileSystemObject::notifySyncCfgChanged(); HierarchyObject::notifySyncCfgChanged(); } mutable SyncOperation syncOpBuffered; //determining sync-op for directory may be expensive as it depends on child-objects -> buffer it mutable bool syncOpUpToDate; // @@ -493,7 +485,7 @@ class FilePair : public FileSystemObject friend class HierarchyObject; //construction public: - virtual void accept(FSObjectVisitor& visitor) const; + void accept(FSObjectVisitor& visitor) const override; FilePair(const Zstring& shortNameLeft, //use empty string if "not existing" const FileDescriptor& left, @@ -506,8 +498,8 @@ public: dataRight(right), moveFileRef(nullptr) {} - template <SelectedSide side> std::int64_t getLastWriteTime () const; - template <SelectedSide side> std::uint64_t getFileSize() const; + template <SelectedSide side> std::int64_t getLastWriteTime() const; + template <SelectedSide side> std::uint64_t getFileSize() const; template <SelectedSide side> FileId getFileId () const; template <SelectedSide side> bool isFollowedSymlink() const; @@ -516,8 +508,8 @@ public: CompareFilesResult getFileCategory() const; - virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const; //semantics: "what if"! assumes "active, no conflict, no recursion (directory)! - virtual SyncOperation getSyncOperation() const; + SyncOperation testSyncOperation(SyncDirection testSyncDir) const override; //semantics: "what if"! assumes "active, no conflict, no recursion (directory)! + SyncOperation getSyncOperation() const override; template <SelectedSide sideTrg> void setSyncedTo(const Zstring& shortName, //call after sync, sets FILE_EQUAL @@ -532,9 +524,9 @@ public: private: SyncOperation applyMoveOptimization(SyncOperation op) const; - virtual void flip(); - virtual void removeObjectL(); - virtual void removeObjectR(); + void flip () override; + void removeObjectL() override; + void removeObjectR() override; FileDescriptor dataLeft; FileDescriptor dataRight; @@ -571,9 +563,9 @@ public: std::int64_t lastWriteTimeSrc); private: - virtual void flip(); - virtual void removeObjectL(); - virtual void removeObjectR(); + void flip() override; + void removeObjectL() override; + void removeObjectR() override; LinkDescriptor dataLeft; LinkDescriptor dataRight; @@ -663,7 +655,7 @@ inline void FileSystemObject::setSyncDirConflict(const std::wstring& description) { syncDir_ = SyncDirection::NONE; - syncDirConflict.reset(new std::wstring(description)); + syncDirConflict = zen::make_unique<std::wstring>(description); notifySyncCfgChanged(); } @@ -695,7 +687,7 @@ void FileSystemObject::setActive(bool active) template <SelectedSide side> inline bool FileSystemObject::isEmpty() const { - return SelectParam<side>::get(shortNameLeft_, shortNameRight_).empty(); + return SelectParam<side>::ref(shortNameLeft_, shortNameRight_).empty(); } @@ -709,7 +701,7 @@ bool FileSystemObject::isEmpty() const template <SelectedSide side> inline const Zstring& FileSystemObject::getItemName() const { - return SelectParam<side>::get(shortNameLeft_, shortNameRight_); //empty if not existing + return SelectParam<side>::ref(shortNameLeft_, shortNameRight_); //empty if not existing } @@ -794,14 +786,14 @@ inline void FileSystemObject::setCategoryConflict(const std::wstring& description) { cmpResult = FILE_CONFLICT; - cmpResultDescr.reset(new std::wstring(description)); + cmpResultDescr = zen::make_unique<std::wstring>(description); } inline void FileSystemObject::setCategoryDiffMetadata(const std::wstring& description) { cmpResult = FILE_DIFFERENT_METADATA; - cmpResultDescr.reset(new std::wstring(description)); + cmpResultDescr = zen::make_unique<std::wstring>(description); } inline @@ -973,14 +965,14 @@ void DirPair::removeObjectR() template <SelectedSide side> inline bool BaseDirPair::isExisting() const { - return SelectParam<side>::get(dirExistsLeft_, dirExistsRight_); + return SelectParam<side>::ref(dirExistsLeft_, dirExistsRight_); } template <SelectedSide side> inline void BaseDirPair::setExisting(bool value) { - SelectParam<side>::get(dirExistsLeft_, dirExistsRight_) = value; + SelectParam<side>::ref(dirExistsLeft_, dirExistsRight_) = value; } @@ -1009,29 +1001,29 @@ void FilePair::removeObjectR() template <SelectedSide side> inline std::int64_t FilePair::getLastWriteTime() const { - return SelectParam<side>::get(dataLeft, dataRight).lastWriteTimeRaw; + return SelectParam<side>::ref(dataLeft, dataRight).lastWriteTimeRaw; } template <SelectedSide side> inline std::uint64_t FilePair::getFileSize() const { - return SelectParam<side>::get(dataLeft, dataRight).fileSize; + return SelectParam<side>::ref(dataLeft, dataRight).fileSize; } template <SelectedSide side> inline FileId FilePair::getFileId() const { - return FileId(SelectParam<side>::get(dataLeft, dataRight).devId, - SelectParam<side>::get(dataLeft, dataRight).fileIdx); + return FileId(SelectParam<side>::ref(dataLeft, dataRight).devId, + SelectParam<side>::ref(dataLeft, dataRight).fileIdx); } template <SelectedSide side> inline bool FilePair::isFollowedSymlink() const { - return SelectParam<side>::get(dataLeft, dataRight).isFollowedSymlink; + return SelectParam<side>::ref(dataLeft, dataRight).isFollowedSymlink; } @@ -1048,8 +1040,8 @@ void FilePair::setSyncedTo(const Zstring& shortName, //FILE_EQUAL is only allowed for same short name and file size: enforced by this method! static const SelectedSide sideSrc = OtherSide<sideTrg>::result; - SelectParam<sideTrg>::get(dataLeft, dataRight) = FileDescriptor(lastWriteTimeTrg, fileSize, fileIdTrg, isSymlinkTrg); - SelectParam<sideSrc>::get(dataLeft, dataRight) = FileDescriptor(lastWriteTimeSrc, fileSize, fileIdSrc, isSymlinkSrc); + SelectParam<sideTrg>::ref(dataLeft, dataRight) = FileDescriptor(lastWriteTimeTrg, fileSize, fileIdTrg, isSymlinkTrg); + SelectParam<sideSrc>::ref(dataLeft, dataRight) = FileDescriptor(lastWriteTimeSrc, fileSize, fileIdSrc, isSymlinkSrc); moveFileRef = nullptr; FileSystemObject::setSynced(shortName); //set FileSystemObject specific part @@ -1063,8 +1055,8 @@ void SymlinkPair::setSyncedTo(const Zstring& shortName, { static const SelectedSide sideSrc = OtherSide<sideTrg>::result; - SelectParam<sideTrg>::get(dataLeft, dataRight) = LinkDescriptor(lastWriteTimeTrg); - SelectParam<sideSrc>::get(dataLeft, dataRight) = LinkDescriptor(lastWriteTimeSrc); + SelectParam<sideTrg>::ref(dataLeft, dataRight) = LinkDescriptor(lastWriteTimeTrg); + SelectParam<sideSrc>::ref(dataLeft, dataRight) = LinkDescriptor(lastWriteTimeSrc); FileSystemObject::setSynced(shortName); //set FileSystemObject specific part } @@ -1080,7 +1072,7 @@ void DirPair::setSyncedTo(const Zstring& shortName) template <SelectedSide side> inline std::int64_t SymlinkPair::getLastWriteTime() const { - return SelectParam<side>::get(dataLeft, dataRight).lastWriteTimeRaw; + return SelectParam<side>::ref(dataLeft, dataRight).lastWriteTimeRaw; } diff --git a/FreeFileSync/Source/lib/db_file.cpp b/FreeFileSync/Source/lib/db_file.cpp index b1f0098e..c1bc5478 100644 --- a/FreeFileSync/Source/lib/db_file.cpp +++ b/FreeFileSync/Source/lib/db_file.cpp @@ -5,7 +5,8 @@ // ************************************************************************** #include "db_file.h" -#include <zen/file_handling.h> +#include <unordered_set> +#include <zen/file_access.h> #include <zen/scope_guard.h> #include <zen/guid.h> #include <zen/utf.h> @@ -54,7 +55,7 @@ Zstring getDatabaseFilePath(const BaseDirPair& baseDirObj, bool tempfile = false //####################################################################################################################################### -void saveStreams(const DbStreams& streamList, const Zstring& filepath) //throw FileError +void saveStreams(const DbStreams& streamList, const Zstring& filepath, const std::function<void(std::int64_t bytesDelta)>& onUpdateSaveStatus) //throw FileError { BinStreamOut streamOut; @@ -73,8 +74,8 @@ void saveStreams(const DbStreams& streamList, const Zstring& filepath) //throw F writeContainer<BinaryStream>(streamOut, stream.second); } - assert(!somethingExists(filepath)); //orphan tmp files should be cleaned up already at this point! - saveBinStream(filepath, streamOut.get()); //throw FileError + assert(!somethingExists(filepath)); //orphan tmp files should have been cleaned up at this point! + saveBinStream(filepath, streamOut.get(), onUpdateSaveStatus); //throw FileError #ifdef ZEN_WIN //be careful to avoid CreateFile() + CREATE_ALWAYS on a hidden file -> see file_io.cpp @@ -87,7 +88,9 @@ DbStreams loadStreams(const Zstring& filepath) //throw FileError, FileErrorDatab { try { - BinStreamIn streamIn = loadBinStream<BinaryStream>(filepath); //throw FileError + warn_static("TODO: implement loadBinStream callback") + + BinStreamIn streamIn = loadBinStream<BinaryStream>(filepath, nullptr); //throw FileError //read FreeFileSync file identifier char formatDescr[sizeof(FILE_FORMAT_DESCR)] = {}; @@ -245,8 +248,8 @@ private: writeNumber<std:: int64_t>(output, descr.lastWriteTimeRaw); writeNumber<std::uint64_t>(output, descr.fileId.first); writeNumber<std::uint64_t>(output, descr.fileId.second); - assert_static(sizeof(descr.fileId.first ) <= sizeof(std::uint64_t)); - assert_static(sizeof(descr.fileId.second) <= sizeof(std::uint64_t)); + static_assert(sizeof(descr.fileId.first ) <= sizeof(std::uint64_t), ""); + static_assert(sizeof(descr.fileId.second) <= sizeof(std::uint64_t), ""); } static void writeLink(BinStreamOut& output, const InSyncDescrLink& descr) @@ -427,14 +430,14 @@ private: template <class M, class V> static V& updateItem(M& map, const Zstring& key, const V& value) { - auto rv = map.insert(typename M::value_type(key, value)); + auto rv = map.emplace(key, value); if (!rv.second) { #if defined ZEN_WIN || defined ZEN_MAC //caveat: key must be updated, if there is a change in short name case!!! if (rv.first->first != key) { map.erase(rv.first); - return map.insert(typename M::value_type(key, value)).first->second; + return map.emplace(key, value).first->second; } #endif rv.first->second = value; @@ -455,7 +458,7 @@ private: if (it->first != key) { map.erase(it); //don't fiddle with decrementing "it"! - you might lose while optimizing pointlessly - return map.insert(typename M::value_type(key, value)).first->second; + return map.emplace(key, value).first->second; } #endif it->second = value; @@ -467,7 +470,7 @@ private: void process(const HierarchyObject::SubFileVec& currentFiles, const Zstring& parentRelativeNamePf, InSyncDir::FileList& dbFiles) { - hash_set<const InSyncFile*> toPreserve; //referencing fixed-in-memory std::map elements + std::unordered_set<const InSyncFile*> toPreserve; //referencing fixed-in-memory std::map elements for (const FilePair& fileObj : currentFiles) if (!fileObj.isEmpty()) { @@ -511,7 +514,7 @@ private: void process(const HierarchyObject::SubLinkVec& currentLinks, const Zstring& parentRelativeNamePf, InSyncDir::LinkList& dbLinks) { - hash_set<const InSyncSymlink*> toPreserve; + std::unordered_set<const InSyncSymlink*> toPreserve; for (const SymlinkPair& linkObj : currentLinks) if (!linkObj.isEmpty()) { @@ -547,7 +550,7 @@ private: void process(const HierarchyObject::SubDirVec& currentDirs, const Zstring& parentRelativeNamePf, InSyncDir::DirList& dbDirs) { - hash_set<const InSyncDir*> toPreserve; + std::unordered_set<const InSyncDir*> toPreserve; for (const DirPair& dirObj : currentDirs) if (!dirObj.isEmpty()) switch (dirObj.getDirCategory()) @@ -558,7 +561,7 @@ private: //update directory entry only (shallow), but do *not touch* exising child elements!!! const Zstring& key = dirObj.getPairShortName(); - auto insertResult = dbDirs.insert(std::make_pair(key, InSyncDir(InSyncDir::DIR_STATUS_IN_SYNC))); //get or create + auto insertResult = dbDirs.emplace(key, InSyncDir(InSyncDir::DIR_STATUS_IN_SYNC)); //get or create auto it = insertResult.first; #if defined ZEN_WIN || defined ZEN_MAC //caveat: key might need to be updated, too, if there is a change in short name case!!! @@ -567,7 +570,7 @@ private: { auto oldValue = std::move(it->second); dbDirs.erase(it); //don't fiddle with decrementing "it"! - you might lose while optimizing pointlessly - it = dbDirs.insert(InSyncDir::DirList::value_type(key, std::move(oldValue))).first; + it = dbDirs.emplace(key, std::move(oldValue)).first; } #endif InSyncDir& dir = it->second; @@ -583,7 +586,7 @@ private: //Example: directories on left and right differ in case while sub-files are equal { //reuse last "in-sync" if available or insert strawman entry (do not try to update and thereby remove child elements!!!) - InSyncDir& dir = dbDirs.insert(std::make_pair(dirObj.getPairShortName(), InSyncDir(InSyncDir::DIR_STATUS_STRAW_MAN))).first->second; + InSyncDir& dir = dbDirs.emplace(dirObj.getPairShortName(), InSyncDir(InSyncDir::DIR_STATUS_STRAW_MAN)).first->second; toPreserve.insert(&dir); recurse(dirObj, dir); } @@ -739,12 +742,14 @@ void zen::saveLastSynchronousState(const BaseDirPair& baseDirObj) //throw FileEr streamsLeft [sessionID] = std::move(updatedStreamLeft); streamsRight[sessionID] = std::move(updatedStreamRight); + warn_static("TODO: implement saveStreams callback") + //write (temp-) files... zen::ScopeGuard guardTempFileLeft = zen::makeGuard([&] {zen::removeFile(dbNameLeftTmp); }); - saveStreams(streamsLeft, dbNameLeftTmp); //throw FileError + saveStreams(streamsLeft, dbNameLeftTmp, nullptr); //throw FileError zen::ScopeGuard guardTempFileRight = zen::makeGuard([&] {zen::removeFile(dbNameRightTmp); }); - saveStreams(streamsRight, dbNameRightTmp); //throw FileError + saveStreams(streamsRight, dbNameRightTmp, nullptr); //throw FileError //operation finished: rename temp files -> this should work transactionally: //if there were no write access, creation of temp files would have failed diff --git a/FreeFileSync/Source/lib/db_file.h b/FreeFileSync/Source/lib/db_file.h index ffaa0e62..9998bbc3 100644 --- a/FreeFileSync/Source/lib/db_file.h +++ b/FreeFileSync/Source/lib/db_file.h @@ -76,18 +76,17 @@ struct InSyncDir //convenience InSyncDir& addDir(const Zstring& shortName, InSyncStatus st) { - //use C++11 emplace when available - return dirs.insert(std::make_pair(shortName, InSyncDir(st))).first->second; + return dirs.emplace(shortName, InSyncDir(st)).first->second; } void addFile(const Zstring& shortName, const InSyncDescrFile& dataL, const InSyncDescrFile& dataR, CompareVariant cmpVar, std::uint64_t fileSize) { - files.insert(std::make_pair(shortName, InSyncFile(dataL, dataR, cmpVar, fileSize))); + files.emplace(shortName, InSyncFile(dataL, dataR, cmpVar, fileSize)); } void addSymlink(const Zstring& shortName, const InSyncDescrLink& dataL, const InSyncDescrLink& dataR, CompareVariant cmpVar) { - symlinks.insert(std::make_pair(shortName, InSyncSymlink(dataL, dataR, cmpVar))); + symlinks.emplace(shortName, InSyncSymlink(dataL, dataR, cmpVar)); } }; diff --git a/FreeFileSync/Source/lib/dir_exist_async.h b/FreeFileSync/Source/lib/dir_exist_async.h index 4d73f699..a7e9b0b7 100644 --- a/FreeFileSync/Source/lib/dir_exist_async.h +++ b/FreeFileSync/Source/lib/dir_exist_async.h @@ -8,7 +8,7 @@ #define DIR_EXIST_HEADER_08173281673432158067342132467183267 #include <zen/thread.h> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/file_error.h> #include "../process_callback.h" #include "resolve_path.h" @@ -39,7 +39,7 @@ DirectoryStatus getExistingDirsUpdating(const std::set<Zstring, LessFilename>& d std::list<std::pair<Zstring, boost::unique_future<bool>>> futureInfo; for (const Zstring& dirpath : dirpaths) if (!dirpath.empty()) //skip empty dirs - futureInfo.push_back(std::make_pair(dirpath, async2<bool>([=]() -> bool + futureInfo.emplace_back(dirpath, async([=]() -> bool { #ifdef ZEN_WIN //1. login to network share, if necessary @@ -47,7 +47,7 @@ DirectoryStatus getExistingDirsUpdating(const std::set<Zstring, LessFilename>& d #endif //2. check dir existence return dirExists(dirpath); - }))); + })); //don't wait (almost) endlessly like win32 would on not existing network shares: const boost::system_time endTime = boost::get_system_time() + boost::posix_time::seconds(20); //consider CD-rom insert or hard disk spin up time from sleep diff --git a/FreeFileSync/Source/lib/dir_lock.cpp b/FreeFileSync/Source/lib/dir_lock.cpp index 1d22f455..1d1ce2ae 100644 --- a/FreeFileSync/Source/lib/dir_lock.cpp +++ b/FreeFileSync/Source/lib/dir_lock.cpp @@ -12,9 +12,8 @@ #include <zen/scope_guard.h> #include <zen/guid.h> #include <zen/tick_count.h> -#include <zen/assert_static.h> #include <zen/int64.h> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/serialize.h> #include <zen/optional.h> @@ -341,8 +340,8 @@ struct LockInformation //throw FileError writeArray(stream, LOCK_FORMAT_DESCR, sizeof(LOCK_FORMAT_DESCR)); writeNumber<boost::int32_t>(stream, LOCK_FORMAT_VER); - assert_static(sizeof(processId) <= sizeof(std::uint64_t)); //ensure cross-platform compatibility! - assert_static(sizeof(sessionId) <= sizeof(std::uint64_t)); // + static_assert(sizeof(processId) <= sizeof(std::uint64_t), ""); //ensure cross-platform compatibility! + static_assert(sizeof(sessionId) <= sizeof(std::uint64_t), ""); // writeContainer(stream, lockId); writeContainer(stream, computerName); @@ -368,7 +367,7 @@ struct LockInformation //throw FileError LockInformation retrieveLockInfo(const Zstring& lockfilepath) //throw FileError { - BinStreamIn streamIn = loadBinStream<BinaryStream>(lockfilepath); //throw FileError + BinStreamIn streamIn = loadBinStream<BinaryStream>(lockfilepath, nullptr); //throw FileError try { return LockInformation(streamIn); //throw UnexpectedEndOfStreamError @@ -484,7 +483,7 @@ void waitOnDirLock(const Zstring& lockfilepath, DirLockCallback* callback) //thr } //wait some time... - assert_static(1000 * POLL_LIFE_SIGN_INTERVAL % GUI_CALLBACK_INTERVAL == 0); + static_assert(1000 * POLL_LIFE_SIGN_INTERVAL % GUI_CALLBACK_INTERVAL == 0, ""); for (size_t i = 0; i < 1000 * POLL_LIFE_SIGN_INTERVAL / GUI_CALLBACK_INTERVAL; ++i) { if (callback) callback->requestUiRefresh(); diff --git a/FreeFileSync/Source/lib/error_log.h b/FreeFileSync/Source/lib/error_log.h index 2971f746..f9e351c6 100644 --- a/FreeFileSync/Source/lib/error_log.h +++ b/FreeFileSync/Source/lib/error_log.h @@ -34,7 +34,7 @@ void logError(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); //throw FileError + saveBinStream(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 d5ef3e48..32026b25 100644 --- a/FreeFileSync/Source/lib/ffs_paths.cpp +++ b/FreeFileSync/Source/lib/ffs_paths.cpp @@ -5,7 +5,7 @@ // ************************************************************************** #include "ffs_paths.h" -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <wx/stdpaths.h> #include <wx/app.h> #include <wx+/string_conv.h> @@ -124,7 +124,7 @@ Zstring zen::getFreeFileSyncLauncher() ZEN_ON_SCOPE_EXIT(if (appURL) ::CFRelease(appURL)); if (::LSFindApplicationForInfo(kLSUnknownCreator, // OSType inCreator, - CFSTR("net.SourceForge.FreeFileSync"),//CFStringRef inBundleID, + CFSTR("Zenju.FreeFileSync"),//CFStringRef inBundleID, nullptr, //CFStringRef inName, nullptr, //FSRef *outAppRef, &appURL) == noErr) //CFURLRef *outAppURL diff --git a/FreeFileSync/Source/lib/generate_logfile.h b/FreeFileSync/Source/lib/generate_logfile.h index 41f6c945..af8d05a9 100644 --- a/FreeFileSync/Source/lib/generate_logfile.h +++ b/FreeFileSync/Source/lib/generate_logfile.h @@ -29,15 +29,44 @@ struct SummaryInfo void saveLogToFile(const SummaryInfo& summary, //throw FileError const ErrorLog& log, - FileOutput& fileOut); + FileOutput& fileOut, + const std::function<void(std::int64_t bytesDelta)>& onUpdateSaveStatus); void saveToLastSyncsLog(const SummaryInfo& summary, //throw FileError const ErrorLog& log, - size_t maxBytesToWrite); + size_t maxBytesToWrite, + const std::function<void(std::int64_t bytesDelta)>& onUpdateSaveStatus); +Zstring getLastSyncsLogfilePath(); +struct OnUpdateLogfileStatusNoThrow +{ + OnUpdateLogfileStatusNoThrow(ProcessCallback& pc, const Zstring& logfilePath) : pc_(pc), logfilePath_(logfilePath), bytesWritten(), + msg(replaceCpy(_("Saving log file %x..."), L"%x", fmtFileName(logfilePath_))) {} + + void operator()(std::int64_t bytesDelta) + { + bytesWritten += bytesDelta; + + if (updateUiIsAllowed()) //test if specific time span between ui updates is over + try + { + pc_.reportStatus(msg + L" (" + filesizeToShortString(bytesWritten) + L")"); //throw? + pc_.forceUiRefresh(); //throw? + } + catch (...) {} + } + +private: + ProcessCallback& pc_; + const Zstring logfilePath_; + std::int64_t bytesWritten; + const std::wstring msg; +}; + + //####################### implementation ####################### namespace @@ -78,12 +107,12 @@ std::wstring generateLogHeader(const SummaryInfo& s) //calculate max width, this considers UTF-16 only, not true Unicode...but maybe good idea? those 2-char-UTF16 codes are usually wider than fixed width chars anyway! size_t sepLineLen = 0; - std::for_each(results.begin(), results.end(), [&](const std::wstring& str) { sepLineLen = std::max(sepLineLen, str.size()); }); + for (const std::wstring& str : results) sepLineLen = std::max(sepLineLen, str.size()); output.resize(output.size() + sepLineLen + 1, L'_'); output += L'\n'; - std::for_each(results.begin(), results.end(), [&](const std::wstring& str) { output += L'|'; output += str; output += L'\n'; }); + for (const std::wstring& str : results) { output += L'|'; output += str; output += L'\n'; } output += L'|'; output.resize(output.size() + sepLineLen, L'_'); @@ -97,7 +126,8 @@ std::wstring generateLogHeader(const SummaryInfo& s) inline void saveLogToFile(const SummaryInfo& summary, //throw FileError const ErrorLog& log, - FileOutput& fileOut) + FileOutput& fileOut, + const std::function<void(std::int64_t bytesDelta)>& onUpdateSaveStatus) { Utf8String header = utfCvrtTo<Utf8String>(generateLogHeader(summary)); replace(header, '\n', LINE_BREAK); //don't replace line break any earlier @@ -112,16 +142,22 @@ void saveLogToFile(const SummaryInfo& summary, //throw FileError msg += LINE_BREAK; //make sure string is not empty! fileOut.write(&*msg.begin(), msg.size()); //throw FileError + if (onUpdateSaveStatus) onUpdateSaveStatus(msg.size()); } } inline +Zstring getLastSyncsLogfilePath() { return getConfigDir() + Zstr("LastSyncs.log"); } + + +inline void saveToLastSyncsLog(const SummaryInfo& summary, //throw FileError const ErrorLog& log, - size_t maxBytesToWrite) //log may be *huge*, e.g. 1 million items; LastSyncs.log *must not* create performance problems! + size_t maxBytesToWrite, //log may be *huge*, e.g. 1 million items; LastSyncs.log *must not* create performance problems! + const std::function<void(std::int64_t bytesDelta)>& onUpdateSaveStatus) { - const Zstring filepath = getConfigDir() + Zstr("LastSyncs.log"); + const Zstring filepath = getLastSyncsLogfilePath(); Utf8String newStream = utfCvrtTo<Utf8String>(generateLogHeader(summary)); replace(newStream, '\n', LINE_BREAK); //don't replace line break any earlier @@ -144,10 +180,14 @@ 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); //throw FileError + oldStream = loadBinStream<Utf8String>(filepath, onUpdateLoadStatus); //throw FileError } catch (FileError&) {} @@ -174,7 +214,7 @@ void saveToLastSyncsLog(const SummaryInfo& summary, //throw FileError } } - saveBinStream(filepath, newStream); //throw FileError + saveBinStream(filepath, newStream, onUpdateSaveStatus); //throw FileError } } diff --git a/FreeFileSync/Source/lib/hard_filter.cpp b/FreeFileSync/Source/lib/hard_filter.cpp index 28ba1b40..ca1005d1 100644 --- a/FreeFileSync/Source/lib/hard_filter.cpp +++ b/FreeFileSync/Source/lib/hard_filter.cpp @@ -57,7 +57,7 @@ bool zen::operator<(const HardFilter& lhs, const HardFilter& rhs) namespace { //constructing them in addFilterEntry becomes perf issue for large filter lists -const Zstring asterisk(Zstr('*')); +const Zstring asterisk(Zstr("*")); const Zstring sepAsterisk = FILE_NAME_SEPARATOR + asterisk; const Zstring asteriskSep = asterisk + FILE_NAME_SEPARATOR; const Zstring asteriskSepAsterisk = asteriskSep + asterisk; @@ -68,10 +68,9 @@ void addFilterEntry(const Zstring& filterPhrase, std::vector<Zstring>& fileFilte { #if defined ZEN_WIN || defined ZEN_MAC //Windows does NOT distinguish between upper/lower-case - Zstring filterFormatted = filterPhrase; - makeUpper(filterFormatted); + const Zstring& filterFmt= makeUpperCopy(filterPhrase); #elif defined ZEN_LINUX - const Zstring& filterFormatted = filterPhrase; + const Zstring& filterFmt = filterPhrase; //Linux DOES distinguish between upper/lower-case: nothing to do here #endif /* @@ -116,13 +115,13 @@ void addFilterEntry(const Zstring& filterPhrase, std::vector<Zstring>& fileFilte } }; - if (startsWith(filterFormatted, FILE_NAME_SEPARATOR)) // \abc - processTail(afterFirst(filterFormatted, FILE_NAME_SEPARATOR)); + if (startsWith(filterFmt, FILE_NAME_SEPARATOR)) // \abc + processTail(afterFirst(filterFmt, FILE_NAME_SEPARATOR)); else { - processTail(filterFormatted); - if (startsWith(filterFormatted, asteriskSep)) // *\abc - processTail(afterFirst(filterFormatted, asteriskSep)); + processTail(filterFmt); + if (startsWith(filterFmt, asteriskSep)) // *\abc + processTail(afterFirst(filterFmt, asteriskSep)); } } @@ -302,14 +301,13 @@ NameFilter::NameFilter(const Zstring& includeFilter, const Zstring& excludeFilte bool NameFilter::passFileFilter(const Zstring& relFilename) const { #if defined ZEN_WIN || defined ZEN_MAC //Windows does NOT distinguish between upper/lower-case - Zstring nameFormatted = relFilename; - makeUpper(nameFormatted); + const Zstring& nameFmt = makeUpperCopy(relFilename); #elif defined ZEN_LINUX //Linux DOES distinguish between upper/lower-case - const Zstring& nameFormatted = relFilename; //nothing to do here + const Zstring& nameFmt = relFilename; //nothing to do here #endif - return matchesFilter(nameFormatted, filterFileIn) && //process include filters - !matchesFilter(nameFormatted, filterFileEx); //process exclude filters + return matchesFilter(nameFmt, filterFileIn) && //process include filters + !matchesFilter(nameFmt, filterFileEx); //process exclude filters } @@ -318,24 +316,23 @@ bool NameFilter::passDirFilter(const Zstring& relDirname, bool* subObjMightMatch assert(!subObjMightMatch || *subObjMightMatch == true); //check correct usage #if defined ZEN_WIN || defined ZEN_MAC //Windows does NOT distinguish between upper/lower-case - Zstring nameFormatted = relDirname; - makeUpper(nameFormatted); + const Zstring& nameFmt = makeUpperCopy(relDirname); #elif defined ZEN_LINUX //Linux DOES distinguish between upper/lower-case - const Zstring& nameFormatted = relDirname; //nothing to do here + const Zstring& nameFmt = relDirname; //nothing to do here #endif - if (matchesFilter(nameFormatted, filterFolderEx)) //process exclude filters + if (matchesFilter(nameFmt, filterFolderEx)) //process exclude filters { if (subObjMightMatch) *subObjMightMatch = false; //exclude subfolders/subfiles as well return false; } - if (!matchesFilter(nameFormatted, filterFolderIn)) //process include filters + if (!matchesFilter(nameFmt, filterFolderIn)) //process include filters { if (subObjMightMatch) { - const Zstring& subNameBegin = nameFormatted + FILE_NAME_SEPARATOR; //const-ref optimization + const Zstring& subNameBegin = nameFmt + FILE_NAME_SEPARATOR; //const-ref optimization *subObjMightMatch = matchesFilterBegin(subNameBegin, filterFileIn) || //might match a file in subdirectory matchesFilterBegin(subNameBegin, filterFolderIn); //or another subdirectory diff --git a/FreeFileSync/Source/lib/hard_filter.h b/FreeFileSync/Source/lib/hard_filter.h index e747c626..19e7003b 100644 --- a/FreeFileSync/Source/lib/hard_filter.h +++ b/FreeFileSync/Source/lib/hard_filter.h @@ -67,16 +67,16 @@ HardFilter::FilterRef combineFilters(const HardFilter::FilterRef& first, class NullFilter : public HardFilter //no filtering at all { public: - virtual bool passFileFilter(const Zstring& relFilename) const; - virtual bool passDirFilter(const Zstring& relDirname, bool* subObjMightMatch) const; - virtual bool isNull() const; + bool passFileFilter(const Zstring& relFilename) const override; + bool passDirFilter(const Zstring& relDirname, bool* subObjMightMatch) const override; + bool isNull() const override; private: friend class HardFilter; - // virtual void save(ZstreamOut& stream) const {} - virtual std::string uniqueClassIdentifier() const { return "NullFilter"; } + // void save(ZstreamOut& stream) const override {} + std::string uniqueClassIdentifier() const override { return "NullFilter"; } // static FilterRef load(ZstreamIn& stream); //throw UnexpectedEndOfStreamError - virtual bool cmpLessSameType(const HardFilter& other) const; + bool cmpLessSameType(const HardFilter& other) const override; }; @@ -85,18 +85,18 @@ class NameFilter : public HardFilter //standard filter by filepath public: NameFilter(const Zstring& includeFilter, const Zstring& excludeFilter); - virtual bool passFileFilter(const Zstring& relFilename) const; - virtual bool passDirFilter(const Zstring& relDirname, bool* subObjMightMatch) const; + bool passFileFilter(const Zstring& relFilename) const override; + bool passDirFilter(const Zstring& relDirname, bool* subObjMightMatch) const override; - virtual bool isNull() const; + bool isNull() const override; static bool isNull(const Zstring& includeFilter, const Zstring& excludeFilter); //*fast* check without expensively constructing NameFilter instance! private: friend class HardFilter; - // virtual void save(ZstreamOut& stream) const; - virtual std::string uniqueClassIdentifier() const { return "NameFilter"; } + // void save(ZstreamOut& stream) const override; + std::string uniqueClassIdentifier() const override { return "NameFilter"; } // static FilterRef load(ZstreamIn& stream); //throw UnexpectedEndOfStreamError - virtual bool cmpLessSameType(const HardFilter& other) const; + bool cmpLessSameType(const HardFilter& other) const override; std::vector<Zstring> filterFileIn; // std::vector<Zstring> filterFolderIn; //upper case (windows) + unique items by construction @@ -113,16 +113,16 @@ class CombinedFilter : public HardFilter //combine two filters to match if and public: CombinedFilter(const FilterRef& first, const FilterRef& second) : first_(first), second_(second) {} - virtual bool passFileFilter(const Zstring& relFilename) const; - virtual bool passDirFilter(const Zstring& relDirname, bool* subObjMightMatch) const; - virtual bool isNull() const; + bool passFileFilter(const Zstring& relFilename) const override; + bool passDirFilter(const Zstring& relDirname, bool* subObjMightMatch) const override; + bool isNull() const override; private: friend class HardFilter; - // virtual void save(ZstreamOut& stream) const; - virtual std::string uniqueClassIdentifier() const { return "CombinedFilter"; } + // void save(ZstreamOut& stream) const override; + std::string uniqueClassIdentifier() const override { return "CombinedFilter"; } // static FilterRef load(ZstreamIn& stream); //throw UnexpectedEndOfStreamError - virtual bool cmpLessSameType(const HardFilter& other) const; + bool cmpLessSameType(const HardFilter& other) const override; const FilterRef first_; const FilterRef second_; diff --git a/FreeFileSync/Source/lib/icon_buffer.cpp b/FreeFileSync/Source/lib/icon_buffer.cpp index 73fe47d1..df0bee8b 100644 --- a/FreeFileSync/Source/lib/icon_buffer.cpp +++ b/FreeFileSync/Source/lib/icon_buffer.cpp @@ -32,7 +32,7 @@ namespace const size_t BUFFER_SIZE_MAX = 800; //maximum number of icons to hold in buffer: must be big enough to hold visible icons + preload buffer! Consider OS limit on GDI resources (wxBitmap)!!! #ifndef NDEBUG -boost::thread::id mainThreadId = boost::this_thread::get_id(); +const boost::thread::id mainThreadId = boost::this_thread::get_id(); #endif #ifdef ZEN_WIN @@ -89,7 +89,7 @@ public: wxBitmap extractWxBitmap() { ZEN_ON_SCOPE_EXIT(assert(!*this)); - assert(boost::this_thread::get_id() == mainThreadId ); + assert(boost::this_thread::get_id() == mainThreadId); if (!handle_) return wxNullBitmap; @@ -396,20 +396,20 @@ class WorkLoad public: Zstring extractNextFile() //context of worker thread, blocking { - assert(boost::this_thread::get_id() != mainThreadId ); + assert(boost::this_thread::get_id() != mainThreadId); boost::unique_lock<boost::mutex> dummy(lockFiles); while (filesToLoad.empty()) conditionNewFiles.timed_wait(dummy, boost::posix_time::milliseconds(100)); //interruption point! - Zstring filepath = filesToLoad.back(); - filesToLoad.pop_back(); + Zstring filepath = filesToLoad.back(); //yes, not std::bad_alloc exception-safe, but bad_alloc is not relevant for us + filesToLoad.pop_back(); // return filepath; } void setWorkload(const std::vector<Zstring>& newLoad) //context of main thread { - assert(boost::this_thread::get_id() == mainThreadId ); + assert(boost::this_thread::get_id() == mainThreadId); { boost::lock_guard<boost::mutex> dummy(lockFiles); filesToLoad = newLoad; @@ -420,7 +420,7 @@ public: void addToWorkload(const Zstring& newEntry) //context of main thread { - assert(boost::this_thread::get_id() == mainThreadId ); + assert(boost::this_thread::get_id() == mainThreadId); { boost::lock_guard<boost::mutex> dummy(lockFiles); filesToLoad.push_back(newEntry); //set as next item to retrieve @@ -474,7 +474,7 @@ public: boost::lock_guard<boost::mutex> dummy(lockIconList); //thread safety: moving IconHolder is free from side effects, but ~wxBitmap() is NOT! => do NOT delete items from iconList here! - auto rc = iconList.insert(std::make_pair(entryName, makeValueObject())); + auto rc = iconList.emplace(entryName, makeValueObject()); assert(rc.second); if (rc.second) //if insertion took place { diff --git a/FreeFileSync/Source/lib/localization.cpp b/FreeFileSync/Source/lib/localization.cpp index ab4b49d1..f891fdb4 100644 --- a/FreeFileSync/Source/lib/localization.cpp +++ b/FreeFileSync/Source/lib/localization.cpp @@ -5,6 +5,7 @@ // ************************************************************************** #include "localization.h" +#include <unordered_map> #include <map> #include <list> #include <iterator> @@ -38,7 +39,7 @@ public: wxLanguage langId() const { return langId_; } - virtual std::wstring translate(const std::wstring& text) override + std::wstring translate(const std::wstring& text) override { //look for translation in buffer table auto it = transMapping.find(text); @@ -47,7 +48,7 @@ public: return text; //fallback } - virtual std::wstring translate(const std::wstring& singular, const std::wstring& plural, std::int64_t n) override + std::wstring translate(const std::wstring& singular, const std::wstring& plural, std::int64_t n) override { auto it = transMappingPl.find(std::make_pair(singular, plural)); if (it != transMappingPl.end()) @@ -60,7 +61,7 @@ public: } private: - typedef hash_map<std::wstring, std::wstring> Translation; //hash_map is 15% faster than std::map on GCC + typedef std::unordered_map<std::wstring, std::wstring> Translation; //hash_map is 15% faster than std::map on GCC typedef std::map<std::pair<std::wstring, std::wstring>, std::vector<std::wstring>> TranslationPlural; Translation transMapping; //map original text |-> translation @@ -75,7 +76,7 @@ FFSTranslation::FFSTranslation(const Zstring& filepath, wxLanguage languageId) : std::string inputStream; try { - inputStream = loadBinStream<std::string>(filepath); //throw FileError + inputStream = loadBinStream<std::string>(filepath, nullptr); //throw FileError } catch (const FileError& e) { @@ -91,7 +92,7 @@ FFSTranslation::FFSTranslation(const Zstring& filepath, wxLanguage languageId) : { const std::wstring original = utfCvrtTo<std::wstring>(item.first); const std::wstring translation = utfCvrtTo<std::wstring>(item.second); - transMapping.insert(std::make_pair(original, translation)); + transMapping.emplace(original, translation); } for (const auto& item : transPluralInput) @@ -103,10 +104,10 @@ FFSTranslation::FFSTranslation(const Zstring& filepath, wxLanguage languageId) : for (const std::string& pf : item.second) plFormsWide.push_back(utfCvrtTo<std::wstring>(pf)); - transMappingPl.insert(std::make_pair(std::make_pair(engSingular, engPlural), plFormsWide)); + transMappingPl.emplace(std::make_pair(engSingular, engPlural), plFormsWide); } - pluralParser = make_unique<parse_plural::PluralForm>(header.pluralDefinition); //throw parse_plural::ParsingError + pluralParser = zen::make_unique<parse_plural::PluralForm>(header.pluralDefinition); //throw parse_plural::ParsingError } @@ -115,16 +116,16 @@ class FindLngfiles : public zen::TraverseCallback public: FindLngfiles(std::vector<Zstring>& lngFiles) : lngFiles_(lngFiles) {} - virtual void onFile(const Zchar* shortName, const Zstring& filepath, const FileInfo& details) + void onFile(const Zchar* shortName, const Zstring& filepath, const FileInfo& details) override { if (endsWith(filepath, Zstr(".lng"))) lngFiles_.push_back(filepath); } - virtual HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) { return LINK_SKIP; } - virtual TraverseCallback* onDir(const Zchar* shortName, const Zstring& dirpath) { return nullptr; } - virtual HandleError reportDirError (const std::wstring& msg, size_t retryNumber) { assert(false); return ON_ERROR_IGNORE; } //errors are not really critical in this context - virtual HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) { assert(false); return ON_ERROR_IGNORE; } // + HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) override { return LINK_SKIP; } + TraverseCallback* onDir(const Zchar* shortName, const Zstring& dirpath) override { return nullptr; } + HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override { assert(false); return ON_ERROR_IGNORE; } //errors are not really critical in this context + HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) override { assert(false); return ON_ERROR_IGNORE; } // private: std::vector<Zstring>& lngFiles_; @@ -197,7 +198,7 @@ ExistingTranslations::ExistingTranslations() { try { - const std::string stream = loadBinStream<std::string>(filepath); //throw FileError + const std::string stream = loadBinStream<std::string>(filepath, nullptr); //throw FileError lngfile::TransHeader lngHeader; lngfile::parseHeader(stream, lngHeader); //throw ParsingError @@ -395,7 +396,7 @@ public: static void init(wxLanguage lng) { locale.reset(); //avoid global locale lifetime overlap! wxWidgets cannot handle this and will crash! - locale.reset(new wxLocale); + locale = zen::make_unique<wxLocale>(); const wxLanguageInfo* sysLngInfo = wxLocale::GetLanguageInfo(wxLocale::GetSystemLanguage()); const wxLanguageInfo* selLngInfo = wxLocale::GetLanguageInfo(lng); @@ -453,7 +454,7 @@ void zen::setLanguage(int language) //throw FileError else try { - zen::setTranslator(new FFSTranslation(utfCvrtTo<Zstring>(languageFile), static_cast<wxLanguage>(language))); //throw lngfile::ParsingError, parse_plural::ParsingError + zen::setTranslator(zen::make_unique<FFSTranslation>(utfCvrtTo<Zstring>(languageFile), static_cast<wxLanguage>(language))); //throw lngfile::ParsingError, parse_plural::ParsingError } catch (lngfile::ParsingError& e) { diff --git a/FreeFileSync/Source/lib/lock_holder.h b/FreeFileSync/Source/lib/lock_holder.h index 2d7b6ef1..93588310 100644 --- a/FreeFileSync/Source/lib/lock_holder.h +++ b/FreeFileSync/Source/lib/lock_holder.h @@ -29,8 +29,8 @@ public: { public: WaitOnLockHandler(ProcessCallback& pc) : pc_(pc) {} - virtual void requestUiRefresh() { pc_.requestUiRefresh(); } //allowed to throw exceptions - virtual void reportStatus(const std::wstring& text) { pc_.reportStatus(text); } + void requestUiRefresh() override { pc_.requestUiRefresh(); } //allowed to throw exceptions + void reportStatus(const std::wstring& text) override { pc_.reportStatus(text); } private: ProcessCallback& pc_; } callback(procCallback); @@ -38,7 +38,7 @@ public: try { //lock file creation is synchronous and may block noticeably for very slow devices (usb sticks, mapped cloud storages) - lockHolder.push_back(DirLock(dirpathFmt + Zstr("sync") + LOCK_FILE_ENDING, &callback)); //throw FileError + lockHolder.emplace_back(dirpathFmt + Zstr("sync") + LOCK_FILE_ENDING, &callback); //throw FileError } catch (const FileError& e) { diff --git a/FreeFileSync/Source/lib/osx_file_icon.h b/FreeFileSync/Source/lib/osx_file_icon.h deleted file mode 100644 index 5edfd740..00000000 --- a/FreeFileSync/Source/lib/osx_file_icon.h +++ /dev/null @@ -1,36 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef OSX_FILE_ICON_8427508422345342 -#define OSX_FILE_ICON_8427508422345342 - -#include <vector> -#include <zen/sys_error.h> - -namespace osx -{ -struct ImageData -{ - ImageData(int w, int h) : width(w), height(h), rgb(w* h * 3), alpha(w* h) {} - ImageData(ImageData&& tmp) : width(tmp.width), height(tmp.height) { rgb.swap(tmp.rgb); alpha.swap(tmp.alpha); } - - const int width; - const int height; - std::vector<unsigned char> rgb; //rgb-byte order for use with wxImage - std::vector<unsigned char> alpha; - -private: - ImageData(const ImageData&); - ImageData& operator=(const ImageData&); -}; - -ImageData getThumbnail(const char* filename, int requestedSize); //throw SysError -ImageData getFileIcon (const char* filename, int requestedSize); //throw SysError -ImageData getDefaultFileIcon (int requestedSize); //throw SysError -ImageData getDefaultFolderIcon(int requestedSize); //throw SysError -} - -#endif //OSX_FILE_ICON_8427508422345342 diff --git a/FreeFileSync/Source/lib/osx_file_icon.mm b/FreeFileSync/Source/lib/osx_file_icon.mm deleted file mode 100644 index e6b384d3..00000000 --- a/FreeFileSync/Source/lib/osx_file_icon.mm +++ /dev/null @@ -1,179 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "osx_file_icon.h" -#include <zen/osx_throw_exception.h> -#include <zen/scope_guard.h> -#include <zen/basic_math.h> - -namespace -{ -osx::ImageData extractBytes(NSImage* nsImg, int requestedSize) //throw SysError; NSException? -{ - /* - wxBitmap(NSImage*) is not good enough: it calls "[NSBitmapImageRep imageRepWithData:[img TIFFRepresentation]]" - => inefficient: TIFFRepresentation converts all contained images of an NSImage - => lacking: imageRepWithData extracts the first contained image only! - => wxBitmap(NSImage*) is wxCocoa only, deprecated! - => wxWidgets generally is not thread-safe so care must be taken to use wxBitmap from main thread only! (e.g. race-condition on non-atomic ref-count!!!) - - -> we need only a single bitmap at a specific size => extract raw bytes for use with wxImage in a thread-safe way! - */ - - //we choose the Core Graphics solution; for the equivalent App-Kit way see: http://www.cocoabuilder.com/archive/cocoa/193131-is-lockfocus-main-thread-specific.html#193191 - - ZEN_OSX_ASSERT(requestedSize > 0); - NSRect rectProposed = NSMakeRect(0, 0, requestedSize, requestedSize); //this is merely a hint! - - CGImageRef imgRef = [nsImg CGImageForProposedRect:&rectProposed context:nil hints:nil]; - ZEN_OSX_ASSERT(imgRef != NULL); //can this fail? not documented; ownership?? not documented! - - const size_t width = ::CGImageGetWidth (imgRef); - const size_t height = ::CGImageGetHeight(imgRef); - - ZEN_OSX_ASSERT(width > 0 && height > 0 && requestedSize > 0); - - int trgWidth = width; - int trgHeight = height; - - const int maxExtent = std::max(width, height); //don't stretch small images, but shrink large ones instead! - if (requestedSize < maxExtent) - { - trgWidth = width * requestedSize / maxExtent; - trgHeight = height * requestedSize / maxExtent; - } - - CGColorSpaceRef colorSpace = ::CGColorSpaceCreateDeviceRGB(); - ZEN_OSX_ASSERT(colorSpace != NULL); //may fail - ZEN_ON_SCOPE_EXIT(::CGColorSpaceRelease(colorSpace)); - - std::vector<unsigned char> buf(trgWidth* trgHeight * 4); //32-bit ARGB, little endian byte order -> already initialized with 0 = fully transparent - - //supported color spaces: https://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_context/dq_context.html#//apple_ref/doc/uid/TP30001066-CH203-BCIBHHBB - CGContextRef ctxRef = ::CGBitmapContextCreate(&buf[0], //void *data, - trgWidth, //size_t width, - trgHeight, //size_t height, - 8, //size_t bitsPerComponent, - 4 * trgWidth, //size_t bytesPerRow, - colorSpace, //CGColorSpaceRef colorspace, - kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little); //CGBitmapInfo bitmapInfo - ZEN_OSX_ASSERT(ctxRef != NULL); - ZEN_ON_SCOPE_EXIT(::CGContextRelease(ctxRef)); - - ::CGContextDrawImage(ctxRef, CGRectMake(0, 0, trgWidth, trgHeight), imgRef); //can this fail? not documented - - //::CGContextFlush(ctxRef); //"If you pass [...] a bitmap context, this function does nothing." - - osx::ImageData imgOut(trgWidth, trgHeight); - - auto it = buf.begin(); - auto itOutRgb = imgOut.rgb.begin(); - auto itOutAlpha = imgOut.alpha.begin(); - for (int i = 0; i < trgWidth * trgHeight; ++i) - { - const unsigned char b = *it++; - const unsigned char g = *it++; - const unsigned char r = *it++; - const unsigned char a = *it++; - - //unsigned arithmetics caveat! - auto demultiplex = [&](unsigned char c) { return static_cast<unsigned char>(numeric::clampCpy(a == 0 ? 0 : (c * 255 + a - 1) / a, 0, 255)); }; //=ceil(c * 255 / a) - - *itOutRgb++ = demultiplex(r); - *itOutRgb++ = demultiplex(g); - *itOutRgb++ = demultiplex(b); - *itOutAlpha++ = a; - } - - return imgOut; -} -} - - -osx::ImageData osx::getThumbnail(const char* filename, int requestedSize) //throw SysError -{ - @try - { - @autoreleasepool - { - NSString* nsFile = [NSString stringWithCString:filename encoding:NSUTF8StringEncoding]; - ZEN_OSX_ASSERT(nsFile != nil); //throw SysError; can this fail? not documented - //stringWithCString returns string which is already set to autorelease! - - NSImage* nsImg = [[[NSImage alloc] initWithContentsOfFile:nsFile] autorelease]; - ZEN_OSX_ASSERT(nsImg != nil); //may fail - - return extractBytes(nsImg, requestedSize); //throw SysError - } - } - @catch(NSException* e) - { - throwSysError(e); //throw SysError - } -} - - -osx::ImageData osx::getFileIcon(const char* filename, int requestedSize) //throw SysError -{ - @try - { - @autoreleasepool - { - NSString* nsFile = [NSString stringWithCString:filename encoding:NSUTF8StringEncoding]; - ZEN_OSX_ASSERT(nsFile != nil); //throw SysError; can this fail? not documented - //stringWithCString returns string which is already set to autorelease! - - NSImage* nsImg = [[NSWorkspace sharedWorkspace] iconForFile:nsFile]; - ZEN_OSX_ASSERT(nsImg != nil); //can this fail? not documented - - return extractBytes(nsImg, requestedSize); //throw SysError - } - } - @catch (NSException* e) - { - throwSysError(e); //throw SysError - } -} - - -osx::ImageData osx::getDefaultFileIcon(int requestedSize) //throw SysError -{ - @try - { - @autoreleasepool - { - NSImage* nsImg = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericDocumentIcon)]; - //NSImage* nsImg = [[NSWorkspace sharedWorkspace] iconForFileType:@"dat"]; - ZEN_OSX_ASSERT(nsImg != nil); //can this fail? not documented - - return extractBytes(nsImg, requestedSize); //throw SysError - } - } - @catch (NSException* e) - { - throwSysError(e); //throw SysError - } -} - - -osx::ImageData osx::getDefaultFolderIcon(int requestedSize) //throw SysError -{ - @try - { - @autoreleasepool - { - NSImage* nsImg = [NSImage imageNamed:NSImageNameFolder]; - //NSImage* nsImg = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericFolderIcon)]; - ZEN_OSX_ASSERT(nsImg != nil); //may fail - - return extractBytes(nsImg, requestedSize); //throw SysError - } - } - @catch (NSException* e) - { - throwSysError(e); //throw SysError - } -} diff --git a/FreeFileSync/Source/lib/parallel_scan.cpp b/FreeFileSync/Source/lib/parallel_scan.cpp index 18ac4216..930078b5 100644 --- a/FreeFileSync/Source/lib/parallel_scan.cpp +++ b/FreeFileSync/Source/lib/parallel_scan.cpp @@ -91,14 +91,14 @@ DiskInfo retrieveDiskInfo(const Zstring& pathName) std::vector<char> buffer(sizeof(VOLUME_DISK_EXTENTS) + sizeof(DISK_EXTENT)); //reserve buffer for at most one disk! call below will then fail if volume spans multiple disks! DWORD bytesReturned = 0; - if (!::DeviceIoControl(hVolume, // handle to device - IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, // dwIoControlCode - nullptr, // lpInBuffer - 0, // nInBufferSize - &buffer[0], // output buffer - static_cast<DWORD>(buffer.size()), // size of output buffer - &bytesReturned, // number of bytes returned - nullptr)) // OVERLAPPED structure + if (!::DeviceIoControl(hVolume, //_In_ HANDLE hDevice, + IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, //_In_ DWORD dwIoControlCode, + nullptr, //_In_opt_ LPVOID lpInBuffer, + 0, //_In_ DWORD nInBufferSize, + &buffer[0], //_Out_opt_ LPVOID lpOutBuffer, + static_cast<DWORD>(buffer.size()), //_In_ DWORD nOutBufferSize, + &bytesReturned, //_Out_opt_ LPDWORD lpBytesReturned + nullptr)) //_Inout_opt_ LPOVERLAPPED lpOverlapped return output; const VOLUME_DISK_EXTENTS& volDisks = *reinterpret_cast<VOLUME_DISK_EXTENTS*>(&buffer[0]); @@ -313,13 +313,13 @@ public: relNameParentPf_(relNameParentPf), output_(output) {} - virtual void onFile (const Zchar* shortName, const Zstring& filepath, const FileInfo& details); - virtual HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details); - virtual TraverseCallback* onDir(const Zchar* shortName, const Zstring& dirpath); - virtual void releaseDirTraverser(TraverseCallback* trav); + void onFile (const Zchar* shortName, const Zstring& filepath, const FileInfo& details) override; + HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) override; + TraverseCallback* onDir(const Zchar* shortName, const Zstring& dirpath) override; + void releaseDirTraverser(TraverseCallback* trav) override; - virtual HandleError reportDirError (const std::wstring& msg, size_t retryNumber); - virtual HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName); + HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override; + HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) override; private: TraverserShared& cfg; @@ -467,30 +467,6 @@ DirCallback::HandleError DirCallback::reportItemError(const std::wstring& msg, s return ON_ERROR_IGNORE; } - -#ifdef ZEN_WIN -class DstHackCallbackImpl : public DstHackCallback -{ -public: - DstHackCallbackImpl(AsyncCallback& acb, long threadID) : - acb_(acb), - threadID_(threadID), - textApplyingDstHack(replaceCpy(_("Encoding extended time information: %x"), L"%x", L"\n%x")) {} - -private: - virtual void requestUiRefresh(const Zstring& filepath) //applying DST hack imposes significant one-time performance drawback => callback to inform user - { - boost::this_thread::interruption_point(); - - acb_.reportCurrentStatus(replaceCpy(textApplyingDstHack, L"%x", fmtFileName(filepath)), threadID_); - } - - AsyncCallback& acb_; - long threadID_; - const std::wstring textApplyingDstHack; -}; -#endif - //------------------------------------------------------------------------------------------ class WorkerThread @@ -523,14 +499,8 @@ public: Zstring(), dirOutput_.dirCont); - DstHackCallback* dstCallbackPtr = nullptr; -#ifdef ZEN_WIN - DstHackCallbackImpl dstCallback(*acb_, threadID_); - dstCallbackPtr = &dstCallback; -#endif - //get all files and folders from directoryPostfixed (and subdirectories) - traverseFolder(dirKey_.dirpath_, traverser, dstCallbackPtr); //exceptions may be thrown! + traverseFolder(dirKey_.dirpath_, traverser); //exceptions may be thrown! } private: diff --git a/FreeFileSync/Source/lib/parse_lng.h b/FreeFileSync/Source/lib/parse_lng.h index 12e5290b..9fbebff4 100644 --- a/FreeFileSync/Source/lib/parse_lng.h +++ b/FreeFileSync/Source/lib/parse_lng.h @@ -139,8 +139,8 @@ public: private: struct Item { virtual ~Item() {} virtual bool hasTranslation() const = 0; }; - struct RegularItem : public Item { RegularItem(const TranslationMap ::value_type& val) : value(val) {} virtual bool hasTranslation() const { return !value.second.empty(); } TranslationMap ::value_type value; }; - struct PluralItem : public Item { PluralItem (const TranslationPluralMap::value_type& val) : value(val) {} virtual bool hasTranslation() const { return !value.second.empty(); } TranslationPluralMap::value_type value; }; + struct RegularItem : public Item { RegularItem(const TranslationMap ::value_type& val) : value(val) {} bool hasTranslation() const override { return !value.second.empty(); } TranslationMap ::value_type value; }; + struct PluralItem : public Item { PluralItem (const TranslationPluralMap::value_type& val) : value(val) {} bool hasTranslation() const override { return !value.second.empty(); } TranslationPluralMap::value_type value; }; const TranslationNewItemPos newItemPos_; std::list<std::shared_ptr<Item>> sequence; //ordered list of translation elements @@ -212,28 +212,28 @@ private: KnownTokens() { //header information - tokens.insert(std::make_pair(Token::TK_HEADER_BEGIN, "<header>")); - tokens.insert(std::make_pair(Token::TK_HEADER_END, "</header>")); - tokens.insert(std::make_pair(Token::TK_LANG_NAME_BEGIN, "<language>")); - tokens.insert(std::make_pair(Token::TK_LANG_NAME_END, "</language>")); - tokens.insert(std::make_pair(Token::TK_TRANS_NAME_BEGIN, "<translator>")); - tokens.insert(std::make_pair(Token::TK_TRANS_NAME_END, "</translator>")); - tokens.insert(std::make_pair(Token::TK_LOCALE_NAME_BEGIN, "<locale>")); - tokens.insert(std::make_pair(Token::TK_LOCALE_NAME_END, "</locale>")); - tokens.insert(std::make_pair(Token::TK_FLAG_FILE_BEGIN, "<image>")); - tokens.insert(std::make_pair(Token::TK_FLAG_FILE_END, "</image>")); - tokens.insert(std::make_pair(Token::TK_PLURAL_COUNT_BEGIN, "<plural_count>")); - tokens.insert(std::make_pair(Token::TK_PLURAL_COUNT_END, "</plural_count>")); - tokens.insert(std::make_pair(Token::TK_PLURAL_DEF_BEGIN, "<plural_definition>")); - tokens.insert(std::make_pair(Token::TK_PLURAL_DEF_END, "</plural_definition>")); + tokens.emplace(Token::TK_HEADER_BEGIN, "<header>"); + tokens.emplace(Token::TK_HEADER_END, "</header>"); + tokens.emplace(Token::TK_LANG_NAME_BEGIN, "<language>"); + tokens.emplace(Token::TK_LANG_NAME_END, "</language>"); + tokens.emplace(Token::TK_TRANS_NAME_BEGIN, "<translator>"); + tokens.emplace(Token::TK_TRANS_NAME_END, "</translator>"); + tokens.emplace(Token::TK_LOCALE_NAME_BEGIN, "<locale>"); + tokens.emplace(Token::TK_LOCALE_NAME_END, "</locale>"); + tokens.emplace(Token::TK_FLAG_FILE_BEGIN, "<image>"); + tokens.emplace(Token::TK_FLAG_FILE_END, "</image>"); + tokens.emplace(Token::TK_PLURAL_COUNT_BEGIN, "<plural_count>"); + tokens.emplace(Token::TK_PLURAL_COUNT_END, "</plural_count>"); + tokens.emplace(Token::TK_PLURAL_DEF_BEGIN, "<plural_definition>"); + tokens.emplace(Token::TK_PLURAL_DEF_END, "</plural_definition>"); //item level - tokens.insert(std::make_pair(Token::TK_SRC_BEGIN, "<source>")); - tokens.insert(std::make_pair(Token::TK_SRC_END, "</source>")); - tokens.insert(std::make_pair(Token::TK_TRG_BEGIN, "<target>")); - tokens.insert(std::make_pair(Token::TK_TRG_END, "</target>")); - tokens.insert(std::make_pair(Token::TK_PLURAL_BEGIN, "<pluralform>")); - tokens.insert(std::make_pair(Token::TK_PLURAL_END, "</pluralform>")); + tokens.emplace(Token::TK_SRC_BEGIN, "<source>"); + tokens.emplace(Token::TK_SRC_END, "</source>"); + tokens.emplace(Token::TK_TRG_BEGIN, "<target>"); + tokens.emplace(Token::TK_TRG_END, "</target>"); + tokens.emplace(Token::TK_PLURAL_BEGIN, "<pluralform>"); + tokens.emplace(Token::TK_PLURAL_END, "</pluralform>"); } TokenMap tokens; }; @@ -418,7 +418,7 @@ private: consumeToken(Token::TK_TRG_END); validateTranslation(original, translation); //throw throw ParsingError - out.insert(std::make_pair(original, translation)); + out.emplace(original, translation); } void parsePlural(TranslationPluralMap& pluralOut, const parse_plural::PluralFormInfo& pluralInfo) @@ -453,7 +453,7 @@ private: const SingularPluralPair original(engSingular, engPlural); validateTranslation(original, pluralList, pluralInfo); - pluralOut.insert(std::make_pair(original, pluralList)); + pluralOut.emplace(original, pluralList); } void validateTranslation(const std::string& original, const std::string& translation) //throw ParsingError diff --git a/FreeFileSync/Source/lib/parse_plural.h b/FreeFileSync/Source/lib/parse_plural.h index bac933c9..c19714de 100644 --- a/FreeFileSync/Source/lib/parse_plural.h +++ b/FreeFileSync/Source/lib/parse_plural.h @@ -122,7 +122,7 @@ struct BinaryExp : public Expr<typename StlOp::result_type> typedef std::shared_ptr<Expr<typename StlOp::second_argument_type>> ExpRhs; BinaryExp(const ExpLhs& lhs, const ExpRhs& rhs, StlOp biop) : lhs_(lhs), rhs_(rhs), biop_(biop) { assert(lhs && rhs); } - virtual typename StlOp::result_type eval() const { return biop_(lhs_->eval(), rhs_->eval()); } + typename StlOp::result_type eval() const override { return biop_(lhs_->eval(), rhs_->eval()); } private: ExpLhs lhs_; ExpRhs rhs_; @@ -146,7 +146,7 @@ struct ConditionalExp : public Expr<T> const std::shared_ptr<Expr<T>>& thenExp, const std::shared_ptr<Expr<T>>& elseExp) : ifExp_(ifExp), thenExp_(thenExp), elseExp_(elseExp) { assert(ifExp && thenExp && elseExp); } - virtual typename Expr<T>::ValueType eval() const { return ifExp_->eval() ? thenExp_->eval() : elseExp_->eval(); } + typename Expr<T>::ValueType eval() const override { return ifExp_->eval() ? thenExp_->eval() : elseExp_->eval(); } private: std::shared_ptr<Expr<bool>> ifExp_; std::shared_ptr<Expr<T>> thenExp_; @@ -156,7 +156,7 @@ private: struct ConstNumberExp : public Expr<std::int64_t> { ConstNumberExp(std::int64_t n) : n_(n) {} - virtual std::int64_t eval() const { return n_; } + std::int64_t eval() const override { return n_; } private: std::int64_t n_; }; @@ -164,7 +164,7 @@ private: struct VariableNumberNExp : public Expr<std::int64_t> { VariableNumberNExp(std::int64_t& n) : n_(n) {} - virtual std::int64_t eval() const { return n_; } + std::int64_t eval() const override { return n_; } private: std::int64_t& n_; }; @@ -205,21 +205,21 @@ class Scanner public: Scanner(const std::string& stream) : stream_(stream), pos(stream_.begin()) { - tokens.push_back(std::make_pair("?" , Token::TK_TERNARY_QUEST)); - tokens.push_back(std::make_pair(":" , Token::TK_TERNARY_COLON)); - tokens.push_back(std::make_pair("||", Token::TK_OR )); - tokens.push_back(std::make_pair("&&", Token::TK_AND )); - tokens.push_back(std::make_pair("==", Token::TK_EQUAL )); - tokens.push_back(std::make_pair("!=", Token::TK_NOT_EQUAL )); - tokens.push_back(std::make_pair("<=", Token::TK_LESS_EQUAL )); - tokens.push_back(std::make_pair("<" , Token::TK_LESS )); - tokens.push_back(std::make_pair(">=", Token::TK_GREATER_EQUAL)); - tokens.push_back(std::make_pair(">" , Token::TK_GREATER )); - tokens.push_back(std::make_pair("%" , Token::TK_MODULUS )); - tokens.push_back(std::make_pair("n" , Token::TK_VARIABLE_N )); - tokens.push_back(std::make_pair("N" , Token::TK_VARIABLE_N )); - tokens.push_back(std::make_pair("(" , Token::TK_BRACKET_LEFT )); - tokens.push_back(std::make_pair(")" , Token::TK_BRACKET_RIGHT)); + tokens.emplace_back("?" , Token::TK_TERNARY_QUEST); + tokens.emplace_back(":" , Token::TK_TERNARY_COLON); + tokens.emplace_back("||", Token::TK_OR ); + tokens.emplace_back("&&", Token::TK_AND ); + tokens.emplace_back("==", Token::TK_EQUAL ); + tokens.emplace_back("!=", Token::TK_NOT_EQUAL ); + tokens.emplace_back("<=", Token::TK_LESS_EQUAL ); + tokens.emplace_back("<" , Token::TK_LESS ); + tokens.emplace_back(">=", Token::TK_GREATER_EQUAL); + tokens.emplace_back(">" , Token::TK_GREATER ); + tokens.emplace_back("%" , Token::TK_MODULUS ); + tokens.emplace_back("n" , Token::TK_VARIABLE_N ); + tokens.emplace_back("N" , Token::TK_VARIABLE_N ); + tokens.emplace_back("(" , Token::TK_BRACKET_LEFT ); + tokens.emplace_back(")" , Token::TK_BRACKET_RIGHT); } Token nextToken() diff --git a/FreeFileSync/Source/lib/process_xml.cpp b/FreeFileSync/Source/lib/process_xml.cpp index 98262882..5f7dbf14 100644 --- a/FreeFileSync/Source/lib/process_xml.cpp +++ b/FreeFileSync/Source/lib/process_xml.cpp @@ -7,7 +7,7 @@ #include "process_xml.h" #include <utility> #include <zenxml/xml.h> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/file_io.h> #include <zen/xml_io.h> #include "ffs_paths.h" @@ -794,11 +794,11 @@ void readConfig(const XmlIn& in, SyncConfig& syncCfg) void readConfig(const XmlIn& in, FilterConfig& filter) { - std::vector<Zstring> tmp = splitFilterByLines(filter.includeFilter); //default value + std::vector<Zstring> tmp = splitFilterByLines(filter.includeFilter); //save default value in["Include"](tmp); filter.includeFilter = mergeFilterLines(tmp); - std::vector<Zstring> tmp2 = splitFilterByLines(filter.excludeFilter); //default value + std::vector<Zstring> tmp2 = splitFilterByLines(filter.excludeFilter); //save default value in["Exclude"](tmp2); filter.excludeFilter = mergeFilterLines(tmp2); diff --git a/FreeFileSync/Source/lib/process_xml.h b/FreeFileSync/Source/lib/process_xml.h index 6d834922..6f07e0c9 100644 --- a/FreeFileSync/Source/lib/process_xml.h +++ b/FreeFileSync/Source/lib/process_xml.h @@ -209,17 +209,17 @@ struct XmlGlobalSettings { //default external apps will be translated "on the fly"!!! First entry will be used for [Enter] or mouse double-click! #ifdef ZEN_WIN - externelApplications.push_back(std::make_pair(L"Show in Explorer", L"explorer /select, \"%item_path%\"")); - externelApplications.push_back(std::make_pair(L"Open with default application", L"\"%item_path%\"")); + externelApplications.emplace_back(L"Show in Explorer", L"explorer /select, \"%item_path%\""); + externelApplications.emplace_back(L"Open with default application", L"\"%item_path%\""); //mark for extraction: _("Show in Explorer") //mark for extraction: _("Open with default application") #elif defined ZEN_LINUX - externelApplications.push_back(std::make_pair(L"Browse directory", L"xdg-open \"%item_folder%\"")); - externelApplications.push_back(std::make_pair(L"Open with default application", L"xdg-open \"%item_path%\"")); + externelApplications.emplace_back(L"Browse directory", L"xdg-open \"%item_folder%\""); + externelApplications.emplace_back(L"Open with default application", L"xdg-open \"%item_path%\""); //mark for extraction: _("Browse directory") Linux doesn't use the term "folder" #elif defined ZEN_MAC - externelApplications.push_back(std::make_pair(L"Browse directory", L"open -R \"%item_path%\"")); - externelApplications.push_back(std::make_pair(L"Open with default application", L"open \"%item_path%\"")); + externelApplications.emplace_back(L"Browse directory", L"open -R \"%item_path%\""); + externelApplications.emplace_back(L"Open with default application", L"open \"%item_path%\""); #endif } diff --git a/FreeFileSync/Source/lib/resolve_path.cpp b/FreeFileSync/Source/lib/resolve_path.cpp index 4688ccbd..a589260f 100644 --- a/FreeFileSync/Source/lib/resolve_path.cpp +++ b/FreeFileSync/Source/lib/resolve_path.cpp @@ -10,7 +10,7 @@ #ifdef ZEN_WIN #include <zen/long_path_prefix.h> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/win.h> //includes "windows.h" #include <zen/dll.h> #include <Shlobj.h> @@ -112,7 +112,7 @@ private: { Zstring dirpath = buffer; if (!dirpath.empty()) - output.insert(std::make_pair(paramName, dirpath)); + output.emplace(paramName, dirpath); } }; @@ -138,7 +138,7 @@ private: Zstring dirpath = path; if (!dirpath.empty()) - output.insert(std::make_pair(paramName, dirpath)); + output.emplace(paramName, dirpath); } } }; @@ -224,7 +224,7 @@ std::unique_ptr<Zstring> getEnvironmentVar(const Zstring& envName) //return null value.length() >= 2) value = wxString(value.c_str() + 1, value.length() - 2); - return make_unique<Zstring>(utfCvrtTo<Zstring>(value)); + return zen::make_unique<Zstring>(utfCvrtTo<Zstring>(value)); } @@ -235,13 +235,13 @@ std::unique_ptr<Zstring> resolveMacro(const Zstring& macro, //macro without %-ch //there exist environment variables named %TIME%, %DATE% so check for our internal macros first! if (equalNoCase(macro, Zstr("time"))) - return make_unique<Zstring>(formatTime<Zstring>(Zstr("%H%M%S"))); + return zen::make_unique<Zstring>(formatTime<Zstring>(Zstr("%H%M%S"))); if (equalNoCase(macro, Zstr("date"))) - return make_unique<Zstring>(formatTime<Zstring>(FORMAT_ISO_DATE)); + return zen::make_unique<Zstring>(formatTime<Zstring>(FORMAT_ISO_DATE)); if (equalNoCase(macro, Zstr("timestamp"))) - return make_unique<Zstring>(formatTime<Zstring>(Zstr("%Y-%m-%d %H%M%S"))); //e.g. "2012-05-15 131513" + return zen::make_unique<Zstring>(formatTime<Zstring>(Zstr("%Y-%m-%d %H%M%S"))); //e.g. "2012-05-15 131513" std::unique_ptr<Zstring> cand; auto processPhrase = [&](const Zchar* phrase, const Zchar* format) -> bool @@ -249,7 +249,7 @@ std::unique_ptr<Zstring> resolveMacro(const Zstring& macro, //macro without %-ch if (!equalNoCase(macro, phrase)) return false; - cand = make_unique<Zstring>(formatTime<Zstring>(format)); + cand = zen::make_unique<Zstring>(formatTime<Zstring>(format)); return true; }; @@ -266,7 +266,7 @@ std::unique_ptr<Zstring> resolveMacro(const Zstring& macro, //macro without %-ch { auto it = std::find_if(ext.begin(), ext.end(), [&](const std::pair<Zstring, Zstring>& p) { return equalNoCase(macro, p.first); }); if (it != ext.end()) - return make_unique<Zstring>(it->second); + return zen::make_unique<Zstring>(it->second); } //try to resolve as environment variable @@ -279,7 +279,7 @@ std::unique_ptr<Zstring> resolveMacro(const Zstring& macro, //macro without %-ch const auto& csidlMap = CsidlConstants::get(); auto it = csidlMap.find(macro); if (it != csidlMap.end()) - return make_unique<Zstring>(it->second); + return zen::make_unique<Zstring>(it->second); } #endif @@ -471,7 +471,7 @@ void getDirectoryAliasesRecursive(const Zstring& dirpath, std::set<Zstring, Less auto addEnvVar = [&](const Zstring& envName) { if (std::unique_ptr<Zstring> value = getEnvironmentVar(envName)) - envToDir.insert(std::make_pair(envName, *value)); + envToDir.emplace(envName, *value); }; #ifdef ZEN_WIN addEnvVar(L"AllUsersProfile"); // C:\ProgramData @@ -498,11 +498,7 @@ void getDirectoryAliasesRecursive(const Zstring& dirpath, std::set<Zstring, Less auto pathStartsWith = [](const Zstring& path, const Zstring& prefix) -> bool { #if defined ZEN_WIN || defined ZEN_MAC - Zstring tmp = path; - Zstring tmp2 = prefix; - ::makeUpper(tmp); - ::makeUpper(tmp2); - return startsWith(tmp, tmp2); + return startsWith(makeUpperCopy(path), makeUpperCopy(prefix)); #elif defined ZEN_LINUX return startsWith(path, prefix); #endif diff --git a/FreeFileSync/Source/lib/shadow.cpp b/FreeFileSync/Source/lib/shadow.cpp deleted file mode 100644 index be9ba1f3..00000000 --- a/FreeFileSync/Source/lib/shadow.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "shadow.h" -#include <stdexcept> -#include <zen/win.h> //includes "windows.h" -#include <zen/dll.h> -#include <zen/win_ver.h> -#include <zen/assert_static.h> -#include <zen/long_path_prefix.h> -#include <zen/symlink_target.h> -#include "../dll/ShadowCopy/shadow.h" -#include <zen/scope_guard.h> - -using namespace zen; -using namespace shadow; - - -namespace -{ -bool runningWOW64() //test if process is running under WOW64 (reference http://msdn.microsoft.com/en-us/library/ms684139(VS.85).aspx) -{ - typedef BOOL (WINAPI* IsWow64ProcessFun)(HANDLE hProcess, PBOOL Wow64Process); - - const SysDllFun<IsWow64ProcessFun> isWow64Process(L"kernel32.dll", "IsWow64Process"); - if (isWow64Process) - { - BOOL isWow64 = FALSE; - if (isWow64Process(::GetCurrentProcess(), &isWow64)) - return isWow64 != FALSE; - } - return false; -} -} - -//############################################################################################################# - -class ShadowCopy::ShadowVolume -{ -public: - ShadowVolume(const Zstring& volumeNamePf) : //throw FileError - createShadowCopy (getDllName(), funName_createShadowCopy), - releaseShadowCopy (getDllName(), funName_releaseShadowCopy), - getShadowVolume (getDllName(), funName_getShadowVolume), - getLastErrorMessage(getDllName(), funName_getLastErrorMessage), - backupHandle(nullptr) - { - //VSS does not support running under WOW64 except for Windows XP and Windows Server 2003 - //reference: http://msdn.microsoft.com/en-us/library/aa384627(VS.85).aspx - if (runningWOW64()) - throw FileError(_("Cannot access the Volume Shadow Copy Service."), - _("Please use FreeFileSync 64-bit version to create shadow copies on this system.")); - - //check if shadow copy dll was loaded correctly - if (!createShadowCopy || !releaseShadowCopy || !getShadowVolume || !getLastErrorMessage) - throw FileError(_("Cannot access the Volume Shadow Copy Service."), - replaceCpy(_("Cannot load file %x."), L"%x", fmtFileName(getDllName()))); - - //--------------------------------------------------------------------------------------------------------- - //start volume shadow copy service: - backupHandle = createShadowCopy(volumeNamePf.c_str()); - if (!backupHandle) - throw FileError(_("Cannot access the Volume Shadow Copy Service."), getLastErrorMessage() + std::wstring(L" Volume: ") + fmtFileName(volumeNamePf)); - - shadowVolPf = appendSeparator(getShadowVolume(backupHandle)); //shadowVolName NEVER has a trailing backslash - } - - ~ShadowVolume() { releaseShadowCopy(backupHandle); } //fast! no performance optimization necessary - - Zstring geNamePf() const { return shadowVolPf; } //with trailing path separator - -private: - ShadowVolume (const ShadowVolume&) = delete; - ShadowVolume& operator=(const ShadowVolume&) = delete; - - const DllFun<FunType_createShadowCopy > createShadowCopy; - const DllFun<FunType_releaseShadowCopy > releaseShadowCopy; - const DllFun<FunType_getShadowVolume > getShadowVolume; - const DllFun<FunType_getLastErrorMessage> getLastErrorMessage; - - Zstring shadowVolPf; - ShadowHandle backupHandle; -}; - -//############################################################################################################# - -Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile, const std::function<void(const Zstring& volumeNamePf)>& onBeforeMakeVolumeCopy) -{ - Zstring filepathFinal = inputFile; - - //try to resolve symlinks and junctions: - //1. symlinks: we need to retrieve the target path, else we would just return a symlink on a VSS volume while the target outside were still locked! - //2. junctions: C:\Users\<username> is a junction that may link to e.g. D:\Users\<username>, so GetVolumePathName() returns "D:\" => "Volume name %x not part of file name %y." - if (vistaOrLater()) - filepathFinal = getResolvedFilePath(inputFile); //throw FileError; requires Vista or later! - //-> returns paths with \\?\ prefix! => make sure to avoid duplicate shadow copies for volume paths with/without prefix - - DWORD bufferSize = 10000; - std::vector<wchar_t> volBuffer(bufferSize); - if (!::GetVolumePathName(filepathFinal.c_str(), //__in LPCTSTR lpszFileName, - &volBuffer[0], //__out LPTSTR lpszVolumePathName, - bufferSize)) //__in DWORD cchBufferLength - throwFileError(replaceCpy(_("Cannot determine volume name for %x."), L"%x", fmtFileName(filepathFinal)), L"GetVolumePathName", ::GetLastError()); - - const Zstring volumeNamePf = appendSeparator(&volBuffer[0]); //msdn: if buffer is 1 char too short, GetVolumePathName() may skip last separator without error! - - //input file is always absolute! directory formatting takes care of this! Therefore volume name can always be found. - const size_t pos = filepathFinal.find(volumeNamePf); //filepathFinal needs NOT to begin with volumeNamePf: consider \\?\ prefix! - if (pos == Zstring::npos) - throw FileError(replaceCpy(replaceCpy(_("Volume name %x is not part of file path %y."), - L"%x", fmtFileName(volumeNamePf)), - L"%y", fmtFileName(filepathFinal))); - - //get or create instance of shadow volume - auto it = shadowVol.find(volumeNamePf); - if (it == shadowVol.end()) - { - onBeforeMakeVolumeCopy(volumeNamePf); //notify client before (potentially) blocking some time - auto newEntry = std::make_shared<ShadowVolume>(volumeNamePf); //throw FileError - it = shadowVol.insert(std::make_pair(volumeNamePf, newEntry)).first; - } - - //return filepath alias on shadow copy volume - return it->second->geNamePf() + Zstring(filepathFinal.c_str() + pos + volumeNamePf.length()); -} diff --git a/FreeFileSync/Source/lib/shadow.h b/FreeFileSync/Source/lib/shadow.h deleted file mode 100644 index 4f2dbf32..00000000 --- a/FreeFileSync/Source/lib/shadow.h +++ /dev/null @@ -1,36 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef SHADOW_H_INCLUDED -#define SHADOW_H_INCLUDED - -#include <map> -#include <memory> -#include <functional> -#include <zen/zstring.h> -#include <zen/file_error.h> - -namespace shadow -{ -class ShadowCopy //take and buffer Windows Volume Shadow Copy snapshots as needed -{ -public: - ShadowCopy() {} - - //return filepath on shadow copy volume - follows symlinks! - Zstring makeShadowCopy(const Zstring& inputFile, const std::function<void(const Zstring& volumeNamePf)>& onBeforeMakeVolumeCopy); //throw FileError - -private: - ShadowCopy (const ShadowCopy&) = delete; - ShadowCopy& operator=(const ShadowCopy&) = delete; - - class ShadowVolume; - typedef std::map<Zstring, std::shared_ptr<ShadowVolume>, LessFilename> VolNameShadowMap; - VolNameShadowMap shadowVol; -}; -} - -#endif //SHADOW_H_INCLUDED diff --git a/FreeFileSync/Source/lib/status_handler.h b/FreeFileSync/Source/lib/status_handler.h index fd0c3cb6..1ee23c38 100644 --- a/FreeFileSync/Source/lib/status_handler.h +++ b/FreeFileSync/Source/lib/status_handler.h @@ -59,16 +59,16 @@ public: protected: //implement parts of ProcessCallback - virtual void initNewPhase(int objectsTotal, std::int64_t dataTotal, Phase phaseId) //may throw + void initNewPhase(int objectsTotal, std::int64_t dataTotal, Phase phaseId) override //may throw { currentPhase_ = phaseId; refNumbers(numbersTotal_, currentPhase_) = std::make_pair(objectsTotal, dataTotal); } - virtual void updateProcessedData(int objectsDelta, std::int64_t dataDelta) { updateData(numbersCurrent_, objectsDelta, dataDelta); } //note: these methods MUST NOT throw in order - virtual void updateTotalData (int objectsDelta, std::int64_t dataDelta) { updateData(numbersTotal_ , objectsDelta, dataDelta); } //to properly allow undoing setting of statistics! + void updateProcessedData(int objectsDelta, std::int64_t dataDelta) override { updateData(numbersCurrent_, objectsDelta, dataDelta); } //note: these methods MUST NOT throw in order + void updateTotalData (int objectsDelta, std::int64_t dataDelta) override { updateData(numbersTotal_ , objectsDelta, dataDelta); } //to properly allow undoing setting of statistics! - virtual void requestUiRefresh() //throw X + void requestUiRefresh() override //throw X { if (abortRequested) //triggered by requestAbortion() { @@ -79,26 +79,26 @@ protected: forceUiRefresh(); } - virtual void reportStatus(const std::wstring& text) { statusText_ = text; requestUiRefresh(); /*throw X */ } - virtual void reportInfo (const std::wstring& text) { statusText_ = text; requestUiRefresh(); /*throw X */ } //log text in derived class + void reportStatus(const std::wstring& text) override { if (!abortRequested) statusText_ = text; requestUiRefresh(); /*throw X */ } + void reportInfo (const std::wstring& text) override { if (!abortRequested) statusText_ = text; requestUiRefresh(); /*throw X */ } //log text in derived class //implement AbortCallback - virtual void requestAbortion() + void requestAbortion() override { abortRequested = true; statusText_ = _("Stop requested: Waiting for current operation to finish..."); - } //this does NOT call abortProcessNow() immediately, but when we're out of the C GUI call stack + } //called from GUI code: this does NOT call abortProcessNow() immediately, but when we're out of the C GUI call stack //implement Statistics - virtual Phase currentPhase() const { return currentPhase_; } + Phase currentPhase() const override { return currentPhase_; } - virtual int getObjectsCurrent(Phase phaseId) const { return refNumbers(numbersCurrent_, phaseId).first; } - virtual int getObjectsTotal (Phase phaseId) const { assert(phaseId != PHASE_SCANNING); return refNumbers(numbersTotal_ , phaseId).first; } + int getObjectsCurrent(Phase phaseId) const override { return refNumbers(numbersCurrent_, phaseId).first; } + int getObjectsTotal (Phase phaseId) const override { assert(phaseId != PHASE_SCANNING); return refNumbers(numbersTotal_ , phaseId).first; } - virtual std::int64_t getDataCurrent(Phase phaseId) const { assert(phaseId != PHASE_SCANNING); return refNumbers(numbersCurrent_, phaseId).second; } - virtual std::int64_t getDataTotal (Phase phaseId) const { assert(phaseId != PHASE_SCANNING); return refNumbers(numbersTotal_ , phaseId).second; } + std::int64_t getDataCurrent(Phase phaseId) const override { assert(phaseId != PHASE_SCANNING); return refNumbers(numbersCurrent_, phaseId).second; } + std::int64_t getDataTotal (Phase phaseId) const override { assert(phaseId != PHASE_SCANNING); return refNumbers(numbersTotal_ , phaseId).second; } - virtual const std::wstring& currentStatusText() const { return statusText_; } + const std::wstring& currentStatusText() const override { return statusText_; } bool abortIsRequested() const { return abortRequested; } diff --git a/FreeFileSync/Source/lib/versioning.cpp b/FreeFileSync/Source/lib/versioning.cpp index 9da6bdf0..58648771 100644 --- a/FreeFileSync/Source/lib/versioning.cpp +++ b/FreeFileSync/Source/lib/versioning.cpp @@ -1,7 +1,7 @@ #include "versioning.h" #include <map> #include <cstddef> //required by GCC 4.8.1 to find ptrdiff_t -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/file_traverser.h> #include <zen/string_tools.h> @@ -172,14 +172,13 @@ void moveFile(const Zstring& sourceFile, //throw FileError { auto copyDelete = [&] { + assert(!somethingExists(targetFile)); + //create target if (symlinkExists(sourceFile)) copySymlink(sourceFile, targetFile, false); //throw FileError; don't copy filesystem permissions else - { - auto onDeleteTargetFile = [&]() { assert(!somethingExists(targetFile)); }; - copyFile(sourceFile, targetFile, false, true, onDeleteTargetFile, onUpdateCopyStatus); //throw FileError - permissions "false", transactional copy "true" - } + copyFile(sourceFile, targetFile, false, true, nullptr, onUpdateCopyStatus); //throw FileError - permissions "false", transactional copy "true" //delete source removeFile(sourceFile); //throw FileError; newly copied file is NOT deleted if exception is thrown here! @@ -210,12 +209,12 @@ public: TraverseFilesOneLevel(std::vector<Zstring>& files, std::vector<Zstring>& dirs) : files_(files), dirs_(dirs) {} private: - virtual void onFile(const Zchar* shortName, const Zstring& filepath, const FileInfo& details) + void onFile(const Zchar* shortName, const Zstring& filepath, const FileInfo& details) override { files_.push_back(shortName); } - virtual HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) + HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) override { if (dirExists(linkpath)) //dir symlink dirs_.push_back(shortName); @@ -224,14 +223,14 @@ private: return LINK_SKIP; } - virtual TraverseCallback* onDir(const Zchar* shortName, const Zstring& dirpath) + TraverseCallback* onDir(const Zchar* shortName, const Zstring& dirpath) override { dirs_.push_back(shortName); return nullptr; //DON'T traverse into subdirs; moveDirectory works recursively! } - virtual HandleError reportDirError (const std::wstring& msg, size_t retryNumber) { throw FileError(msg); } - virtual HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) { throw FileError(msg); } + HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override { throw FileError(msg); } + HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) override { throw FileError(msg); } std::vector<Zstring>& files_; std::vector<Zstring>& dirs_; @@ -317,11 +316,11 @@ void FileVersioner::revisionDirImpl(const Zstring& dirpath, const Zstring& relat std::vector<Zstring> dirList; // { TraverseFilesOneLevel tol(fileList, dirList); //throw FileError - traverseFolder(dirpath, tol); // + traverseFolder(dirpath, tol); // } const Zstring dirpathPf = appendSeparator(dirpath); - const Zstring relpathPf = appendSeparator(relativePath); + const Zstring relpathPf = appendSeparator(relativePath); //move files for (const Zstring& shortname : fileList) @@ -352,11 +351,11 @@ public: TraverseVersionsOneLevel(std::vector<Zstring>& files, std::function<void()> updateUI) : files_(files), updateUI_(updateUI) {} private: - virtual void onFile(const Zchar* shortName, const Zstring& filepath, const FileInfo& details) { files_.push_back(shortName); updateUI_(); } - virtual HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) { files_.push_back(shortName); updateUI_(); return LINK_SKIP; } - virtual std::shared_ptr<TraverseCallback> onDir(const Zchar* shortName, const Zstring& dirpath) { updateUI_(); return nullptr; } //DON'T traverse into subdirs - virtual HandleError reportDirError (const std::wstring& msg) { throw FileError(msg); } - virtual HandleError reportItemError(const std::wstring& msg, const Zchar* shortName) { throw FileError(msg); } + void onFile(const Zchar* shortName, const Zstring& filepath, const FileInfo& details) override { files_.push_back(shortName); updateUI_(); } + HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) override { files_.push_back(shortName); updateUI_(); return LINK_SKIP; } + std::shared_ptr<TraverseCallback> onDir(const Zchar* shortName, const Zstring& dirpath) override { updateUI_(); return nullptr; } //DON'T traverse into subdirs + HandleError reportDirError (const std::wstring& msg) override { throw FileError(msg); } + HandleError reportItemError(const std::wstring& msg, const Zchar* shortName) override { throw FileError(msg); } std::vector<Zstring>& files_; std::function<void()> updateUI_; diff --git a/FreeFileSync/Source/structures.cpp b/FreeFileSync/Source/structures.cpp index fa9c8b16..f8716669 100644 --- a/FreeFileSync/Source/structures.cpp +++ b/FreeFileSync/Source/structures.cpp @@ -35,9 +35,9 @@ std::wstring zen::getVariantName(DirectionConfig::Variant var) case DirectionConfig::TWOWAY: return L"<- " + _("Two way") + L" ->"; case DirectionConfig::MIRROR: - return _("Mirror") + L" ->>"; + return _("Mirror") + L" ->"; case DirectionConfig::UPDATE: - return _("Update") + L" ->"; + return _("Update") + L" >"; case DirectionConfig::CUSTOM: return _("Custom"); } @@ -454,7 +454,7 @@ MainConfiguration zen::merge(const std::vector<MainConfiguration>& mainCfgs) auto it = std::find_if(cmpCfgStat.begin(), cmpCfgStat.end(), [&](const std::pair<CompConfig, int>& entry) { return effectivelyEqual(entry.first, cmpCfg); }); if (it == cmpCfgStat.end()) - cmpCfgStat.push_back(std::make_pair(cmpCfg, 1)); + cmpCfgStat.emplace_back(cmpCfg, 1); else ++(it->second); } @@ -464,7 +464,7 @@ MainConfiguration zen::merge(const std::vector<MainConfiguration>& mainCfgs) auto it = std::find_if(syncCfgStat.begin(), syncCfgStat.end(), [&](const std::pair<SyncConfig, int>& entry) { return effectivelyEqual(entry.first, syncCfg); }); if (it == syncCfgStat.end()) - syncCfgStat.push_back(std::make_pair(syncCfg, 1)); + syncCfgStat.emplace_back(syncCfg, 1); else ++(it->second); } diff --git a/FreeFileSync/Source/structures.h b/FreeFileSync/Source/structures.h index bf0f3baf..8f718d15 100644 --- a/FreeFileSync/Source/structures.h +++ b/FreeFileSync/Source/structures.h @@ -10,7 +10,6 @@ #include <vector> #include <memory> #include <zen/zstring.h> -#include <zen/assert_static.h> namespace zen { diff --git a/FreeFileSync/Source/synchronization.cpp b/FreeFileSync/Source/synchronization.cpp index 2c3af007..8aed5d16 100644 --- a/FreeFileSync/Source/synchronization.cpp +++ b/FreeFileSync/Source/synchronization.cpp @@ -12,7 +12,7 @@ #include <zen/format_unit.h> #include <zen/scope_guard.h> #include <zen/process_priority.h> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/recycler.h> #include <zen/optional.h> #include <zen/symlink_target.h> @@ -142,7 +142,7 @@ void SyncStatistics::processFile(const FilePair& fileObj) break; case SO_UNRESOLVED_CONFLICT: - conflictMsgs.push_back(std::make_pair(fileObj.getPairRelativePath(), fileObj.getSyncOpConflict())); + conflictMsgs.emplace_back(fileObj.getPairRelativePath(), fileObj.getSyncOpConflict()); break; case SO_COPY_METADATA_TO_LEFT: @@ -192,7 +192,7 @@ void SyncStatistics::processLink(const SymlinkPair& linkObj) break; case SO_UNRESOLVED_CONFLICT: - conflictMsgs.push_back(std::make_pair(linkObj.getPairRelativePath(), linkObj.getSyncOpConflict())); + conflictMsgs.emplace_back(linkObj.getPairRelativePath(), linkObj.getSyncOpConflict()); break; case SO_MOVE_LEFT_SOURCE: @@ -229,7 +229,7 @@ void SyncStatistics::processDir(const DirPair& dirObj) break; case SO_UNRESOLVED_CONFLICT: - conflictMsgs.push_back(std::make_pair(dirObj.getPairRelativePath(), dirObj.getSyncOpConflict())); + conflictMsgs.emplace_back(dirObj.getPairRelativePath(), dirObj.getSyncOpConflict()); break; case SO_COPY_METADATA_TO_LEFT: @@ -277,7 +277,8 @@ std::vector<zen::FolderPairSyncCfg> zen::extractSyncCfg(const MainConfiguration& FolderPairSyncCfg(syncCfg.directionCfg.var == DirectionConfig::TWOWAY || detectMovedFilesEnabled(syncCfg.directionCfg), syncCfg.handleDeletion, syncCfg.versioningStyle, - getFormattedDirectoryPath(syncCfg.versioningDirectory))); + getFormattedDirectoryPath(syncCfg.versioningDirectory), + syncCfg.directionCfg.var)); } return output; } @@ -349,7 +350,7 @@ private: FileVersioner& getOrCreateVersioner() //throw FileError! => dont create in DeletionHandling()!!! { if (!versioner.get()) - versioner = make_unique<FileVersioner>(versioningDir_, versioningStyle_, timeStamp_); //throw FileError + versioner = zen::make_unique<FileVersioner>(versioningDir_, versioningStyle_, timeStamp_); //throw FileError return *versioner; }; @@ -484,7 +485,6 @@ void DeletionHandling::tryCleanup(bool allowUserCallback) //throw FileError; thr #ifdef ZEN_WIN if (!toBeRecycled.empty()) { - //may throw: first exception is swallowed, notifyDeletionStatus() is then called again where it should throw again and the exception will propagate as expected auto notifyDeletionStatus = [&](const Zstring& currentItem) { if (!currentItem.empty()) @@ -865,7 +865,7 @@ private: const std::function<void()>& onDeleteTargetFile, const std::function<void(std::int64_t bytesDelta)>& onNotifyFileCopy) const; //throw FileError - void verifyFileCopy(const Zstring& source, const Zstring& target) const; + void verifyFiles(const Zstring& source, const Zstring& target, const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus) const; //throw FileError template <SelectedSide side> DeletionHandling& getDelHandling(); @@ -1684,9 +1684,9 @@ void SynchronizeFolderPair::synchronizeFolderInt(DirPair& dirObj, SyncOperation reportInfo(txtCreatingFolder, target); try { - makeDirectoryPlain(target, dirObj.getFullPath<sideSrc>(), copyFilePermissions_); //throw FileError, ErrorTargetExisting, (ErrorTargetPathMissing) + makeDirectoryPlain(target, dirObj.getFullPath<sideSrc>(), copyFilePermissions_); //throw FileError } - catch (const ErrorTargetExisting&) { if (!dirExists(target)) throw; } //detect clash with file (dir-symlink OTOH is okay) + catch (const FileError&) { if (!dirExists(target)) throw; } //update DirPair dirObj.setSyncedTo(dirObj.getItemName<sideSrc>()); @@ -1761,7 +1761,6 @@ void SynchronizeFolderPair::synchronizeFolderInt(DirPair& dirObj, SyncOperation procCallback_.requestUiRefresh(); //may throw } - //########################################################################################### InSyncAttributes SynchronizeFolderPair::copyFileWithCallback(const Zstring& sourceFile, //throw FileError @@ -1783,7 +1782,10 @@ InSyncAttributes SynchronizeFolderPair::copyFileWithCallback(const Zstring& sour if (verifyCopiedFiles_) { auto guardTarget = makeGuard([&] { removeFile(targetFile); }); //delete target if verification fails - verifyFileCopy(sourceFileTmp, targetFile); //throw FileError + + procCallback_.reportInfo(replaceCpy(txtVerifying, L"%x", fmtFileName(targetFile))); + verifyFiles(sourceFileTmp, targetFile, [&](std::int64_t bytesDelta) { procCallback_.requestUiRefresh(); }); //throw FileError + guardTarget.dismiss(); } //#################### /Verification ############################# @@ -1806,11 +1808,10 @@ InSyncAttributes SynchronizeFolderPair::copyFileWithCallback(const Zstring& sour try { //contains prefix: E.g. "\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Program Files\FFS\sample.dat" - shadowSource = shadowCopyHandler_->makeShadowCopy(sourceFile, //throw FileError + shadowSource = shadowCopyHandler_->makeShadowCopy(sourceFile, //throw FileError [&](const Zstring& volumeName) { procCallback_.reportStatus(replaceCpy(_("Creating a Volume Shadow Copy for %x..."), L"%x", fmtFileName(volumeName))); - procCallback_.forceUiRefresh(); }); } catch (const FileError& e2) //enhance error massage @@ -1827,17 +1828,13 @@ InSyncAttributes SynchronizeFolderPair::copyFileWithCallback(const Zstring& sour } //--------------------- data verification ------------------------- -struct VerifyCallback -{ - virtual ~VerifyCallback() {} - virtual void updateStatus() = 0; -}; - -void verifyFiles(const Zstring& source, const Zstring& target, VerifyCallback& callback) //throw FileError +void SynchronizeFolderPair::verifyFiles(const Zstring& source, const Zstring& target, const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus) const //throw FileError { static std::vector<char> memory1(1024 * 1024); //1024 kb seems to be a reasonable buffer size static std::vector<char> memory2(1024 * 1024); + warn_static("redesign: access still buffered:") + #ifdef ZEN_WIN wxFile file1(applyLongPathPrefix(source).c_str(), wxFile::read); //don't use buffered file input for verification! #elif defined ZEN_LINUX || defined ZEN_MAC @@ -1859,15 +1856,16 @@ void verifyFiles(const Zstring& source, const Zstring& target, VerifyCallback& c const size_t length1 = file1.Read(&memory1[0], memory1.size()); if (file1.Error()) throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtFileName(source))); - callback.updateStatus(); const size_t length2 = file2.Read(&memory2[0], memory2.size()); if (file2.Error()) throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtFileName(target))); - callback.updateStatus(); if (length1 != length2 || ::memcmp(&memory1[0], &memory2[0], length1) != 0) throw FileError(replaceCpy(replaceCpy(_("Data verification error: %x and %y have different content."), L"%x", L"\n" + fmtFileName(source)), L"%y", L"\n" + fmtFileName(target))); + + if (onUpdateStatus) + onUpdateStatus(length1); } while (!file1.Eof()); @@ -1875,27 +1873,6 @@ void verifyFiles(const Zstring& source, const Zstring& target, VerifyCallback& c throw FileError(replaceCpy(replaceCpy(_("Data verification error: %x and %y have different content."), L"%x", L"\n" + fmtFileName(source)), L"%y", L"\n" + fmtFileName(target))); } - -class VerifyStatusUpdater : public VerifyCallback -{ -public: - VerifyStatusUpdater(ProcessCallback& statusHandler) : statusHandler_(statusHandler) {} - - virtual void updateStatus() { statusHandler_.requestUiRefresh(); } //trigger display refresh - -private: - ProcessCallback& statusHandler_; -}; - - -void SynchronizeFolderPair::verifyFileCopy(const Zstring& source, const Zstring& target) const -{ - procCallback_.reportInfo(replaceCpy(txtVerifying, L"%x", fmtFileName(target))); - - VerifyStatusUpdater callback(procCallback_); - tryReportingError([&] { verifyFiles(source, target, callback); }, procCallback_); -} - //########################################################################################### template <SelectedSide side> //create base directories first (if not yet existing) -> no symlink or attribute copying! @@ -1941,6 +1918,13 @@ struct ReadWriteCount size_t reads; size_t writes; }; + +enum class FolderPairJobType +{ + PROCESS, + WRITE_DB_ONLY, + SKIP, +}; } @@ -1992,7 +1976,7 @@ void zen::synchronize(const TimeComp& timeStamp, ProcessCallback::PHASE_SYNCHRONIZING); - std::deque<bool> skipFolderPair(folderCmp.size()); //folder pairs may be skipped after fatal errors were found + std::vector<FolderPairJobType> jobType(folderCmp.size(), FolderPairJobType::PROCESS); //folder pairs may be skipped after fatal errors were found //-------------------execute basic checks all at once before starting sync-------------------------------------- @@ -2009,7 +1993,7 @@ void zen::synchronize(const TimeComp& timeStamp, return false; }; - auto dependentDir = [](const Zstring& lhs, const Zstring& rhs) //note: this is NOT an equivalence relation! + auto havePathDependency = [](const Zstring& lhs, const Zstring& rhs) //note: this is NOT an equivalence relation! { return EqualFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())), Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length()))); @@ -2019,21 +2003,26 @@ void zen::synchronize(const TimeComp& timeStamp, std::map<Zstring, ReadWriteCount, LessFilename> dirReadWriteCount; //count read/write accesses for (auto j = begin(folderCmp); j != end(folderCmp); ++j) { - dirReadWriteCount[j->getBaseDirPf<LEFT_SIDE >()]; //create all entries first! - dirReadWriteCount[j->getBaseDirPf<RIGHT_SIDE>()]; //=> counting accesses is complex for later inserts! + //create all entries first! otherwise counting accesses is too complex during later inserts! + if (!j->getBaseDirPf<LEFT_SIDE >().empty()) //<empty> is always a dependent directory => exclude! + dirReadWriteCount[j->getBaseDirPf<LEFT_SIDE >()]; + if (!j->getBaseDirPf<RIGHT_SIDE >().empty()) + dirReadWriteCount[j->getBaseDirPf<RIGHT_SIDE>()]; } auto incReadCount = [&](const Zstring& baseDir) { - for (auto& item : dirReadWriteCount) - if (dependentDir(baseDir, item.first)) - ++item.second.reads; + if (!baseDir.empty()) + for (auto& item : dirReadWriteCount) + if (havePathDependency(baseDir, item.first)) + ++item.second.reads; }; auto incWriteCount = [&](const Zstring& baseDir) { - for (auto& item : dirReadWriteCount) - if (dependentDir(baseDir, item.first)) - ++item.second.writes; + if (!baseDir.empty()) + for (auto& item : dirReadWriteCount) + if (havePathDependency(baseDir, item.first)) + ++item.second.writes; }; std::vector<std::pair<Zstring, Zstring>> significantDiffPairs; @@ -2054,7 +2043,7 @@ void zen::synchronize(const TimeComp& timeStamp, //exclude some pathological case (leftdir, rightdir are empty) if (EqualFilename()(j->getBaseDirPf<LEFT_SIDE>(), j->getBaseDirPf<RIGHT_SIDE>())) { - skipFolderPair[folderIndex] = true; + jobType[folderIndex] = FolderPairJobType::SKIP; continue; } @@ -2069,20 +2058,20 @@ void zen::synchronize(const TimeComp& timeStamp, folderPairStat.getUpdate<RIGHT_SIDE>() + folderPairStat.getDelete<RIGHT_SIDE>() > 0; - //skip folder pair if there is nothing to do (except for two-way mode and move-detection, where DB files need to be written) - if (!writeLeft && !writeRight && - !folderPairCfg.saveSyncDB_) + //skip folder pair if there is nothing to do (except for two-way mode and move-detection, where DB files need to be updated) + //-> skip creating (not yet existing) base directories in particular if there's no need + if (!writeLeft && !writeRight) { - skipFolderPair[folderIndex] = true; //skip creating (not yet existing) base directories in particular if there's no need + jobType[folderIndex] = folderPairCfg.saveSyncDB_ ? FolderPairJobType::WRITE_DB_ONLY : FolderPairJobType::SKIP; continue; } //aggregate information of folders used by multiple pairs in read/write access - if (!dependentDir(j->getBaseDirPf<LEFT_SIDE>(), j->getBaseDirPf<RIGHT_SIDE>())) //true in general + if (!havePathDependency(j->getBaseDirPf<LEFT_SIDE>(), j->getBaseDirPf<RIGHT_SIDE>())) //true in general { if (writeLeft && writeRight) { - incWriteCount(j->getBaseDirPf<LEFT_SIDE >()); + incWriteCount(j->getBaseDirPf<LEFT_SIDE>()); incWriteCount(j->getBaseDirPf<RIGHT_SIDE>()); } else if (writeLeft) @@ -2107,7 +2096,7 @@ void zen::synchronize(const TimeComp& timeStamp, (j->getBaseDirPf<RIGHT_SIDE>().empty() && (writeRight || folderPairCfg.saveSyncDB_))) { callback.reportFatalError(_("Target folder input field must not be empty.")); - skipFolderPair[folderIndex] = true; + jobType[folderIndex] = FolderPairJobType::SKIP; continue; } @@ -2117,7 +2106,7 @@ void zen::synchronize(const TimeComp& timeStamp, if (dirNotFoundAnymore(j->getBaseDirPf<LEFT_SIDE >(), j->isExisting<LEFT_SIDE >()) || dirNotFoundAnymore(j->getBaseDirPf<RIGHT_SIDE>(), j->isExisting<RIGHT_SIDE>())) { - skipFolderPair[folderIndex] = true; + jobType[folderIndex] = FolderPairJobType::SKIP; continue; } @@ -2140,7 +2129,7 @@ void zen::synchronize(const TimeComp& timeStamp, if (sourceDirNotFound(j->getBaseDirPf<LEFT_SIDE >(), j->isExisting<LEFT_SIDE >()) || sourceDirNotFound(j->getBaseDirPf<RIGHT_SIDE>(), j->isExisting<RIGHT_SIDE>())) { - skipFolderPair[folderIndex] = true; + jobType[folderIndex] = FolderPairJobType::SKIP; continue; } @@ -2152,14 +2141,14 @@ void zen::synchronize(const TimeComp& timeStamp, { //should not arrive here: already checked in SyncCfgDialog callback.reportFatalError(_("Please enter a target folder for versioning.")); - skipFolderPair[folderIndex] = true; + jobType[folderIndex] = FolderPairJobType::SKIP; continue; } } //check if more than 50% of total number of files/dirs are to be created/overwritten/deleted if (significantDifferenceDetected(folderPairStat)) - significantDiffPairs.push_back(std::make_pair(j->getBaseDirPf<LEFT_SIDE>(), j->getBaseDirPf<RIGHT_SIDE>())); + significantDiffPairs.emplace_back(j->getBaseDirPf<LEFT_SIDE>(), j->getBaseDirPf<RIGHT_SIDE>()); //check for sufficient free diskspace auto checkSpace = [&](const Zstring& baseDirPf, std::int64_t minSpaceNeeded) @@ -2170,7 +2159,7 @@ void zen::synchronize(const TimeComp& timeStamp, if (0 < freeSpace && //zero disk space probably means "request not supported" (e.g. see WebDav) freeSpace < minSpaceNeeded) - diskSpaceMissing.push_back(std::make_pair(baseDirPf, std::make_pair(minSpaceNeeded, freeSpace))); + diskSpaceMissing.emplace_back(baseDirPf, std::make_pair(minSpaceNeeded, freeSpace)); } catch (FileError&) {} }; @@ -2296,13 +2285,14 @@ void zen::synchronize(const TimeComp& timeStamp, const size_t folderIndex = j - begin(folderCmp); const FolderPairSyncCfg& folderPairCfg = syncConfig[folderIndex]; - if (skipFolderPair[folderIndex]) //folder pairs may be skipped after fatal errors were found + if (jobType[folderIndex] == FolderPairJobType::SKIP) //folder pairs may be skipped after fatal errors were found continue; //------------------------------------------------------------------------------------------ - callback.reportInfo(_("Synchronizing folder pair:") + L"\n" + - L" " + j->getBaseDirPf<LEFT_SIDE >() + L"\n" + - L" " + j->getBaseDirPf<RIGHT_SIDE>()); + if (jobType[folderIndex] == FolderPairJobType::PROCESS) + callback.reportInfo(_("Synchronizing folder pair:") + L" [" + getVariantName(folderPairCfg.syncVariant_) + L"]\n" + + L" " + j->getBaseDirPf<LEFT_SIDE >() + L"\n" + + L" " + j->getBaseDirPf<RIGHT_SIDE>()); //------------------------------------------------------------------------------------------ //checking a second time: (a long time may have passed since the intro checks!) @@ -2326,60 +2316,63 @@ void zen::synchronize(const TimeComp& timeStamp, catch (FileError&) {} }); - //guarantee removal of invalid entries (where element on both sides is empty) - ZEN_ON_SCOPE_EXIT(BaseDirPair::removeEmpty(*j);); - - bool copyPermissionsFp = false; - tryReportingError([&] + if (jobType[folderIndex] == FolderPairJobType::PROCESS) { - copyPermissionsFp = copyFilePermissions && //copy permissions only if asked for and supported by *both* sides! - !j->getBaseDirPf<LEFT_SIDE >().empty() && //scenario: directory selected on one side only - !j->getBaseDirPf<RIGHT_SIDE>().empty() && // - supportsPermissions(beforeLast(j->getBaseDirPf<LEFT_SIDE >(), FILE_NAME_SEPARATOR)) && //throw FileError - supportsPermissions(beforeLast(j->getBaseDirPf<RIGHT_SIDE>(), FILE_NAME_SEPARATOR)); - }, callback); //show error dialog if necessary + //guarantee removal of invalid entries (where element is empty on both sides) + ZEN_ON_SCOPE_EXIT(BaseDirPair::removeEmpty(*j);); + bool copyPermissionsFp = false; + tryReportingError([&] + { + copyPermissionsFp = copyFilePermissions && //copy permissions only if asked for and supported by *both* sides! + !j->getBaseDirPf<LEFT_SIDE >().empty() && //scenario: directory selected on one side only + !j->getBaseDirPf<RIGHT_SIDE>().empty() && // + supportsPermissions(beforeLast(j->getBaseDirPf<LEFT_SIDE >(), FILE_NAME_SEPARATOR)) && //throw FileError + supportsPermissions(beforeLast(j->getBaseDirPf<RIGHT_SIDE>(), FILE_NAME_SEPARATOR)); + }, callback); //show error dialog if necessary - auto getEffectiveDeletionPolicy = [&](const Zstring& baseDirPf) -> DeletionPolicy - { -#ifdef ZEN_WIN - if (folderPairCfg.handleDeletion == DELETE_TO_RECYCLER) + + auto getEffectiveDeletionPolicy = [&](const Zstring& baseDirPf) -> DeletionPolicy { - auto it = baseDirHasRecycler.find(baseDirPf); - if (it != baseDirHasRecycler.end()) //buffer filled during intro checks (but only if deletions are expected) - if (!it->second) - return DELETE_PERMANENTLY; //Windows' ::SHFileOperation() will do this anyway, but we have a better and faster deletion routine (e.g. on networks) - } +#ifdef ZEN_WIN + if (folderPairCfg.handleDeletion == DELETE_TO_RECYCLER) + { + auto it = baseDirHasRecycler.find(baseDirPf); + if (it != baseDirHasRecycler.end()) //buffer filled during intro checks (but only if deletions are expected) + if (!it->second) + return DELETE_PERMANENTLY; //Windows' ::SHFileOperation() will do this anyway, but we have a better and faster deletion routine (e.g. on networks) + } #endif - return folderPairCfg.handleDeletion; - }; + return folderPairCfg.handleDeletion; + }; - DeletionHandling delHandlerL(getEffectiveDeletionPolicy(j->getBaseDirPf<LEFT_SIDE>()), - folderPairCfg.versioningFolder, - folderPairCfg.versioningStyle_, - timeStamp, - j->getBaseDirPf<LEFT_SIDE>(), - callback); + DeletionHandling delHandlerL(getEffectiveDeletionPolicy(j->getBaseDirPf<LEFT_SIDE>()), + folderPairCfg.versioningFolder, + folderPairCfg.versioningStyle_, + timeStamp, + j->getBaseDirPf<LEFT_SIDE>(), + callback); - DeletionHandling delHandlerR(getEffectiveDeletionPolicy(j->getBaseDirPf<RIGHT_SIDE>()), - folderPairCfg.versioningFolder, - folderPairCfg.versioningStyle_, - timeStamp, - j->getBaseDirPf<RIGHT_SIDE>(), - callback); + DeletionHandling delHandlerR(getEffectiveDeletionPolicy(j->getBaseDirPf<RIGHT_SIDE>()), + folderPairCfg.versioningFolder, + folderPairCfg.versioningStyle_, + timeStamp, + j->getBaseDirPf<RIGHT_SIDE>(), + callback); - SynchronizeFolderPair syncFP(callback, verifyCopiedFiles, copyPermissionsFp, transactionalFileCopy, + SynchronizeFolderPair syncFP(callback, verifyCopiedFiles, copyPermissionsFp, transactionalFileCopy, #ifdef ZEN_WIN - shadowCopyHandler.get(), + shadowCopyHandler.get(), #endif - delHandlerL, delHandlerR); - syncFP.startSync(*j); + delHandlerL, delHandlerR); + syncFP.startSync(*j); - //(try to gracefully) cleanup temporary Recycle bin folders and versioning -> will be done in ~DeletionHandling anyway... - tryReportingError([&] { delHandlerL.tryCleanup(); /*throw FileError*/}, callback); //show error dialog if necessary - tryReportingError([&] { delHandlerR.tryCleanup(); /*throw FileError*/}, callback); // + //(try to gracefully) cleanup temporary Recycle bin folders and versioning -> will be done in ~DeletionHandling anyway... + tryReportingError([&] { delHandlerL.tryCleanup(); /*throw FileError*/}, callback); //show error dialog if necessary + tryReportingError([&] { delHandlerR.tryCleanup(); /*throw FileError*/}, callback); // + } //(try to gracefully) write database file if (folderPairCfg.saveSyncDB_) diff --git a/FreeFileSync/Source/synchronization.h b/FreeFileSync/Source/synchronization.h index 11f560be..6b1cbfdd 100644 --- a/FreeFileSync/Source/synchronization.h +++ b/FreeFileSync/Source/synchronization.h @@ -63,16 +63,19 @@ struct FolderPairSyncCfg FolderPairSyncCfg(bool saveSyncDB, const DeletionPolicy handleDel, VersioningStyle versioningStyle, - const Zstring& versioningDirFmt) : + const Zstring& versioningDirFmt, + DirectionConfig::Variant syncVariant) : saveSyncDB_(saveSyncDB), handleDeletion(handleDel), versioningStyle_(versioningStyle), - versioningFolder(versioningDirFmt) {} + versioningFolder(versioningDirFmt), + syncVariant_(syncVariant) {} bool saveSyncDB_; //save database if in automatic mode or dection of moved files is active DeletionPolicy handleDeletion; VersioningStyle versioningStyle_; Zstring versioningFolder; //formatted directory name + DirectionConfig::Variant syncVariant_; }; std::vector<FolderPairSyncCfg> extractSyncCfg(const MainConfiguration& mainCfg); diff --git a/FreeFileSync/Source/ui/batch_config.cpp b/FreeFileSync/Source/ui/batch_config.cpp index dc6a76c1..643fde32 100644 --- a/FreeFileSync/Source/ui/batch_config.cpp +++ b/FreeFileSync/Source/ui/batch_config.cpp @@ -40,16 +40,16 @@ public: size_t onCompletionHistoryMax); private: - virtual void OnClose (wxCloseEvent& event) { EndModal(BUTTON_CANCEL); } - virtual void OnCancel (wxCommandEvent& event) { EndModal(BUTTON_CANCEL); } - virtual void OnSaveBatchJob(wxCommandEvent& event); - virtual void OnErrorPopup (wxCommandEvent& event) { localBatchCfg.handleError = ON_ERROR_POPUP; updateGui(); } - virtual void OnErrorIgnore(wxCommandEvent& event) { localBatchCfg.handleError = ON_ERROR_IGNORE; updateGui(); } - virtual void OnErrorStop (wxCommandEvent& event) { localBatchCfg.handleError = ON_ERROR_STOP; updateGui(); } - virtual void OnHelpScheduleBatch(wxHyperlinkEvent& event) { displayHelpEntry(L"html/Schedule a Batch Job.html", this); } - - virtual void OnToggleGenerateLogfile(wxCommandEvent& event) { updateGui(); } - virtual void OnToggleLogfilesLimit (wxCommandEvent& event) { updateGui(); } + void OnClose (wxCloseEvent& event) override { EndModal(BUTTON_CANCEL); } + void OnCancel (wxCommandEvent& event) override { EndModal(BUTTON_CANCEL); } + void OnSaveBatchJob(wxCommandEvent& event) override; + 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 OnToggleGenerateLogfile(wxCommandEvent& event) override { updateGui(); } + void OnToggleLogfilesLimit (wxCommandEvent& event) override { updateGui(); } void updateGui(); //re-evaluate gui after config changes diff --git a/FreeFileSync/Source/ui/batch_status_handler.cpp b/FreeFileSync/Source/ui/batch_status_handler.cpp index b40941fa..5f021484 100644 --- a/FreeFileSync/Source/ui/batch_status_handler.cpp +++ b/FreeFileSync/Source/ui/batch_status_handler.cpp @@ -5,7 +5,7 @@ // ************************************************************************** #include "batch_status_handler.h" -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/file_traverser.h> #include <zen/shell_execute.h> #include <wx+/popup_dlg.h> @@ -39,30 +39,34 @@ Zstring addStatusToLogfilename(const Zstring& logfilepath, const std::wstring& s class FindLogfiles : public TraverseCallback { public: - FindLogfiles(const Zstring& prefix, std::vector<Zstring>& logfiles) : prefix_(prefix), logfiles_(logfiles) {} + FindLogfiles(const Zstring& prefix, std::vector<Zstring>& logfiles, const std::function<void()>& onUpdateStatus) : prefix_(prefix), logfiles_(logfiles), onUpdateStatus_(onUpdateStatus) {} private: - virtual void onFile(const Zchar* shortName, const Zstring& filePath, const FileInfo& details) + void onFile(const Zchar* shortName, const Zstring& filePath, const FileInfo& details) override { const Zstring fileName(shortName); if (startsWith(fileName, prefix_) && endsWith(fileName, Zstr(".log"))) logfiles_.push_back(filePath); + + if (onUpdateStatus_) + onUpdateStatus_(); } - virtual TraverseCallback* onDir(const Zchar* shortName, const Zstring& dirpath) { return nullptr; } //DON'T traverse into subdirs - virtual HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) { return LINK_SKIP; } - virtual HandleError reportDirError (const std::wstring& msg, size_t retryNumber) { assert(false); return ON_ERROR_IGNORE; } //errors are not really critical in this context - virtual HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) { assert(false); return ON_ERROR_IGNORE; } // + TraverseCallback* onDir(const Zchar* shortName, const Zstring& dirpath) override { return nullptr; } //DON'T traverse into subdirs + HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) override { return LINK_SKIP; } + HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override { assert(false); return ON_ERROR_IGNORE; } //errors are not really critical in this context + HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) override { assert(false); return ON_ERROR_IGNORE; } // const Zstring prefix_; std::vector<Zstring>& logfiles_; + const std::function<void()> onUpdateStatus_; }; -void limitLogfileCount(const Zstring& logdir, const std::wstring& jobname, size_t maxCount) //throw() +void limitLogfileCount(const Zstring& logdir, const std::wstring& jobname, size_t maxCount, const std::function<void()>& onUpdateStatus) //throw() { std::vector<Zstring> logFiles; - FindLogfiles traverseCallback(utfCvrtTo<Zstring>(jobname), logFiles); //throw()! + FindLogfiles traverseCallback(utfCvrtTo<Zstring>(jobname), logFiles, onUpdateStatus); //throw()! traverseFolder(logdir, traverseCallback); if (logFiles.size() <= maxCount) @@ -71,8 +75,12 @@ void limitLogfileCount(const Zstring& logdir, const std::wstring& jobname, size_ //delete oldest logfiles: take advantage of logfile naming convention to find them std::nth_element(logFiles.begin(), logFiles.end() - maxCount, logFiles.end(), LessFilename()); - std::for_each(logFiles.begin(), logFiles.end() - maxCount, - [](const Zstring& filepath) { try { removeFile(filepath); } catch (FileError&) {} }); + std::for_each(logFiles.begin(), logFiles.end() - maxCount, [&](const Zstring& filepath) + { + try { removeFile(filepath); } + catch (FileError&) {}; + onUpdateStatus(); + }); } @@ -95,7 +103,7 @@ std::unique_ptr<FileOutput> prepareNewLogfile(const Zstring& logfileDirectory, / for (int i = 0;; ++i) try { - return make_unique<FileOutput>(filepath, FileOutput::ACC_CREATE_NEW); //throw FileError, ErrorTargetExisting + return zen::make_unique<FileOutput>(filepath, FileOutput::ACC_CREATE_NEW); //throw FileError, ErrorTargetExisting //*no* file system race-condition! } catch (const ErrorTargetExisting&) @@ -161,7 +169,7 @@ BatchStatusHandler::~BatchStatusHandler() { switchBatchToGui_.execute(); //open FreeFileSync GUI } - catch (...) {} + catch (...) { assert(false); } showFinalResults = false; } else if (progressDlg) @@ -181,7 +189,7 @@ BatchStatusHandler::~BatchStatusHandler() try { //use EXEC_TYPE_ASYNC until there is reason no to: https://sourceforge.net/p/freefilesync/discussion/help/thread/828dca52 - tryReportingError([&] { shellExecute2(expandMacros(finalCommand), EXEC_TYPE_ASYNC); }, //throw FileError, throw X? + tryReportingError([&] { shellExecute(expandMacros(finalCommand), EXEC_TYPE_ASYNC); }, //throw FileError, throw X? *this); } catch (...) {} @@ -232,23 +240,19 @@ BatchStatusHandler::~BatchStatusHandler() (wxGetUTCTimeMillis().GetValue() - startTime_) / 1000 }; - //print the results list: logfile + //----------------- write results into user-specified logfile ------------------------ if (logFile.get()) { - try + if (logfilesCountLimit_ > 0) { - //saving log file below may take a *long* time, so report (without logging) - reportStatus(replaceCpy(_("Saving log file %x..."), L"%x", fmtFileName(logFile->getFilename()))); //throw? - forceUiRefresh(); // + try { reportStatus(_("Cleaning up old log files exceeding limit...")); } + catch (...) {} + limitLogfileCount(beforeLast(logFile->getFilename(), FILE_NAME_SEPARATOR), jobName_, logfilesCountLimit_, [&] { try { requestUiRefresh(); } catch (...) {} }); //throw() } - catch (...) {} - - if (logfilesCountLimit_ > 0) - limitLogfileCount(beforeLast(logFile->getFilename(), FILE_NAME_SEPARATOR), jobName_, logfilesCountLimit_); //throw() try { - saveLogToFile(summary, errorLog, *logFile); //throw FileError + saveLogToFile(summary, errorLog, *logFile, OnUpdateLogfileStatusNoThrow(*this, logFile->getFilename())); //throw FileError //additionally notify errors by showing in log file name const Zstring oldLogfilepath = logFile->getFilename(); @@ -262,9 +266,10 @@ BatchStatusHandler::~BatchStatusHandler() } catch (FileError&) {} } + //----------------- write results into LastSyncs.log------------------------ try { - saveToLastSyncsLog(summary, errorLog, lastSyncsLogFileSizeMax_); //throw FileError + saveToLastSyncsLog(summary, errorLog, lastSyncsLogFileSizeMax_, OnUpdateLogfileStatusNoThrow(*this, getLastSyncsLogfilePath())); //throw FileError } catch (FileError&) {} diff --git a/FreeFileSync/Source/ui/batch_status_handler.h b/FreeFileSync/Source/ui/batch_status_handler.h index 2fc64148..214a367b 100644 --- a/FreeFileSync/Source/ui/batch_status_handler.h +++ b/FreeFileSync/Source/ui/batch_status_handler.h @@ -40,16 +40,16 @@ public: std::vector<Zstring>& onCompletionHistory); ~BatchStatusHandler(); - virtual void initNewPhase (int objectsTotal, std::int64_t dataTotal, Phase phaseID); - virtual void updateProcessedData(int objectsDelta, std::int64_t dataDelta); - virtual void reportInfo(const std::wstring& text); - virtual void forceUiRefresh(); + void initNewPhase (int objectsTotal, std::int64_t dataTotal, Phase phaseID) override; + void updateProcessedData(int objectsDelta, std::int64_t dataDelta) override; + void reportInfo (const std::wstring& text) override; + void forceUiRefresh () override; - virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive); - virtual Response reportError(const std::wstring& errorMessage, size_t retryNumber); - virtual void reportFatalError(const std::wstring& errorMessage); + void reportWarning (const std::wstring& warningMessage, bool& warningActive) override; + Response reportError (const std::wstring& errorMessage, size_t retryNumber ) override; + void reportFatalError(const std::wstring& errorMessage ) override; - virtual void abortProcessNow(); //throw BatchAbortProcess + void abortProcessNow() override; //throw BatchAbortProcess private: void onProgressDialogTerminate(); diff --git a/FreeFileSync/Source/ui/check_version.cpp b/FreeFileSync/Source/ui/check_version.cpp index 91ac2bf0..ce80753f 100644 --- a/FreeFileSync/Source/ui/check_version.cpp +++ b/FreeFileSync/Source/ui/check_version.cpp @@ -28,6 +28,26 @@ using namespace zen; namespace { +std::wstring getUserAgentName() +{ + std::wstring agentName = std::wstring(L"FreeFileSync ") + zen::currentVersion; +#ifdef ZEN_WIN + agentName += L" Windows"; +#elif defined ZEN_LINUX + agentName += L" Linux"; +#elif defined ZEN_MAC + agentName += L" Mac"; +#else +#error wtf +#endif + const std::wstring localeName(wxLocale::GetLanguageCanonicalName(wxLocale::GetSystemLanguage())); + if (!localeName.empty()) + agentName += L" " + localeName; + + return agentName; +} + + #ifdef ZEN_WIN class InternetConnectionError {}; @@ -38,7 +58,7 @@ public: { //::InternetAttemptConnect(0) -> not working as expected: succeeds even when there is no internet connection! - hInternet = ::InternetOpen(L"FreeFileSync", //_In_ LPCTSTR lpszAgent, + hInternet = ::InternetOpen(getUserAgentName().c_str(), //_In_ LPCTSTR lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, //_In_ DWORD dwAccessType, nullptr, //_In_ LPCTSTR lpszProxyName, nullptr, //_In_ LPCTSTR lpszProxyBypass, @@ -129,7 +149,7 @@ OutputIterator readBytesUrl(const wchar_t* url, OutputIterator result) //throw I enum GetVerResult { GET_VER_SUCCESS, - GET_VER_NO_CONNECTION, //no internet connection or just Sourceforge down? + GET_VER_NO_CONNECTION, //no internet connection or homepage down? GET_VER_PAGE_NOT_FOUND //version file seems to have moved! => trigger an update! }; @@ -140,11 +160,11 @@ GetVerResult getOnlineVersion(wxString& version) //empty string on error; std::vector<char> output; try { - readBytesUrl(L"http://freefilesync.sourceforge.net/latest_version.txt", std::back_inserter(output)); //throw InternetConnectionError + readBytesUrl(L"http://www.freefilesync.org/latest_version.txt", std::back_inserter(output)); //throw InternetConnectionError } catch (const InternetConnectionError&) { - return canAccessUrl(L"http://sourceforge.net/") ? GET_VER_PAGE_NOT_FOUND : GET_VER_NO_CONNECTION; + return canAccessUrl(L"http://www.freefilesync.org/") ? GET_VER_PAGE_NOT_FOUND : GET_VER_NO_CONNECTION; } output.push_back('\0'); @@ -158,6 +178,8 @@ GetVerResult getOnlineVersion(wxString& version) //empty string on error; { wxHTTP webAccess; webAccess.SetHeader(L"content-type", L"text/html; charset=utf-8"); + webAccess.SetHeader(L"USER-AGENT", getUserAgentName()); + webAccess.SetTimeout(timeout); //default: 10 minutes(WTF are these wxWidgets people thinking???)... if (webAccess.Connect(server)) //will *not* fail for non-reachable url here! @@ -181,10 +203,10 @@ GetVerResult getOnlineVersion(wxString& version) //empty string on error; return false; }; - if (getStringFromUrl(L"freefilesync.sourceforge.net", L"/latest_version.txt", 5, &version)) + if (getStringFromUrl(L"freefilesync.org", L"/latest_version.txt", 5, &version)) return GET_VER_SUCCESS; - const bool canConnectToSf = getStringFromUrl(L"sourceforge.net", L"/", 1, nullptr); + const bool canConnectToSf = getStringFromUrl(L"freefilesync.org", L"/", 1, nullptr); return canConnectToSf ? GET_VER_PAGE_NOT_FOUND : GET_VER_NO_CONNECTION; #endif } @@ -230,7 +252,7 @@ void zen::checkForUpdateNow(wxWindow* parent) _("&Download"))) { case ConfirmationButton::DO_IT: - wxLaunchDefaultBrowser(L"http://freefilesync.sourceforge.net/get_latest.php"); + wxLaunchDefaultBrowser(L"http://freefilesync.org/get_latest.php"); break; case ConfirmationButton::CANCEL: break; @@ -245,7 +267,7 @@ void zen::checkForUpdateNow(wxWindow* parent) case GET_VER_NO_CONNECTION: showNotificationDialog(parent, DialogInfoType::ERROR2, PopupDialogCfg(). setTitle(("Check for Program Updates")). - setMainInstructions(_("Unable to connect to sourceforge.net."))); + setMainInstructions(_("Unable to connect to freefilesync.org."))); break; case GET_VER_PAGE_NOT_FOUND: @@ -255,7 +277,7 @@ void zen::checkForUpdateNow(wxWindow* parent) _("&Check"))) { case ConfirmationButton::DO_IT: - wxLaunchDefaultBrowser(L"http://freefilesync.sourceforge.net/"); + wxLaunchDefaultBrowser(L"http://www.freefilesync.org/"); break; case ConfirmationButton::CANCEL: break; @@ -286,7 +308,7 @@ void zen::checkForUpdatePeriodically(wxWindow* parent, long& lastUpdateCheck, co _("&Download"))) { case ConfirmationButton::DO_IT: - wxLaunchDefaultBrowser(L"http://freefilesync.sourceforge.net/get_latest.php"); + wxLaunchDefaultBrowser(L"http://www.freefilesync.org/get_latest.php"); break; case ConfirmationButton::CANCEL: break; @@ -304,7 +326,7 @@ void zen::checkForUpdatePeriodically(wxWindow* parent, long& lastUpdateCheck, co _("&Check"))) { case ConfirmationButton::DO_IT: - wxLaunchDefaultBrowser(L"http://freefilesync.sourceforge.net/"); + wxLaunchDefaultBrowser(L"http://www.freefilesync.org/"); break; case ConfirmationButton::CANCEL: break; diff --git a/FreeFileSync/Source/ui/column_attr.h b/FreeFileSync/Source/ui/column_attr.h index 2bc2d8e4..42dc458d 100644 --- a/FreeFileSync/Source/ui/column_attr.h +++ b/FreeFileSync/Source/ui/column_attr.h @@ -38,13 +38,13 @@ inline std::vector<ColumnAttributeRim> getDefaultColumnAttributesLeft() { std::vector<ColumnAttributeRim> attr; - attr.push_back(ColumnAttributeRim(COL_TYPE_FULL_PATH, 250, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_BASE_DIRECTORY, 200, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_REL_FOLDER, -280, 1, true)); //stretch to full width and substract sum of fixed size widths! - attr.push_back(ColumnAttributeRim(COL_TYPE_FILENAME, 200, 0, true)); - attr.push_back(ColumnAttributeRim(COL_TYPE_DATE, 112, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_SIZE, 80, 0, true)); - attr.push_back(ColumnAttributeRim(COL_TYPE_EXTENSION, 60, 0, false)); + attr.emplace_back(COL_TYPE_FULL_PATH, 250, 0, false); + attr.emplace_back(COL_TYPE_BASE_DIRECTORY, 200, 0, false); + attr.emplace_back(COL_TYPE_REL_FOLDER, -280, 1, true); //stretch to full width and substract sum of fixed size widths! + attr.emplace_back(COL_TYPE_FILENAME, 200, 0, true); + attr.emplace_back(COL_TYPE_DATE, 112, 0, false); + attr.emplace_back(COL_TYPE_SIZE, 80, 0, true); + attr.emplace_back(COL_TYPE_EXTENSION, 60, 0, false); return attr; } @@ -52,13 +52,13 @@ inline std::vector<ColumnAttributeRim> getDefaultColumnAttributesRight() { std::vector<ColumnAttributeRim> attr; - attr.push_back(ColumnAttributeRim(COL_TYPE_FULL_PATH, 250, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_BASE_DIRECTORY, 200, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_REL_FOLDER , -280, 1, false)); //already shown on left side - attr.push_back(ColumnAttributeRim(COL_TYPE_FILENAME, 200, 0, true)); - attr.push_back(ColumnAttributeRim(COL_TYPE_DATE, 112, 0, false)); - attr.push_back(ColumnAttributeRim(COL_TYPE_SIZE, 80, 0, true)); - attr.push_back(ColumnAttributeRim(COL_TYPE_EXTENSION, 60, 0, false)); + attr.emplace_back(COL_TYPE_FULL_PATH, 250, 0, false); + attr.emplace_back(COL_TYPE_BASE_DIRECTORY, 200, 0, false); + attr.emplace_back(COL_TYPE_REL_FOLDER , -280, 1, false); //already shown on left side + attr.emplace_back(COL_TYPE_FILENAME, 200, 0, true); + attr.emplace_back(COL_TYPE_DATE, 112, 0, false); + attr.emplace_back(COL_TYPE_SIZE, 80, 0, true); + attr.emplace_back(COL_TYPE_EXTENSION, 60, 0, false); return attr; } @@ -101,9 +101,9 @@ inline std::vector<ColumnAttributeNavi> getDefaultColumnAttributesNavi() { std::vector<ColumnAttributeNavi> attr; - attr.push_back(ColumnAttributeNavi(COL_TYPE_NAVI_DIRECTORY, -120, 1, true)); //stretch to full width and substract sum of fixed size widths - attr.push_back(ColumnAttributeNavi(COL_TYPE_NAVI_ITEM_COUNT, 60, 0, true)); - attr.push_back(ColumnAttributeNavi(COL_TYPE_NAVI_BYTES, 60, 0, true)); //GTK needs a few pixels width more + attr.emplace_back(COL_TYPE_NAVI_DIRECTORY, -120, 1, true); //stretch to full width and substract sum of fixed size widths + attr.emplace_back(COL_TYPE_NAVI_ITEM_COUNT, 60, 0, true); + attr.emplace_back(COL_TYPE_NAVI_BYTES, 60, 0, true); //GTK needs a few pixels width more return attr; } } diff --git a/FreeFileSync/Source/ui/custom_grid.cpp b/FreeFileSync/Source/ui/custom_grid.cpp index 98f9b37f..fdd32ff2 100644 --- a/FreeFileSync/Source/ui/custom_grid.cpp +++ b/FreeFileSync/Source/ui/custom_grid.cpp @@ -193,7 +193,7 @@ protected: } private: - virtual size_t getRowCount() const + size_t getRowCount() const override { if (gridDataView_) { @@ -273,7 +273,7 @@ public: const IconInfo ii = getIconInfo(currentRow); if (!ii.iconPath.empty()) if (!iconMgr_->refIconBuffer().readyForRetrieval(ii.iconPath)) - newLoad.push_back(std::make_pair(i, ii.iconPath)); //insert least-important items on outer rim first + newLoad.emplace_back(i, ii.iconPath); //insert least-important items on outer rim first } } } @@ -298,7 +298,7 @@ private: } protected: - virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override + void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override { if (enabled) { @@ -375,12 +375,12 @@ private: { GetRowType(DisplayType& result) : result_(result) {} - virtual void visit(const FilePair& fileObj) {} - virtual void visit(const SymlinkPair& linkObj) + void visit(const FilePair& fileObj) override {} + void visit(const SymlinkPair& linkObj) override { result_ = DISP_TYPE_SYMLINK; } - virtual void visit(const DirPair& dirObj) + void visit(const DirPair& dirObj) override { result_ = DISP_TYPE_FOLDER; } @@ -391,7 +391,7 @@ private: return output; } - virtual wxString getValue(size_t row, ColumnType colType) const + wxString getValue(size_t row, ColumnType colType) const override { if (const FileSystemObject* fsObj = getRawData(row)) { @@ -399,7 +399,7 @@ private: { GetTextValue(ColumnTypeRim colType, const FileSystemObject& fso) : colType_(colType), fsObj_(fso) {} - virtual void visit(const FilePair& fileObj) + void visit(const FilePair& fileObj) override { switch (colType_) { @@ -433,7 +433,7 @@ private: } } - virtual void visit(const SymlinkPair& linkObj) + void visit(const SymlinkPair& linkObj) override { switch (colType_) { @@ -463,7 +463,7 @@ private: } } - virtual void visit(const DirPair& dirObj) + void visit(const DirPair& dirObj) override { switch (colType_) { @@ -506,7 +506,7 @@ private: static const int GAP_SIZE = 2; - virtual void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected) override + void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected) override { wxRect rectTmp = rect; @@ -599,7 +599,7 @@ private: } } - virtual int getBestSize(wxDC& dc, size_t row, ColumnType colType) override + int getBestSize(wxDC& dc, size_t row, ColumnType colType) override { // Partitioning: // ________________________________ @@ -615,7 +615,7 @@ private: return bestSize; // + 1 pix for cell border line -> not used anymore! } - virtual wxString getColumnLabel(ColumnType colType) const + wxString getColumnLabel(ColumnType colType) const override { switch (static_cast<ColumnTypeRim>(colType)) { @@ -637,7 +637,7 @@ private: return wxEmptyString; } - virtual void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override + void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override { wxRect rectInside = drawColumnLabelBorder(dc, rect); drawColumnLabelBackground(dc, rectInside, highlighted); @@ -680,17 +680,17 @@ private: { GetIcon(IconInfo& ii) : ii_(ii) {} - virtual void visit(const FilePair& fileObj) + void visit(const FilePair& fileObj) override { ii_.iconPath = fileObj.getFullPath<side>(); ii_.drawAsLink = fileObj.isFollowedSymlink<side>() || hasLinkExtension(ii_.iconPath); } - virtual void visit(const SymlinkPair& linkObj) + void visit(const SymlinkPair& linkObj) override { ii_.iconPath = linkObj.getFullPath<side>(); ii_.drawAsLink = true; } - virtual void visit(const DirPair& dirObj) + void visit(const DirPair& dirObj) override { ii_.drawAsFolder = true; //todo: if ("is followed symlink") ii_.drawAsLink = true; @@ -703,40 +703,40 @@ private: return out; } - virtual wxString getToolTip(size_t row, ColumnType colType) const override + wxString getToolTip(size_t row, ColumnType colType) const override { wxString toolTip; - const FileSystemObject* fsObj = getRawData(row); - if (fsObj && !fsObj->isEmpty<side>()) - { - toolTip = toWx(getGridDataView() && getGridDataView()->getFolderPairCount() > 1 ? - fsObj->getFullPath<side>() : - fsObj->getRelativePath<side>()); - - struct AssembleTooltip : public FSObjectVisitor + if (const FileSystemObject* fsObj = getRawData(row)) + if (!fsObj->isEmpty<side>()) { - AssembleTooltip(wxString& tipMsg) : tipMsg_(tipMsg) {} + toolTip = toWx(getGridDataView() && getGridDataView()->getFolderPairCount() > 1 ? + fsObj->getFullPath<side>() : + fsObj->getRelativePath<side>()); - virtual void visit(const FilePair& fileObj) + struct AssembleTooltip : public FSObjectVisitor { - tipMsg_ += L"\n" + - _("Size:") + L" " + zen::filesizeToShortString(fileObj.getFileSize<side>()) + L"\n" + - _("Date:") + L" " + zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>()); - } + AssembleTooltip(wxString& tipMsg) : tipMsg_(tipMsg) {} - virtual void visit(const SymlinkPair& linkObj) - { - tipMsg_ += L"\n" + - _("Date:") + L" " + zen::utcToLocalTimeString(linkObj.getLastWriteTime<side>()); - } + void visit(const FilePair& fileObj) override + { + tipMsg_ += L"\n" + + _("Size:") + L" " + zen::filesizeToShortString(fileObj.getFileSize<side>()) + L"\n" + + _("Date:") + L" " + zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>()); + } - virtual void visit(const DirPair& dirObj) {} + void visit(const SymlinkPair& linkObj) override + { + tipMsg_ += L"\n" + + _("Date:") + L" " + zen::utcToLocalTimeString(linkObj.getLastWriteTime<side>()); + } - wxString& tipMsg_; - } assembler(toolTip); - fsObj->accept(assembler); - } + void visit(const DirPair& dirObj) override {} + + wxString& tipMsg_; + } assembler(toolTip); + fsObj->accept(assembler); + } return toolTip; } @@ -753,15 +753,15 @@ class GridDataLeft : public GridDataRim<LEFT_SIDE> public: GridDataLeft(const std::shared_ptr<const zen::GridView>& gridDataView, Grid& grid) : GridDataRim<LEFT_SIDE>(gridDataView, grid) {} - void setNavigationMarker(hash_set<const FileSystemObject*>&& markedFilesAndLinks, - hash_set<const HierarchyObject*>&& markedContainer) + void setNavigationMarker(std::unordered_set<const FileSystemObject*>&& markedFilesAndLinks, + std::unordered_set<const HierarchyObject*>&& markedContainer) { markedFilesAndLinks_.swap(markedFilesAndLinks); markedContainer_ .swap(markedContainer); } private: - virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override + void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override { GridDataRim<LEFT_SIDE>::renderRowBackgound(dc, rect, row, enabled, selected); @@ -809,8 +809,8 @@ private: } } - hash_set<const FileSystemObject*> markedFilesAndLinks_; //mark files/symlinks directly within a container - hash_set<const HierarchyObject*> markedContainer_; //mark full container including all child-objects + std::unordered_set<const FileSystemObject*> markedFilesAndLinks_; //mark files/symlinks directly within a container + std::unordered_set<const HierarchyObject*> markedContainer_; //mark full container including all child-objects //DO NOT DEREFERENCE!!!! NOT GUARANTEED TO BE VALID!!! }; @@ -941,7 +941,7 @@ public: void highlightSyncAction(bool value) { highlightSyncAction_ = value; } private: - virtual wxString getValue(size_t row, ColumnType colType) const override + wxString getValue(size_t row, ColumnType colType) const override { if (const FileSystemObject* fsObj = getRawData(row)) switch (static_cast<ColumnTypeMiddle>(colType)) @@ -956,7 +956,7 @@ private: return wxString(); } - virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override + void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override { if (enabled) { @@ -979,7 +979,7 @@ private: clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); } - virtual void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected) override + void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected) override { auto drawHighlightBackground = [&](const FileSystemObject& fsObj, const wxColor& col) { @@ -1064,7 +1064,7 @@ private: } } - virtual wxString getColumnLabel(ColumnType colType) const override + wxString getColumnLabel(ColumnType colType) const override { switch (static_cast<ColumnTypeMiddle>(colType)) { @@ -1078,9 +1078,9 @@ private: return wxEmptyString; } - virtual wxString getToolTip(ColumnType colType) const override { return getColumnLabel(colType); } + wxString getToolTip(ColumnType colType) const override { return getColumnLabel(colType); } - virtual void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override + void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override { switch (static_cast<ColumnTypeMiddle>(colType)) { @@ -1631,9 +1631,9 @@ void gridview::init(Grid& gridLeft, Grid& gridCenter, Grid& gridRight, const std gridCenter.SetSize(widthCategory + widthCheckbox + widthAction, -1); std::vector<Grid::ColumnAttribute> attribMiddle; - attribMiddle.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_CHECKBOX ), widthCheckbox, 0, true)); - attribMiddle.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_CMP_CATEGORY), widthCategory, 0, true)); - attribMiddle.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_SYNC_ACTION ), widthAction, 0, true)); + attribMiddle.emplace_back(static_cast<ColumnType>(COL_TYPE_CHECKBOX ), widthCheckbox, 0, true); + attribMiddle.emplace_back(static_cast<ColumnType>(COL_TYPE_CMP_CATEGORY), widthCategory, 0, true); + attribMiddle.emplace_back(static_cast<ColumnType>(COL_TYPE_SYNC_ACTION ), widthAction, 0, true); gridCenter.setColumnConfig(attribMiddle); } @@ -1788,8 +1788,8 @@ void gridview::setScrollMaster(Grid& grid) void gridview::setNavigationMarker(Grid& gridLeft, - hash_set<const FileSystemObject*>&& markedFilesAndLinks, - hash_set<const HierarchyObject*>&& markedContainer) + std::unordered_set<const FileSystemObject*>&& markedFilesAndLinks, + std::unordered_set<const HierarchyObject*>&& markedContainer) { if (auto provLeft = dynamic_cast<GridDataLeft*>(gridLeft.getDataProvider())) provLeft->setNavigationMarker(std::move(markedFilesAndLinks), std::move(markedContainer)); diff --git a/FreeFileSync/Source/ui/custom_grid.h b/FreeFileSync/Source/ui/custom_grid.h index 9d7c8856..02c08a6e 100644 --- a/FreeFileSync/Source/ui/custom_grid.h +++ b/FreeFileSync/Source/ui/custom_grid.h @@ -32,8 +32,8 @@ void setScrollMaster(Grid& grid); //mark rows selected in navigation/compressed tree and navigate to leading object void setNavigationMarker(Grid& gridLeft, - hash_set<const FileSystemObject*>&& markedFilesAndLinks,//mark files/symlinks directly within a container - hash_set<const HierarchyObject*>&& markedContainer); //mark full container including child-objects + std::unordered_set<const FileSystemObject*>&& markedFilesAndLinks,//mark files/symlinks directly within a container + std::unordered_set<const HierarchyObject*>&& markedContainer); //mark full container including child-objects } wxBitmap getSyncOpImage(SyncOperation syncOp); @@ -50,7 +50,7 @@ extern const wxEventType EVENT_GRID_SYNC_DIRECTION; struct CheckRowsEvent : public wxCommandEvent { CheckRowsEvent(size_t rowFirst, size_t rowLast, bool setIncluded) : wxCommandEvent(EVENT_GRID_CHECK_ROWS), rowFirst_(rowFirst), rowLast_(rowLast), setIncluded_(setIncluded) { assert(rowFirst <= rowLast); } - virtual wxEvent* Clone() const { return new CheckRowsEvent(*this); } + wxEvent* Clone() const override { return new CheckRowsEvent(*this); } const size_t rowFirst_; //selected range: [rowFirst_, rowLast_) const size_t rowLast_; //range is empty when clearing selection @@ -61,7 +61,7 @@ struct CheckRowsEvent : public wxCommandEvent struct SyncDirectionEvent : public wxCommandEvent { SyncDirectionEvent(size_t rowFirst, size_t rowLast, SyncDirection direction) : wxCommandEvent(EVENT_GRID_SYNC_DIRECTION), rowFirst_(rowFirst), rowLast_(rowLast), direction_(direction) { assert(rowFirst <= rowLast); } - virtual wxEvent* Clone() const { return new SyncDirectionEvent(*this); } + wxEvent* Clone() const override { return new SyncDirectionEvent(*this); } const size_t rowFirst_; //see CheckRowsEvent const size_t rowLast_; // diff --git a/FreeFileSync/Source/ui/dir_name.cpp b/FreeFileSync/Source/ui/dir_name.cpp index ea8a9386..993e7259 100644 --- a/FreeFileSync/Source/ui/dir_name.cpp +++ b/FreeFileSync/Source/ui/dir_name.cpp @@ -6,7 +6,7 @@ #include "dir_name.h" #include <zen/thread.h> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <wx/dnd.h> #include <wx/window.h> #include <wx/textctrl.h> diff --git a/FreeFileSync/Source/ui/folder_history_box.h b/FreeFileSync/Source/ui/folder_history_box.h index e310044f..35a03c69 100644 --- a/FreeFileSync/Source/ui/folder_history_box.h +++ b/FreeFileSync/Source/ui/folder_history_box.h @@ -42,7 +42,7 @@ public: zen::trim(nameTmp); //insert new folder or put it to the front if already existing - vector_remove_if(dirpaths_, [&](const Zstring& item) { return ::EqualFilename()(item, nameTmp); }); + zen::vector_remove_if(dirpaths_, [&](const Zstring& item) { return ::EqualFilename()(item, nameTmp); }); dirpaths_.insert(dirpaths_.begin(), nameTmp); diff --git a/FreeFileSync/Source/ui/grid_view.cpp b/FreeFileSync/Source/ui/grid_view.cpp index 704a5306..007c8040 100644 --- a/FreeFileSync/Source/ui/grid_view.cpp +++ b/FreeFileSync/Source/ui/grid_view.cpp @@ -19,7 +19,7 @@ void addNumbers(const FileSystemObject& fsObj, StatusResult& result) { GetValues(StatusResult& res) : result_(res) {} - virtual void visit(const FilePair& fileObj) + void visit(const FilePair& fileObj) override { if (!fileObj.isEmpty<LEFT_SIDE>()) { @@ -33,7 +33,7 @@ void addNumbers(const FileSystemObject& fsObj, StatusResult& result) } } - virtual void visit(const SymlinkPair& linkObj) + void visit(const SymlinkPair& linkObj) override { if (!linkObj.isEmpty<LEFT_SIDE>()) ++result_.filesOnLeftView; @@ -42,7 +42,7 @@ void addNumbers(const FileSystemObject& fsObj, StatusResult& result) ++result_.filesOnRightView; } - virtual void visit(const DirPair& dirObj) + void visit(const DirPair& dirObj) override { if (!dirObj.isEmpty<LEFT_SIDE>()) ++result_.foldersOnLeftView; @@ -70,14 +70,14 @@ void GridView::updateView(Predicate pred) if (pred(*fsObj)) { //save row position for direct random access to FilePair or DirPair - this->rowPositions.insert(std::make_pair(ref.objId, viewRef.size())); //costs: 0.28 µs per call - MSVC based on std::set + this->rowPositions.emplace(ref.objId, viewRef.size()); //costs: 0.28 µs per call - MSVC based on std::set //"this->" required by two-pass lookup as enforced by GCC 4.7 //save row position to identify first child *on sorted subview* of DirPair or BaseDirPair in case latter are filtered out const HierarchyObject* parent = &fsObj->parent(); for (;;) //map all yet unassociated parents to this row { - const auto rv = this->rowPositionsFirstChild.insert(std::make_pair(parent, viewRef.size())); + const auto rv = this->rowPositionsFirstChild.emplace(parent, viewRef.size()); if (!rv.second) break; @@ -320,12 +320,12 @@ private: void recurse(HierarchyObject& hierObj) { for (FilePair& fileObj : hierObj.refSubFiles()) - sortedRef_.push_back(RefIndex(index_, fileObj.getId())); + sortedRef_.emplace_back(index_, fileObj.getId()); for (SymlinkPair& linkObj : hierObj.refSubLinks()) - sortedRef_.push_back(RefIndex(index_, linkObj.getId())); + sortedRef_.emplace_back(index_, linkObj.getId()); for (DirPair& dirObj : hierObj.refSubDirs()) { - sortedRef_.push_back(RefIndex(index_, dirObj.getId())); + sortedRef_.emplace_back(index_, dirObj.getId()); recurse(dirObj); //add recursion here to list sub-objects directly below parent! } } diff --git a/FreeFileSync/Source/ui/grid_view.h b/FreeFileSync/Source/ui/grid_view.h index 9c0dd32b..9250e674 100644 --- a/FreeFileSync/Source/ui/grid_view.h +++ b/FreeFileSync/Source/ui/grid_view.h @@ -8,6 +8,7 @@ #define GRIDVIEW_H_INCLUDED #include <set> +#include <unordered_map> #include "column_attr.h" #include "../file_hierarchy.h" @@ -136,8 +137,8 @@ private: template <class Predicate> void updateView(Predicate pred); - zen::hash_map<FileSystemObject::ObjectIdConst, size_t> rowPositions; //find row positions on sortedRef directly - zen::hash_map<const void*, size_t> rowPositionsFirstChild; //find first child on sortedRef of a hierarchy object + std::unordered_map<FileSystemObject::ObjectIdConst, size_t> rowPositions; //find row positions on sortedRef directly + std::unordered_map<const void*, size_t> rowPositionsFirstChild; //find first child on sortedRef of a hierarchy object //void* instead of HierarchyObject*: these are weak pointers and should *never be dereferenced*! std::vector<FileSystemObject::ObjectId> viewRef; //partial view on sortedRef diff --git a/FreeFileSync/Source/ui/gui_generated.cpp b/FreeFileSync/Source/ui/gui_generated.cpp index d3fbc6e4..2bdd6aca 100644 --- a/FreeFileSync/Source/ui/gui_generated.cpp +++ b/FreeFileSync/Source/ui/gui_generated.cpp @@ -1325,12 +1325,18 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w wxBoxSizer* bSizer280; bSizer280 = new wxBoxSizer( wxHORIZONTAL ); - m_buttonClear = new wxButton( m_panelFilterSettingsHolder, wxID_DEFAULT, _("C&lear"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer280->Add( m_buttonClear, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_staticText44 = new wxStaticText( m_panelFilterSettingsHolder, wxID_ANY, _("Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair."), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticText44->Wrap( 600 ); - bSizer280->Add( m_staticText44, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 10 ); + m_staticText44->Wrap( 590 ); + bSizer280->Add( m_staticText44, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + + + bSizer280->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticline46 = new wxStaticLine( m_panelFilterSettingsHolder, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer280->Add( m_staticline46, 0, wxEXPAND, 5 ); + + m_buttonClear = new wxButton( m_panelFilterSettingsHolder, wxID_DEFAULT, _("C&lear"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + bSizer280->Add( m_buttonClear, 0, wxALL|wxALIGN_CENTER_VERTICAL, 10 ); bSizer278->Add( bSizer280, 0, wxEXPAND, 5 ); @@ -1339,7 +1345,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w m_panelFilterSettingsHolder->SetSizer( bSizer278 ); m_panelFilterSettingsHolder->Layout(); bSizer278->Fit( m_panelFilterSettingsHolder ); - m_notebook->AddPage( m_panelFilterSettingsHolder, _("dummy"), true ); + m_notebook->AddPage( m_panelFilterSettingsHolder, _("dummy"), false ); m_panelSyncSettingsHolder = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_panelSyncSettingsHolder->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); @@ -1401,7 +1407,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w m_checkBoxDetectMove = new wxCheckBox( m_panelSyncSettings, wxID_ANY, _("Detect moved files"), wxDefaultPosition, wxDefaultSize, 0 ); m_checkBoxDetectMove->SetValue(true); - m_checkBoxDetectMove->SetToolTip( _("- Requires and creates database files\n- Detection active after initial sync\n- Not supported by all file systems") ); + m_checkBoxDetectMove->SetToolTip( _("- Detection active after initial sync\n- Requires and creates database files\n- Not supported by all file systems") ); bSizer235->Add( m_checkBoxDetectMove, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5 ); @@ -1701,7 +1707,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 ); bSizer7->Add( m_notebook, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); @@ -3319,7 +3325,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS m_buttonDonate = new wxButton( m_panel39, wxID_ANY, _("Donate with PayPal"), wxDefaultPosition, wxDefaultSize, 0 ); m_buttonDonate->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) ); - m_buttonDonate->SetToolTip( _("http://freefilesync.sourceforge.net/donate.php") ); + m_buttonDonate->SetToolTip( _("http://www.freefilesync.org/donate.php") ); bSizer178->Add( m_buttonDonate, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); @@ -3359,7 +3365,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer166->Add( m_bitmap9, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - m_hyperlink1 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("freefilesync.sf.net"), wxT("http://freefilesync.sf.net/"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink1 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("freefilesync.org"), wxT("http://www.freefilesync.org/"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink1->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, true, wxEmptyString ) ); m_hyperlink1->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); diff --git a/FreeFileSync/Source/ui/gui_generated.h b/FreeFileSync/Source/ui/gui_generated.h index 4b238ba9..dc3dd4c7 100644 --- a/FreeFileSync/Source/ui/gui_generated.h +++ b/FreeFileSync/Source/ui/gui_generated.h @@ -300,8 +300,9 @@ protected: wxSpinCtrl* m_spinCtrlMaxSize; wxChoice* m_choiceUnitMaxSize; wxStaticLine* m_staticline62; - wxButton* m_buttonClear; wxStaticText* m_staticText44; + wxStaticLine* m_staticline46; + wxButton* m_buttonClear; wxPanel* m_panelSyncSettingsHolder; wxBoxSizer* bSizerLocalSyncSettings; wxCheckBox* m_checkBoxUseLocalSyncOptions; diff --git a/FreeFileSync/Source/ui/gui_status_handler.cpp b/FreeFileSync/Source/ui/gui_status_handler.cpp index de75eb3f..f9f63fa6 100644 --- a/FreeFileSync/Source/ui/gui_status_handler.cpp +++ b/FreeFileSync/Source/ui/gui_status_handler.cpp @@ -271,7 +271,7 @@ SyncStatusHandler::~SyncStatusHandler() try { //use EXEC_TYPE_ASYNC until there is reason not to: https://sourceforge.net/p/freefilesync/discussion/help/thread/828dca52 - tryReportingError([&] { shellExecute2(expandMacros(finalCommand), EXEC_TYPE_ASYNC); }, //throw FileError, throw X? + tryReportingError([&] { shellExecute(expandMacros(finalCommand), EXEC_TYPE_ASYNC); }, //throw FileError, throw X? *this); } catch (...) {} @@ -318,9 +318,10 @@ SyncStatusHandler::~SyncStatusHandler() (wxGetUTCTimeMillis().GetValue() - startTime_) / 1000 }; + //----------------- write results into LastSyncs.log------------------------ try { - saveToLastSyncsLog(summary, errorLog, lastSyncsLogFileSizeMax_); //throw FileError + saveToLastSyncsLog(summary, errorLog, lastSyncsLogFileSizeMax_, OnUpdateLogfileStatusNoThrow(*this, getLastSyncsLogfilePath())); //throw FileError } catch (FileError&) {} diff --git a/FreeFileSync/Source/ui/gui_status_handler.h b/FreeFileSync/Source/ui/gui_status_handler.h index 47c6e431..7f58afb8 100644 --- a/FreeFileSync/Source/ui/gui_status_handler.h +++ b/FreeFileSync/Source/ui/gui_status_handler.h @@ -27,14 +27,14 @@ public: CompareStatusHandler(MainDialog& dlg); ~CompareStatusHandler(); - virtual void initNewPhase(int objectsTotal, std::int64_t dataTotal, Phase phaseID); - virtual void forceUiRefresh(); + void initNewPhase(int objectsTotal, std::int64_t dataTotal, Phase phaseID) override; + void forceUiRefresh() override; - virtual Response reportError(const std::wstring& text, size_t retryNumber); - virtual void reportFatalError(const std::wstring& errorMessage); - virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive); + Response reportError (const std::wstring& text, size_t retryNumber) override; + void reportFatalError(const std::wstring& errorMessage) override; + void reportWarning (const std::wstring& warningMessage, bool& warningActive) override; - virtual void abortProcessNow(); //throw GuiAbortProcess + void abortProcessNow() override; //throw GuiAbortProcess private: void OnKeyPressed(wxKeyEvent& event); @@ -59,16 +59,16 @@ public: std::vector<Zstring>& onCompletionHistory); ~SyncStatusHandler(); - virtual void initNewPhase (int objectsTotal, std::int64_t dataTotal, Phase phaseID); - virtual void updateProcessedData(int objectsDelta, std::int64_t dataDelta); - virtual void reportInfo(const std::wstring& text); - virtual void forceUiRefresh(); + void initNewPhase (int objectsTotal, std::int64_t dataTotal, Phase phaseID) override; + void updateProcessedData(int objectsDelta, std::int64_t dataDelta ) override; + void reportInfo (const std::wstring& text ) override; + void forceUiRefresh () override; - virtual Response reportError(const std::wstring& text, size_t retryNumber); - virtual void reportFatalError(const std::wstring& errorMessage); - virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive); + Response reportError (const std::wstring& text, size_t retryNumber ) override; + void reportFatalError(const std::wstring& errorMessage ) override; + void reportWarning (const std::wstring& warningMessage, bool& warningActive) override; - virtual void abortProcessNow(); //throw GuiAbortProcess + void abortProcessNow() override; //throw GuiAbortProcess private: void onProgressDialogTerminate(); diff --git a/FreeFileSync/Source/ui/main_dlg.cpp b/FreeFileSync/Source/ui/main_dlg.cpp index 69aa6fb6..918da099 100644 --- a/FreeFileSync/Source/ui/main_dlg.cpp +++ b/FreeFileSync/Source/ui/main_dlg.cpp @@ -6,7 +6,7 @@ #include "main_dlg.h" #include <zen/format_unit.h> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/serialize.h> #include <zen/thread.h> #include <zen/shell_execute.h> @@ -94,7 +94,7 @@ public: DirectoryName(dropWindow1, dirSelectButton, dirpath, &staticText, &dropGrid.getMainWin()), mainDlg_(mainDlg) {} - virtual bool acceptDrop(const std::vector<wxString>& droppedFiles, const wxPoint& clientPos, const wxWindow& wnd) override + bool acceptDrop(const std::vector<wxString>& droppedFiles, const wxPoint& clientPos, const wxWindow& wnd) override { if (std::any_of(droppedFiles.begin(), droppedFiles.end(), [](const wxString& filepath) { @@ -155,13 +155,13 @@ public: mainDlg(mainDialog) {} private: - virtual MainConfiguration getMainConfig() const override { return mainDlg.getConfig().mainCfg; } - virtual wxWindow* getParentWindow() override { return &mainDlg; } - virtual std::unique_ptr<FilterConfig>& getFilterCfgOnClipboardRef() override { return mainDlg.filterCfgOnClipboard; } + MainConfiguration getMainConfig() const override { return mainDlg.getConfig().mainCfg; } + wxWindow* getParentWindow() override { return &mainDlg; } + std::unique_ptr<FilterConfig>& getFilterCfgOnClipboardRef() override { return mainDlg.filterCfgOnClipboard; } - virtual void onAltCompCfgChange () override { mainDlg.applyCompareConfig(); } - virtual void onAltSyncCfgChange () override { mainDlg.applySyncConfig(); } - virtual void onLocalFilterCfgChange() override { mainDlg.applyFilterConfig(); } //re-apply filter + void onAltCompCfgChange () override { mainDlg.applyCompareConfig(); } + void onAltSyncCfgChange () override { mainDlg.applySyncConfig(); } + void onLocalFilterCfgChange() override { mainDlg.applyFilterConfig(); } //re-apply filter MainDialog& mainDlg; }; @@ -260,7 +260,7 @@ public: MouseMoveWindow(mainDlg, false), //don't include main dialog itself, thereby prevent various mouse capture lost issues mainDlg_(mainDlg) {} - virtual bool allowMove(const wxMouseEvent& event) override + bool allowMove(const wxMouseEvent& event) override { if (wxPanel* panel = dynamic_cast<wxPanel*>(event.GetEventObject())) { @@ -537,11 +537,11 @@ MainDialog::MainDialog(const Zstring& globalConfigFile, auiMgr.AddPane(m_panelViewFilter, wxAuiPaneInfo().Name(L"PanelView").Layer(2).Bottom().Row(1).Caption(_("View Settings")).CaptionVisible(false).PaneBorder(false).Gripper().MinSize(m_bpButtonViewTypeSyncAction->GetSize().GetWidth(), m_panelViewFilter->GetSize().GetHeight())); - auiMgr.AddPane(m_gridNavi, - wxAuiPaneInfo().Name(L"PanelOverview").Layer(3).Left().Position(1).Caption(_("Overview")).MinSize(300, m_gridNavi->GetSize().GetHeight())); //MinSize(): just default size, see comment below - auiMgr.AddPane(m_panelConfig, - wxAuiPaneInfo().Name(L"PanelConfig").Layer(3).Left().Position(2).Caption(_("Configuration")).MinSize(m_listBoxHistory->GetSize().GetWidth(), m_panelConfig->GetSize().GetHeight())); + wxAuiPaneInfo().Name(L"PanelConfig").Layer(3).Left().Position(1).Caption(_("Configuration")).MinSize(m_listBoxHistory->GetSize().GetWidth(), m_panelConfig->GetSize().GetHeight())); + + auiMgr.AddPane(m_gridNavi, + wxAuiPaneInfo().Name(L"PanelOverview").Layer(3).Left().Position(2).Caption(_("Overview")).MinSize(300, m_gridNavi->GetSize().GetHeight())); //MinSize(): just default size, see comment below //set comparison button label tentatively for m_panelTopButtons to receive final height: updateTopButton(*m_buttonCompare, getResourceImage(L"compare"), L"Dummy", false); @@ -672,7 +672,7 @@ MainDialog::MainDialog(const Zstring& globalConfigFile, newItem->SetBitmap(getResourceImage(entry.languageFlag)); //map menu item IDs with language IDs: evaluated when processing event handler - languageMenuItemMap.insert(std::make_pair(newItem->GetId(), entry.languageID)); + languageMenuItemMap.emplace(newItem->GetId(), entry.languageID); //connect event this->Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnMenuLanguageSwitch)); @@ -917,7 +917,7 @@ void MainDialog::setGlobalCfgOnInit(const xmlAccess::XmlGlobalSettings& globalSe CaptionNameMapping captionNameMap; const wxAuiPaneInfoArray& paneArray = auiMgr.GetAllPanes(); for (size_t i = 0; i < paneArray.size(); ++i) - captionNameMap.push_back(std::make_pair(paneArray[i].caption, paneArray[i].name)); + captionNameMap.emplace_back(paneArray[i].caption, paneArray[i].name); auiMgr.LoadPerspective(globalSettings.gui.guiPerspectiveLast); @@ -961,7 +961,7 @@ xmlAccess::XmlGlobalSettings MainDialog::getGlobalCfgBeforeExit() std::map<int, Zstring> historyDetail; //(cfg-file/last use index) for (unsigned int i = 0; i < m_listBoxHistory->GetCount(); ++i) if (auto clientString = dynamic_cast<const wxClientHistoryData*>(m_listBoxHistory->GetClientObject(i))) - historyDetail.insert(std::make_pair(clientString->lastUseIndex_, clientString->cfgFile_)); + historyDetail.emplace(clientString->lastUseIndex_, clientString->cfgFile_); else assert(false); @@ -1162,7 +1162,7 @@ public: mainDlg.enableAllElements(); } - virtual Response reportError(const std::wstring& msg) override + Response reportError(const std::wstring& msg) override { if (ignoreErrors) return DeleteFilesHandler::IGNORE_ERROR; @@ -1189,7 +1189,7 @@ public: return DeleteFilesHandler::IGNORE_ERROR; //dummy return value } - virtual void reportWarning(const std::wstring& msg, bool& warningActive) override + void reportWarning(const std::wstring& msg, bool& warningActive) override { if (!warningActive || ignoreErrors) return; @@ -1208,7 +1208,7 @@ public: } } - virtual void reportStatus (const std::wstring& msg) override + void reportStatus (const std::wstring& msg) override { statusMsg = msg; requestUiRefresh(); @@ -1363,11 +1363,11 @@ void MainDialog::openExternalApplication(const wxString& commandline, const std: try { #ifdef ZEN_WIN - shellExecute2(L"\"" + fallbackDir + L"\"", EXEC_TYPE_ASYNC); //throw FileError + shellExecute(L"\"" + fallbackDir + L"\"", EXEC_TYPE_ASYNC); //throw FileError #elif defined ZEN_LINUX - shellExecute2("xdg-open \"" + fallbackDir + "\"", EXEC_TYPE_ASYNC); // + shellExecute("xdg-open \"" + fallbackDir + "\"", EXEC_TYPE_ASYNC); // #elif defined ZEN_MAC - shellExecute2("open \"" + fallbackDir + "\"", EXEC_TYPE_ASYNC); // + shellExecute("open \"" + fallbackDir + "\"", EXEC_TYPE_ASYNC); // #endif } catch (const FileError& e) { showNotificationDialog(this, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); } @@ -1422,7 +1422,7 @@ void MainDialog::openExternalApplication(const wxString& commandline, const std: try { //caveat: spawning too many threads asynchronously can easily kill a user's desktop session on Ubuntu! - shellExecute2(cmdExp, selectionTmp.size() > massInvokeThreshold ? EXEC_TYPE_SYNC : EXEC_TYPE_ASYNC); //throw FileError + shellExecute(cmdExp, selectionTmp.size() > massInvokeThreshold ? EXEC_TYPE_SYNC : EXEC_TYPE_ASYNC); //throw FileError } catch (const FileError& e) { showNotificationDialog(this, DialogInfoType::ERROR2, PopupDialogCfg().setDetailInstructions(e.toString())); } } @@ -1986,8 +1986,8 @@ void MainDialog::onNaviSelection(GridRangeSelectEvent& event) } //get selection on navigation tree and set corresponding markers on main grid - hash_set<const FileSystemObject*> markedFilesAndLinks; //mark files/symlinks directly - hash_set<const HierarchyObject*> markedContainer; //mark full container including child-objects + std::unordered_set<const FileSystemObject*> markedFilesAndLinks; //mark files/symlinks directly + std::unordered_set<const HierarchyObject*> markedContainer; //mark full container including child-objects const std::vector<size_t>& selection = m_gridNavi->getSelectedRows(); std::for_each(selection.begin(), selection.end(), @@ -2054,13 +2054,13 @@ void MainDialog::onNaviGridContext(GridClickEvent& event) //by short name Zstring labelShort = Zstring(Zstr("*")) + FILE_NAME_SEPARATOR + selection[0]->getPairShortName(); if (isDir) - labelShort += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); + labelShort += FILE_NAME_SEPARATOR + Zstring(Zstr("*")); submenu.addItem(utfCvrtTo<wxString>(labelShort), [this, &selection, include] { filterShortname(*selection[0], include); }); //by relative path Zstring labelRel = FILE_NAME_SEPARATOR + selection[0]->getPairRelativePath(); if (isDir) - labelRel += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); + labelRel += FILE_NAME_SEPARATOR + Zstring(Zstr("*")); submenu.addItem(utfCvrtTo<wxString>(labelRel), [this, &selection, include] { filterItems(selection, include); }); menu.addSubmenu(label, submenu, &getResourceImage(iconName)); @@ -2182,13 +2182,13 @@ void MainDialog::onMainGridContextRim(bool leftSide) //by short name Zstring labelShort = Zstring(Zstr("*")) + FILE_NAME_SEPARATOR + selection[0]->getPairShortName(); if (isDir) - labelShort += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); + labelShort += FILE_NAME_SEPARATOR + Zstring(Zstr("*")); submenu.addItem(utfCvrtTo<wxString>(labelShort), [this, &selection, include] { filterShortname(*selection[0], include); }); //by relative path Zstring labelRel = FILE_NAME_SEPARATOR + selection[0]->getPairRelativePath(); if (isDir) - labelRel += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); + labelRel += FILE_NAME_SEPARATOR + Zstring(Zstr("*")); submenu.addItem(utfCvrtTo<wxString>(labelRel), [this, &selection, include] { filterItems(selection, include); }); menu.addSubmenu(label, submenu, &getResourceImage(iconName)); @@ -2306,7 +2306,7 @@ void MainDialog::filterShortname(const FileSystemObject& fsObj, bool include) Zstring phrase = Zstring(Zstr("*")) + FILE_NAME_SEPARATOR + fsObj.getPairShortName(); const bool isDir = dynamic_cast<const DirPair*>(&fsObj) != nullptr; if (isDir) - phrase += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); //include filter: * required; exclude filter: * optional, but let's still apply it! + phrase += FILE_NAME_SEPARATOR + Zstring(Zstr("*")); //include filter: * required; exclude filter: * optional, but let's still apply it! filterPhrase(phrase, include, true); } @@ -2329,7 +2329,7 @@ void MainDialog::filterItems(const std::vector<FileSystemObject*>& selection, bo const bool isDir = dynamic_cast<const DirPair*>(fsObj) != nullptr; if (isDir) - phrase += Zstring(FILE_NAME_SEPARATOR) + Zstr("*"); //include filter: * required; exclude filter: * optional, but let's still apply it! + phrase += FILE_NAME_SEPARATOR + Zstring(Zstr("*")); //include filter: * required; exclude filter: * optional, but let's still apply it! } filterPhrase(phrase, include, true); } @@ -2486,8 +2486,8 @@ void MainDialog::OnCompSettingsContext(wxMouseEvent& event) auto currentVar = getConfig().mainCfg.cmpConfig.compareVar; - menu.addRadio(_("File time and size"), [&] { setVariant(CMP_BY_TIME_SIZE); }, currentVar == CMP_BY_TIME_SIZE); - menu.addRadio(_("File content" ), [&] { setVariant(CMP_BY_CONTENT); }, currentVar == CMP_BY_CONTENT); + menu.addRadio(getVariantName(CMP_BY_TIME_SIZE), [&] { setVariant(CMP_BY_TIME_SIZE); }, currentVar == CMP_BY_TIME_SIZE); + menu.addRadio(getVariantName(CMP_BY_CONTENT ), [&] { setVariant(CMP_BY_CONTENT); }, currentVar == CMP_BY_CONTENT); menu.popup(*this); } @@ -2505,10 +2505,10 @@ void MainDialog::OnSyncSettingsContext(wxMouseEvent& event) const auto currentVar = getConfig().mainCfg.syncCfg.directionCfg.var; - menu.addRadio(L"<- " + _("Two way") + L" ->" , [&] { setVariant(DirectionConfig::TWOWAY); }, currentVar == DirectionConfig::TWOWAY); - menu.addRadio( _("Mirror") + L" ->>", [&] { setVariant(DirectionConfig::MIRROR); }, currentVar == DirectionConfig::MIRROR); - menu.addRadio( _("Update") + L" ->" , [&] { setVariant(DirectionConfig::UPDATE); }, currentVar == DirectionConfig::UPDATE); - menu.addRadio( _("Custom") , [&] { setVariant(DirectionConfig::CUSTOM); }, currentVar == DirectionConfig::CUSTOM); + menu.addRadio(getVariantName(DirectionConfig::TWOWAY), [&] { setVariant(DirectionConfig::TWOWAY); }, currentVar == DirectionConfig::TWOWAY); + menu.addRadio(getVariantName(DirectionConfig::MIRROR), [&] { setVariant(DirectionConfig::MIRROR); }, currentVar == DirectionConfig::MIRROR); + menu.addRadio(getVariantName(DirectionConfig::UPDATE), [&] { setVariant(DirectionConfig::UPDATE); }, currentVar == DirectionConfig::UPDATE); + menu.addRadio(getVariantName(DirectionConfig::CUSTOM), [&] { setVariant(DirectionConfig::CUSTOM); }, currentVar == DirectionConfig::CUSTOM); menu.popup(*this); } @@ -2632,7 +2632,7 @@ void MainDialog::removeObsoleteCfgHistoryItems(const std::vector<Zstring>& filep std::list<boost::unique_future<bool>> fileEx; for (const Zstring& filepath : filepaths) - fileEx.push_back(zen::async2<bool>([=] { return fileExists(filepath); })); + fileEx.push_back(zen::async([=] { return fileExists(filepath); })); //potentially slow network access => limit maximum wait time! wait_for_all_timed(fileEx.begin(), fileEx.end(), boost::posix_time::milliseconds(1000)); @@ -3727,7 +3727,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event) if (it->isExisting<RIGHT_SIDE>()) dirpathsExisting.insert(it->getBaseDirPf<RIGHT_SIDE>()); } - dirLocks = make_unique<LockHolder>(dirpathsExisting, globalCfg.optDialogs.warningDirectoryLockFailed, statusHandler); + dirLocks = zen::make_unique<LockHolder>(dirpathsExisting, globalCfg.optDialogs.warningDirectoryLockFailed, statusHandler); } //START SYNCHRONIZATION @@ -4433,18 +4433,16 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event) if (provLeft && provMiddle && provRight) { - std::for_each(colAttrLeft.begin(), colAttrLeft.end(), - [&](const Grid::ColumnAttribute& ca) + for (const Grid::ColumnAttribute& ca : colAttrLeft) { header += fmtValue(provLeft->getColumnLabel(ca.type_)); header += CSV_SEP; - }); - std::for_each(colAttrMiddle.begin(), colAttrMiddle.end(), - [&](const Grid::ColumnAttribute& ca) + } + for (const Grid::ColumnAttribute& ca : colAttrMiddle) { header += fmtValue(provMiddle->getColumnLabel(ca.type_)); header += CSV_SEP; - }); + } if (!colAttrRight.empty()) { std::for_each(colAttrRight.begin(), colAttrRight.end() - 1, diff --git a/FreeFileSync/Source/ui/main_dlg.h b/FreeFileSync/Source/ui/main_dlg.h index a9becd95..689bd528 100644 --- a/FreeFileSync/Source/ui/main_dlg.h +++ b/FreeFileSync/Source/ui/main_dlg.h @@ -143,10 +143,10 @@ private: void OnContextSetLayout(wxMouseEvent& event); void onLocalKeyEvent (wxKeyEvent& event); - virtual void OnCompSettingsContext(wxMouseEvent& event) override; - virtual void OnSyncSettingsContext(wxMouseEvent& event) override; - virtual void OnGlobalFilterContext(wxMouseEvent& event) override; - virtual void OnViewButtonRightClick(wxMouseEvent& event) override; + void OnCompSettingsContext (wxMouseEvent& event) override; + void OnSyncSettingsContext (wxMouseEvent& event) override; + void OnGlobalFilterContext (wxMouseEvent& event) override; + void OnViewButtonRightClick(wxMouseEvent& event) override; void applyCompareConfig(bool setDefaultViewType = false); @@ -182,20 +182,20 @@ private: void onGridLabelContextR(zen::GridClickEvent& event); void onGridLabelContext(zen::Grid& grid, zen::ColumnTypeRim type, const std::vector<zen::ColumnAttributeRim>& defaultColumnAttributes); - virtual void OnToggleViewType (wxCommandEvent& event) override; - virtual void OnToggleViewButton(wxCommandEvent& event) override; + void OnToggleViewType (wxCommandEvent& event) override; + void OnToggleViewButton(wxCommandEvent& event) override; - virtual void OnConfigNew (wxCommandEvent& event) override; - virtual void OnConfigSave (wxCommandEvent& event) override; - virtual void OnConfigSaveAs (wxCommandEvent& event) override; - virtual void OnSaveAsBatchJob (wxCommandEvent& event) override; - virtual void OnConfigLoad (wxCommandEvent& event) override; - virtual void OnLoadFromHistory(wxCommandEvent& event) override; - virtual void OnLoadFromHistoryDoubleClick(wxCommandEvent& event); + void OnConfigNew (wxCommandEvent& event) override; + void OnConfigSave (wxCommandEvent& event) override; + void OnConfigSaveAs (wxCommandEvent& event) override; + void OnSaveAsBatchJob (wxCommandEvent& event) override; + void OnConfigLoad (wxCommandEvent& event) override; + void OnLoadFromHistory(wxCommandEvent& event) override; + void OnLoadFromHistoryDoubleClick(wxCommandEvent& event) override; void deleteSelectedCfgHistoryItems(); - virtual void OnCfgHistoryRightClick(wxMouseEvent& event) override; + void OnCfgHistoryRightClick(wxMouseEvent& event) override; void OnCfgHistoryKeyEvent (wxKeyEvent& event) override; void OnRegularUpdateCheck (wxIdleEvent& event); void OnLayoutWindowAsync (wxIdleEvent& event); @@ -204,10 +204,10 @@ private: void OnResizeTopButtonPanel (wxEvent& event); void OnResizeConfigPanel (wxEvent& event); void OnResizeViewPanel (wxEvent& event); - virtual void OnCompare (wxCommandEvent& event) override; - virtual void OnStartSync (wxCommandEvent& event) override; - virtual void OnSwapSides (wxCommandEvent& event) override; - virtual void OnClose (wxCloseEvent& event) override; + void OnCompare (wxCommandEvent& event) override; + void OnStartSync (wxCommandEvent& event) override; + void OnSwapSides (wxCommandEvent& event) override; + void OnClose (wxCloseEvent& event) override; void OnCmpSettings (wxCommandEvent& event) override { showConfigDialog(zen::SyncConfigPanel::COMPARISON); } void OnConfigureFilter(wxCommandEvent& event) override { showConfigDialog(zen::SyncConfigPanel::FILTER ); } @@ -220,9 +220,9 @@ private: void filterItems(const std::vector<zen::FileSystemObject*>& selection, bool include); void filterPhrase(const Zstring& phrase, bool include, bool addNewLine); - virtual void OnAddFolderPair (wxCommandEvent& event) override; + void OnAddFolderPair (wxCommandEvent& event) override; void OnRemoveFolderPair (wxCommandEvent& event); - virtual void OnRemoveTopFolderPair(wxCommandEvent& event) override; + void OnRemoveTopFolderPair(wxCommandEvent& event) override; void applyFilterConfig(); void applySyncConfig(); @@ -233,20 +233,20 @@ private: void resetLayout(); - virtual void OnSearchGridEnter(wxCommandEvent& event) override; - virtual void OnHideSearchPanel(wxCommandEvent& event) override; + void OnSearchGridEnter(wxCommandEvent& event) override; + void OnHideSearchPanel(wxCommandEvent& event) override; void OnSearchPanelKeyPressed(wxKeyEvent& event); //menu events - virtual void OnMenuOptions (wxCommandEvent& event) override; - virtual void OnMenuExportFileList(wxCommandEvent& event) override; - virtual void OnMenuResetLayout (wxCommandEvent& event) override { resetLayout(); } - virtual void OnMenuFindItem (wxCommandEvent& event) override; - virtual void OnMenuCheckVersion (wxCommandEvent& event) override; - virtual void OnMenuCheckVersionAutomatically(wxCommandEvent& event) override; - virtual void OnMenuAbout (wxCommandEvent& event) override; - virtual void OnShowHelp (wxCommandEvent& event) override; - virtual void OnMenuQuit (wxCommandEvent& event) override { Close(); } + void OnMenuOptions (wxCommandEvent& event) override; + void OnMenuExportFileList(wxCommandEvent& event) override; + void OnMenuResetLayout (wxCommandEvent& event) override { resetLayout(); } + void OnMenuFindItem (wxCommandEvent& event) override; + void OnMenuCheckVersion (wxCommandEvent& event) override; + void OnMenuCheckVersionAutomatically(wxCommandEvent& event) override; + void OnMenuAbout (wxCommandEvent& event) override; + void OnShowHelp (wxCommandEvent& event) override; + void OnMenuQuit (wxCommandEvent& event) override { Close(); } void OnMenuLanguageSwitch(wxCommandEvent& event); diff --git a/FreeFileSync/Source/ui/on_completion_box.cpp b/FreeFileSync/Source/ui/on_completion_box.cpp index 51b4dda1..274d0a30 100644 --- a/FreeFileSync/Source/ui/on_completion_box.cpp +++ b/FreeFileSync/Source/ui/on_completion_box.cpp @@ -28,7 +28,7 @@ std::vector<std::pair<std::wstring, Zstring>> getDefaultCommands() //(gui name/c { std::vector<std::pair<std::wstring, Zstring>> output; - auto addEntry = [&](const std::wstring& name, const Zstring& value) { output.push_back(std::make_pair(name, value)); }; + auto addEntry = [&](const std::wstring& name, const Zstring& value) { output.emplace_back(name, value); }; #ifdef ZEN_WIN if (zen::vistaOrLater()) @@ -36,7 +36,7 @@ std::vector<std::pair<std::wstring, Zstring>> getDefaultCommands() //(gui name/c addEntry(_("Standby" ), Zstr("rundll32.exe powrprof.dll,SetSuspendState Sleep")); //suspend/Suspend to RAM/sleep addEntry(_("Log off" ), Zstr("shutdown /l")); addEntry(_("Shut down"), Zstr("shutdown /s /t 60")); - //addEntry(_("Hibernate"), L"shutdown /h"); //Suspend to disk -> Standby is better anyway + //addEntry(_"Hibernate", L"shutdown /h"); //Suspend to disk -> Standby is better anyway } else //XP { diff --git a/FreeFileSync/Source/ui/osx_dock.h b/FreeFileSync/Source/ui/osx_dock.h deleted file mode 100644 index 62237524..00000000 --- a/FreeFileSync/Source/ui/osx_dock.h +++ /dev/null @@ -1,17 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef OSX_DOCK_837210847312534 -#define OSX_DOCK_837210847312534 - -#include <zen/sys_error.h> - -namespace osx -{ -void dockIconSetText(const char* str); //throw SysError -} - -#endif //OSX_DOCK_837210847312534 diff --git a/FreeFileSync/Source/ui/osx_dock.mm b/FreeFileSync/Source/ui/osx_dock.mm deleted file mode 100644 index 8f42ae88..00000000 --- a/FreeFileSync/Source/ui/osx_dock.mm +++ /dev/null @@ -1,24 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "osx_dock.h" -#include <Cocoa/Cocoa.h> -#include <zen/osx_throw_exception.h> - - -void osx::dockIconSetText(const char* str) //throw SysError -{ - @try - { - NSString* label = [NSString stringWithCString:str encoding:NSUTF8StringEncoding]; - //stringWithCString returns string which is already set to autorelease! - [[NSApp dockTile] setBadgeLabel:label]; //label may be nil - } - @catch (NSException* e) - { - throwSysError(e); //throw SysError - } -} diff --git a/FreeFileSync/Source/ui/progress_indicator.cpp b/FreeFileSync/Source/ui/progress_indicator.cpp index dc1f42a6..123e2649 100644 --- a/FreeFileSync/Source/ui/progress_indicator.cpp +++ b/FreeFileSync/Source/ui/progress_indicator.cpp @@ -26,7 +26,7 @@ #include <wx+/popup_dlg.h> #include <wx+/image_resources.h> #include <wx+/key_event.h> -#include <zen/file_handling.h> +#include <zen/file_access.h> #include <zen/thread.h> #include "gui_generated.h" #include "../lib/ffs_paths.h" @@ -410,7 +410,7 @@ public: for (auto it = log_.begin(); it != log_.end(); ++it) if (it->type & includedTypes) { - assert_static((IsSameType<GetCharType<MsgString>::Type, wchar_t>::value)); + static_assert(IsSameType<GetCharType<MsgString>::Type, wchar_t>::value, ""); assert(!startsWith(it->message, L'\n')); size_t rowNumber = 0; @@ -419,7 +419,7 @@ public: if (c == L'\n') { if (!lastCharNewline) //do not reference empty lines! - viewRef.push_back(Line(it, rowNumber)); + viewRef.emplace_back(it, rowNumber); ++rowNumber; lastCharNewline = true; } @@ -427,7 +427,7 @@ public: lastCharNewline = false; if (!lastCharNewline) - viewRef.push_back(Line(it, rowNumber)); + viewRef.emplace_back(it, rowNumber); } } @@ -481,9 +481,9 @@ class GridDataMessages : public GridData public: GridDataMessages(const std::shared_ptr<MessageView>& msgView) : msgView_(msgView) {} - virtual size_t getRowCount() const override { return msgView_ ? msgView_->rowsOnView() : 0; } + size_t getRowCount() const override { return msgView_ ? msgView_->rowsOnView() : 0; } - virtual wxString getValue(size_t row, ColumnType colType) const override + wxString getValue(size_t row, ColumnType colType) const override { if (msgView_) if (Opt<MessageView::LogEntryView> entry = msgView_->getEntry(row)) @@ -515,7 +515,7 @@ public: return wxEmptyString; } - virtual void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected) override + void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected) override { wxRect rectTmp = rect; @@ -572,7 +572,7 @@ public: } } - virtual int getBestSize(wxDC& dc, size_t row, ColumnType colType) override + int getBestSize(wxDC& dc, size_t row, ColumnType colType) override { // -> synchronize renderCell() <-> getBestSize() @@ -609,7 +609,7 @@ public: return std::max(getResourceImage(L"msg_info_small").GetHeight(), grid.getMainWin().GetCharHeight() + 2) + 1; //+ some space + bottom border } - virtual wxString getToolTip(size_t row, ColumnType colType) const override + wxString getToolTip(size_t row, ColumnType colType) const override { switch (static_cast<ColumnTypeMsg>(colType)) { @@ -623,7 +623,7 @@ public: return wxEmptyString; } - virtual wxString getColumnLabel(ColumnType colType) const override { return wxEmptyString; } + wxString getColumnLabel(ColumnType colType) const override { return wxEmptyString; } private: const std::shared_ptr<MessageView> msgView_; @@ -665,9 +665,9 @@ public: m_gridMessages->showRowLabel(false); m_gridMessages->setRowHeight(rowHeight); std::vector<Grid::ColumnAttribute> attr; - attr.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_MSG_TIME ), colMsgTimeWidth, 0)); - attr.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_MSG_CATEGORY), colMsgCategoryWidth, 0)); - attr.push_back(Grid::ColumnAttribute(static_cast<ColumnType>(COL_TYPE_MSG_TEXT ), -colMsgTimeWidth - colMsgCategoryWidth, 1)); + attr.emplace_back(static_cast<ColumnType>(COL_TYPE_MSG_TIME ), colMsgTimeWidth, 0); + attr.emplace_back(static_cast<ColumnType>(COL_TYPE_MSG_CATEGORY), colMsgCategoryWidth, 0); + attr.emplace_back(static_cast<ColumnType>(COL_TYPE_MSG_TEXT ), -colMsgTimeWidth - colMsgCategoryWidth, 1); m_gridMessages->setColumnConfig(attr); //support for CTRL + C @@ -682,19 +682,19 @@ public: } private: - virtual void OnErrors(wxCommandEvent& event) override + void OnErrors(wxCommandEvent& event) override { m_bpButtonErrors->toggle(); updateGrid(); } - virtual void OnWarnings(wxCommandEvent& event) override + void OnWarnings(wxCommandEvent& event) override { m_bpButtonWarnings->toggle(); updateGrid(); } - virtual void OnInfo(wxCommandEvent& event) override + void OnInfo(wxCommandEvent& event) override { m_bpButtonInfo->toggle(); updateGrid(); @@ -871,10 +871,10 @@ public: assert((!samples.empty() || lastSample == std::pair<int64_t, double>(0, 0))); //samples.clear(); - //samples.insert(std::make_pair(-1000, 0)); - //samples.insert(std::make_pair(0, 0)); - //samples.insert(std::make_pair(1, 1)); - //samples.insert(std::make_pair(1000, 0)); + //samples.emplace(-1000, 0); + //samples.emplace(0, 0); + //samples.emplace(1, 1); + //samples.emplace(1000, 0); //return; lastSample = std::make_pair(timeNowMs, value); @@ -893,7 +893,7 @@ public: } private: - virtual std::pair<double, double> getRangeX() const override + std::pair<double, double> getRangeX() const override { if (samples.empty()) return std::make_pair(0.0, 0.0); @@ -911,7 +911,7 @@ private: upperEndMs / 1000.0); } - virtual Opt<CurvePoint> getLessEq(double x) const override //x: seconds since begin + Opt<CurvePoint> getLessEq(double x) const override //x: seconds since begin { const int64_t timex = std::floor(x * 1000); //------ add artifical last sample value ------- @@ -929,7 +929,7 @@ private: return CurvePoint(it->first / 1000.0, it->second); } - virtual Opt<CurvePoint> getGreaterEq(double x) const override + Opt<CurvePoint> getGreaterEq(double x) const override { const int64_t timex = std::ceil(x * 1000); //------ add artifical last sample value ------- @@ -961,13 +961,13 @@ public: double getValueX() const { return x_; } private: - virtual std::pair<double, double> getRangeX() const override { return std::make_pair(x_, x_); } //conceptually just a vertical line! + std::pair<double, double> getRangeX() const override { return std::make_pair(x_, x_); } //conceptually just a vertical line! - virtual void getPoints(double minX, double maxX, int pixelWidth, std::vector<CurvePoint>& points) const override + void getPoints(double minX, double maxX, int pixelWidth, std::vector<CurvePoint>& points) const override { - points.push_back(CurvePoint(0, y_)); - points.push_back(CurvePoint(x_, y_)); - points.push_back(CurvePoint(x_, 0)); + points.emplace_back(0, y_); + points.emplace_back(x_, y_); + points.emplace_back(x_, 0); } double x_; //time elapsed in seconds @@ -980,7 +980,7 @@ const double stretchDefaultBlockSize = 1.4; //enlarge block default size struct LabelFormatterBytes : public LabelFormatter { - virtual double getOptimalBlockSize(double bytesProposed) const + double getOptimalBlockSize(double bytesProposed) const override { bytesProposed *= stretchDefaultBlockSize; //enlarge block default size @@ -998,13 +998,13 @@ struct LabelFormatterBytes : public LabelFormatter return e * numeric::nearMatch(a, std::begin(steps), std::end(steps)); } - virtual wxString formatText(double value, double optimalBlockSize) const { return filesizeToShortString(static_cast<std::int64_t>(value)); }; + wxString formatText(double value, double optimalBlockSize) const override { return filesizeToShortString(static_cast<std::int64_t>(value)); }; }; struct LabelFormatterItemCount : public LabelFormatter { - virtual double getOptimalBlockSize(double itemsProposed) const + double getOptimalBlockSize(double itemsProposed) const override { itemsProposed *= stretchDefaultBlockSize; //enlarge block default size @@ -1014,7 +1014,7 @@ struct LabelFormatterItemCount : public LabelFormatter return nextNiceNumber(itemsProposed); } - virtual wxString formatText(double value, double optimalBlockSize) const + wxString formatText(double value, double optimalBlockSize) const override { return toGuiString(numeric::round(value)); //not enough room for a "%x items" representation }; @@ -1025,7 +1025,7 @@ struct LabelFormatterTimeElapsed : public LabelFormatter { LabelFormatterTimeElapsed(bool drawLabel) : drawLabel_(drawLabel) {} - virtual double getOptimalBlockSize(double secProposed) const + double getOptimalBlockSize(double secProposed) const override { //5 sec minimum block size const double stepsSec[] = { 5, 10, 20, 30, 60 }; //nice numbers for seconds @@ -1034,7 +1034,7 @@ struct LabelFormatterTimeElapsed : public LabelFormatter const double stepsMin[] = { 1, 2, 5, 10, 15, 20, 30, 60 }; //nice numbers for minutes if (secProposed <= 3600) - return 60.0 * numeric::nearMatch(secProposed / 60, std::begin(stepsMin), std::end(stepsMin)); + return 60 * numeric::nearMatch(secProposed / 60, std::begin(stepsMin), std::end(stepsMin)); if (secProposed <= 3600 * 24) return 3600 * nextNiceNumber(secProposed / 3600); //round up to full hours @@ -1042,7 +1042,7 @@ struct LabelFormatterTimeElapsed : public LabelFormatter return 24 * 3600 * nextNiceNumber(secProposed / (24 * 3600)); //round to full days } - virtual wxString formatText(double timeElapsed, double optimalBlockSize) const + wxString formatText(double timeElapsed, double optimalBlockSize) const override { if (!drawLabel_) return wxString(); @@ -1078,27 +1078,27 @@ public: const wxString& jobName, const Zstring& onCompletion, std::vector<Zstring>& onCompletionHistory); - virtual ~SyncProgressDialogImpl(); + ~SyncProgressDialogImpl() override; //call this in StatusUpdater derived class destructor at the LATEST(!) to prevent access to currentStatusUpdater - virtual void processHasFinished(SyncResult resultId, const ErrorLog& log); - virtual void closeWindowDirectly(); + void processHasFinished(SyncResult resultId, const ErrorLog& log) override; + void closeWindowDirectly() override; - virtual wxWindow* getWindowIfVisible() { return this->IsShown() ? this : nullptr; } + wxWindow* getWindowIfVisible() override { return this->IsShown() ? this : nullptr; } //workaround OS X bug: if "this" is used as parent window for a modal dialog then this dialog will erroneously un-hide its parent! - virtual void initNewPhase(); - virtual void notifyProgressChange(); - virtual void updateGui() { updateGuiInt(true); } + void initNewPhase () override; + void notifyProgressChange() override; + void updateGui () override { updateGuiInt(true); } - virtual Zstring getExecWhenFinishedCommand() const { return pnl.m_comboBoxOnCompletion->getValue(); } + Zstring getExecWhenFinishedCommand() const override { return pnl.m_comboBoxOnCompletion->getValue(); } - virtual void stopTimer() //halt all internal counters! + void stopTimer() override //halt all internal counters! { pnl.m_animCtrlSyncing->Stop(); timeElapsed.pause(); } - virtual void resumeTimer() + void resumeTimer() override { pnl.m_animCtrlSyncing->Play(); timeElapsed.resume(); @@ -1182,8 +1182,8 @@ SyncProgressDialogImpl<TopLevelDialog>::SyncProgressDialogImpl(long style, //wxF timeLastSpeedEstimateMs (-1000000), //some big number phaseStartMs(0) { - assert_static((IsSameType<TopLevelDialog, wxFrame >::value || - IsSameType<TopLevelDialog, wxDialog>::value)); + static_assert(IsSameType<TopLevelDialog, wxFrame >::value || + IsSameType<TopLevelDialog, wxDialog>::value, ""); assert((IsSameType<TopLevelDialog, wxFrame>::value == !parentFrame)); //finish construction of this dialog: diff --git a/FreeFileSync/Source/ui/small_dlgs.cpp b/FreeFileSync/Source/ui/small_dlgs.cpp index 66692f7a..b142e8d8 100644 --- a/FreeFileSync/Source/ui/small_dlgs.cpp +++ b/FreeFileSync/Source/ui/small_dlgs.cpp @@ -40,9 +40,9 @@ public: AboutDlg(wxWindow* parent); private: - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnOK (wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_OKAY); } - virtual void OnDonate(wxCommandEvent& event) { wxLaunchDefaultBrowser(L"http://freefilesync.sourceforge.net/donate.php"); } + void OnClose (wxCloseEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } + void OnOK (wxCommandEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_OKAY); } + void OnDonate(wxCommandEvent& event) override { wxLaunchDefaultBrowser(L"http://www.freefilesync.org/donate.php"); } }; @@ -91,7 +91,7 @@ AboutDlg::AboutDlg(wxWindow* parent) : AboutDlgGenerated(parent) #endif build += zen::is64BitBuild ? L" x64" : L" x86"; - assert_static(zen::is32BitBuild || zen::is64BitBuild); + static_assert(zen::is32BitBuild || zen::is64BitBuild, ""); GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() @@ -151,11 +151,10 @@ public: bool& useRecycleBin); private: - virtual void OnOK(wxCommandEvent& event); - virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnDelOnBothSides(wxCommandEvent& event); - virtual void OnUseRecycler(wxCommandEvent& event); + void OnOK (wxCommandEvent& event) override; + void OnCancel(wxCommandEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } + void OnClose (wxCloseEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } + void OnUseRecycler (wxCommandEvent& event) override; void updateGui(); @@ -256,10 +255,6 @@ void DeleteDialog::OnOK(wxCommandEvent& event) EndModal(ReturnSmallDlg::BUTTON_OKAY); } -void DeleteDialog::OnDelOnBothSides(wxCommandEvent& event) -{ - updateGui(); -} void DeleteDialog::OnUseRecycler(wxCommandEvent& event) { @@ -289,9 +284,9 @@ public: const zen::SyncStatistics& st, bool& dontShowAgain); private: - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnStartSync(wxCommandEvent& event); + void OnClose (wxCloseEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } + void OnCancel (wxCommandEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } + void OnStartSync(wxCommandEvent& event) override; bool& m_dontShowAgain; }; @@ -379,18 +374,18 @@ public: OptionsDlg(wxWindow* parent, xmlAccess::XmlGlobalSettings& globalSettings); private: - virtual void OnOkay(wxCommandEvent& event); - virtual void OnResetDialogs(wxCommandEvent& event); - virtual void OnDefault(wxCommandEvent& event); - virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnAddRow(wxCommandEvent& event); - virtual void OnRemoveRow(wxCommandEvent& event); - virtual void OnHelpShowExamples(wxHyperlinkEvent& event) { displayHelpEntry(L"html/External Applications.html", this); } + void OnOkay (wxCommandEvent& event) override; + void OnResetDialogs(wxCommandEvent& event) override; + void OnDefault (wxCommandEvent& event) override; + void OnCancel (wxCommandEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } + 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 onResize(wxSizeEvent& event); void updateGui(); - virtual void OnToggleAutoRetryCount(wxCommandEvent& event) { updateGui(); } + void OnToggleAutoRetryCount(wxCommandEvent& event) override { updateGui(); } void setExtApp(const xmlAccess::ExternalApps& extApp); xmlAccess::ExternalApps getExtApp() const; @@ -578,7 +573,7 @@ xmlAccess::ExternalApps OptionsDlg::getExtApp() const description = it->second; if (!description.empty() || !commandline.empty()) - output.push_back(std::make_pair(description, commandline)); + output.emplace_back(description, commandline); } return output; } @@ -629,16 +624,16 @@ public: SelectTimespanDlg(wxWindow* parent, std::int64_t& timeFrom, std::int64_t& timeTo); private: - virtual void OnOkay(wxCommandEvent& event); - virtual void OnCancel(wxCommandEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnClose (wxCloseEvent& event) { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } + void OnOkay (wxCommandEvent& event) override; + void OnCancel(wxCommandEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } + void OnClose (wxCloseEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } - virtual void OnChangeSelectionFrom(wxCalendarEvent& event) + void OnChangeSelectionFrom(wxCalendarEvent& event) override { if (m_calendarFrom->GetDate() > m_calendarTo->GetDate()) m_calendarTo->SetDate(m_calendarFrom->GetDate()); } - virtual void OnChangeSelectionTo(wxCalendarEvent& event) + void OnChangeSelectionTo(wxCalendarEvent& event) override { if (m_calendarFrom->GetDate() > m_calendarTo->GetDate()) m_calendarFrom->SetDate(m_calendarTo->GetDate()); diff --git a/FreeFileSync/Source/ui/sorting.h b/FreeFileSync/Source/ui/sorting.h index 1493faa4..d022aeb7 100644 --- a/FreeFileSync/Source/ui/sorting.h +++ b/FreeFileSync/Source/ui/sorting.h @@ -7,7 +7,6 @@ #ifndef SORTING_H_82574232452345 #define SORTING_H_82574232452345 -#include <zen/assert_static.h> #include <zen/type_tools.h> #include "../file_hierarchy.h" @@ -17,9 +16,9 @@ namespace { struct CompileTimeReminder : public FSObjectVisitor { - virtual void visit(const FilePair& fileObj) {} - virtual void visit(const SymlinkPair& linkObj) {} - virtual void visit(const DirPair& dirObj ) {} + void visit(const FilePair& fileObj) override {} + void visit(const SymlinkPair& linkObj) override {} + void visit(const DirPair& dirObj ) override {} } checkDymanicCasts; //just a compile-time reminder to manually check dynamic casts in this file when needed } diff --git a/FreeFileSync/Source/ui/sync_cfg.cpp b/FreeFileSync/Source/ui/sync_cfg.cpp index 2973f194..88424ccb 100644 --- a/FreeFileSync/Source/ui/sync_cfg.cpp +++ b/FreeFileSync/Source/ui/sync_cfg.cpp @@ -48,9 +48,9 @@ public: const wxString& title); private: - virtual void OnOkay (wxCommandEvent& event) override; - virtual void OnCancel(wxCommandEvent& event) override { EndModal(ReturnSyncConfig::BUTTON_CANCEL); } - virtual void OnClose (wxCloseEvent& event) override { EndModal(ReturnSyncConfig::BUTTON_CANCEL); } + void OnOkay (wxCommandEvent& event) override; + void OnCancel(wxCommandEvent& event) override { EndModal(ReturnSyncConfig::BUTTON_CANCEL); } + void OnClose (wxCloseEvent& event) override { EndModal(ReturnSyncConfig::BUTTON_CANCEL); } void onLocalKeyEvent(wxKeyEvent& event); @@ -65,15 +65,15 @@ private: }; //------------- comparison panel ---------------------- - virtual void OnHelpComparisonSettings(wxHyperlinkEvent& event) override { displayHelpEntry(L"html/Comparison Settings.html" , this); } - virtual void OnHelpTimeShift (wxHyperlinkEvent& event) override { displayHelpEntry(L"html/Daylight Saving Time.html", this); } + 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); } - virtual void OnToggleLocalCompSettings(wxCommandEvent& event) override { updateCompGui(); updateSyncGui(); /*affects sync settings, too!*/ } - virtual void OnTimeSize(wxCommandEvent& event) override { localCmpVar = CMP_BY_TIME_SIZE; updateCompGui(); updateSyncGui(); /*affects sync settings, too!*/ } - virtual void OnContent (wxCommandEvent& event) override { localCmpVar = CMP_BY_CONTENT; updateCompGui(); updateSyncGui(); /*affects sync settings, too!*/ } - virtual void OnTimeSizeDouble(wxMouseEvent& event) override; - virtual void OnContentDouble (wxMouseEvent& event) override; - virtual void OnChangeCompOption(wxCommandEvent& event) override { updateCompGui(); } + void OnToggleLocalCompSettings(wxCommandEvent& event) override { updateCompGui(); updateSyncGui(); /*affects sync settings, too!*/ } + void OnTimeSize (wxCommandEvent& event) override { localCmpVar = CMP_BY_TIME_SIZE; updateCompGui(); updateSyncGui(); /*affects sync settings, too!*/ } + void OnContent (wxCommandEvent& event) override { localCmpVar = CMP_BY_CONTENT; updateCompGui(); updateSyncGui(); /*affects sync settings, too!*/ } + void OnTimeSizeDouble (wxMouseEvent& event) override; + void OnContentDouble (wxMouseEvent& event) override; + void OnChangeCompOption (wxCommandEvent& event) override { updateCompGui(); } void updateCompGui(); @@ -83,9 +83,9 @@ private: EnumDescrList<SymLinkHandling> enumDescrHandleSyml; //------------- filter panel -------------------------- - virtual void OnHelpShowExamples(wxHyperlinkEvent& event) override { displayHelpEntry(L"html/Exclude Items.html", this); } - virtual void OnChangeFilterOption(wxCommandEvent& event) override { updateFilterGui(); } - virtual void OnFilterReset (wxCommandEvent& event) override { setFilter(FilterConfig()); } + void OnHelpShowExamples(wxHyperlinkEvent& event) override { displayHelpEntry(L"html/Exclude Items.html", this); } + void OnChangeFilterOption(wxCommandEvent& event) override { updateFilterGui(); } + void OnFilterReset (wxCommandEvent& event) override { setFilter(FilterConfig()); } void onFilterKeyEvent(wxKeyEvent& event); void setFilter(const FilterConfig& filter); @@ -98,35 +98,35 @@ private: EnumDescrList<UnitSize> enumSizeDescr; //------------- synchronization panel ----------------- - virtual void OnSyncTwoWay(wxCommandEvent& event) override { directionCfg.var = DirectionConfig::TWOWAY; updateSyncGui(); } - virtual void OnSyncMirror(wxCommandEvent& event) override { directionCfg.var = DirectionConfig::MIRROR; updateSyncGui(); } - virtual void OnSyncUpdate(wxCommandEvent& event) override { directionCfg.var = DirectionConfig::UPDATE; updateSyncGui(); } - virtual void OnSyncCustom(wxCommandEvent& event) override { directionCfg.var = DirectionConfig::CUSTOM; updateSyncGui(); } - - virtual void OnToggleLocalSyncSettings(wxCommandEvent& event) override { updateSyncGui(); } - virtual void OnToggleDetectMovedFiles(wxCommandEvent& event) override { directionCfg.detectMovedFiles = !directionCfg.detectMovedFiles; updateSyncGui(); } - virtual void OnChangeSyncOption (wxCommandEvent& event) override { updateSyncGui(); } - - virtual void OnSyncTwoWayDouble(wxMouseEvent& event) override; - virtual void OnSyncMirrorDouble(wxMouseEvent& event) override; - virtual void OnSyncUpdateDouble(wxMouseEvent& event) override; - virtual void OnSyncCustomDouble(wxMouseEvent& event) override; - - virtual void OnExLeftSideOnly (wxCommandEvent& event) override; - virtual void OnExRightSideOnly(wxCommandEvent& event) override; - virtual void OnLeftNewer (wxCommandEvent& event) override; - virtual void OnRightNewer (wxCommandEvent& event) override; - virtual void OnDifferent (wxCommandEvent& event) override; - virtual void OnConflict (wxCommandEvent& event) override; - - virtual void OnDeletionPermanent (wxCommandEvent& event) override { handleDeletion = DELETE_PERMANENTLY; updateSyncGui(); } - virtual void OnDeletionRecycler (wxCommandEvent& event) override { handleDeletion = DELETE_TO_RECYCLER; updateSyncGui(); } - virtual void OnDeletionVersioning (wxCommandEvent& event) override { handleDeletion = DELETE_TO_VERSIONING; updateSyncGui(); } - - virtual void OnErrorPopup (wxCommandEvent& event) override { onGuiError = ON_GUIERROR_POPUP; updateSyncGui(); } - virtual void OnErrorIgnore(wxCommandEvent& event) override { onGuiError = ON_GUIERROR_IGNORE; updateSyncGui(); } - - virtual void OnHelpVersioning(wxHyperlinkEvent& event) override { displayHelpEntry(L"html/Versioning.html", this); } + void OnSyncTwoWay(wxCommandEvent& event) override { directionCfg.var = DirectionConfig::TWOWAY; updateSyncGui(); } + void OnSyncMirror(wxCommandEvent& event) override { directionCfg.var = DirectionConfig::MIRROR; updateSyncGui(); } + void OnSyncUpdate(wxCommandEvent& event) override { directionCfg.var = DirectionConfig::UPDATE; updateSyncGui(); } + void OnSyncCustom(wxCommandEvent& event) override { directionCfg.var = DirectionConfig::CUSTOM; updateSyncGui(); } + + void OnToggleLocalSyncSettings(wxCommandEvent& event) override { updateSyncGui(); } + void OnToggleDetectMovedFiles (wxCommandEvent& event) override { directionCfg.detectMovedFiles = !directionCfg.detectMovedFiles; updateSyncGui(); } + void OnChangeSyncOption (wxCommandEvent& event) override { updateSyncGui(); } + + void OnSyncTwoWayDouble(wxMouseEvent& event) override; + void OnSyncMirrorDouble(wxMouseEvent& event) override; + void OnSyncUpdateDouble(wxMouseEvent& event) override; + void OnSyncCustomDouble(wxMouseEvent& event) override; + + void OnExLeftSideOnly (wxCommandEvent& event) override; + void OnExRightSideOnly(wxCommandEvent& event) override; + void OnLeftNewer (wxCommandEvent& event) override; + void OnRightNewer (wxCommandEvent& event) override; + void OnDifferent (wxCommandEvent& event) override; + void OnConflict (wxCommandEvent& event) override; + + void OnDeletionPermanent (wxCommandEvent& event) override { handleDeletion = DELETE_PERMANENTLY; updateSyncGui(); } + void OnDeletionRecycler (wxCommandEvent& event) override { handleDeletion = DELETE_TO_RECYCLER; updateSyncGui(); } + void OnDeletionVersioning (wxCommandEvent& event) override { handleDeletion = DELETE_TO_VERSIONING; updateSyncGui(); } + + void OnErrorPopup (wxCommandEvent& event) override { onGuiError = ON_GUIERROR_POPUP; updateSyncGui(); } + void OnErrorIgnore(wxCommandEvent& event) override { onGuiError = ON_GUIERROR_IGNORE; updateSyncGui(); } + + void OnHelpVersioning(wxHyperlinkEvent& event) override { displayHelpEntry(L"html/Versioning.html", this); } struct SyncOptions { diff --git a/FreeFileSync/Source/ui/taskbar.cpp b/FreeFileSync/Source/ui/taskbar.cpp index 9e7cbcde..863eb6d6 100644 --- a/FreeFileSync/Source/ui/taskbar.cpp +++ b/FreeFileSync/Source/ui/taskbar.cpp @@ -9,6 +9,7 @@ #ifdef ZEN_WIN #include <zen/dll.h> #include <zen/win_ver.h> +#include <zen/stl_tools.h> #include "../dll/Taskbar_Seven/taskbar.h" #elif defined HAVE_UBUNTU_UNITY @@ -169,7 +170,7 @@ public: //######################################################################################################## -Taskbar::Taskbar(const wxFrame& window) : pimpl_(new Pimpl(window)) {} //throw TaskbarNotAvailable +Taskbar::Taskbar(const wxFrame& window) : pimpl_(zen::make_unique<Pimpl>(window)) {} //throw TaskbarNotAvailable Taskbar::~Taskbar() {} void Taskbar::setStatus(Status status) { pimpl_->setStatus(status); } diff --git a/FreeFileSync/Source/ui/tray_icon.cpp b/FreeFileSync/Source/ui/tray_icon.cpp index c9debfb1..712e4d51 100644 --- a/FreeFileSync/Source/ui/tray_icon.cpp +++ b/FreeFileSync/Source/ui/tray_icon.cpp @@ -129,12 +129,10 @@ public: //=> the only way to distinguish single left click and double-click is to wait wxSystemSettings::GetMetric(wxSYS_DCLICK_MSEC) (480ms) which is way too long! } - //virtual ~TaskBarImpl(){} - void dontCallbackAnymore() { onRequestResume_ = nullptr; } private: - virtual wxMenu* CreatePopupMenu() + wxMenu* CreatePopupMenu() override { if (!onRequestResume_) return nullptr; diff --git a/FreeFileSync/Source/ui/tree_view.cpp b/FreeFileSync/Source/ui/tree_view.cpp index de952465..6e5d4430 100644 --- a/FreeFileSync/Source/ui/tree_view.cpp +++ b/FreeFileSync/Source/ui/tree_view.cpp @@ -88,7 +88,7 @@ void TreeView::extractVisibleSubtree(HierarchyObject& hierObj, //in { const bool included = pred(subDirObj); - cont.subDirs.push_back(TreeView::DirNodeImpl()); // + cont.subDirs.emplace_back(); // auto& subDirCont = cont.subDirs.back(); TreeView::extractVisibleSubtree(subDirObj, subDirCont, pred); if (included) @@ -310,14 +310,14 @@ void TreeView::getChildren(const Container& cont, unsigned int level, std::vecto for (const DirNodeImpl& subDir : cont.subDirs) { - output.push_back(TreeView::TreeLine(level, 0, &subDir, TreeView::TYPE_DIRECTORY)); - workList.push_back(std::make_pair(subDir.bytesGross, &output.back().percent_)); + output.emplace_back(level, 0, &subDir, TreeView::TYPE_DIRECTORY); + workList.emplace_back(subDir.bytesGross, &output.back().percent_); } if (cont.firstFileId) { - output.push_back(TreeLine(level, 0, &cont, TreeView::TYPE_FILES)); - workList.push_back(std::make_pair(cont.bytesNet, &output.back().percent_)); + output.emplace_back(level, 0, &cont, TreeView::TYPE_FILES); + workList.emplace_back(cont.bytesNet, &output.back().percent_); } calcPercentage(workList); @@ -349,7 +349,7 @@ void TreeView::applySubView(std::vector<RootNodeImpl>&& newView) return nullptr; }; - zen::hash_set<const HierarchyObject*> expandedNodes; + std::unordered_set<const HierarchyObject*> expandedNodes; if (!flatTree.empty()) { auto it = flatTree.begin(); @@ -380,8 +380,8 @@ void TreeView::applySubView(std::vector<RootNodeImpl>&& newView) for (const RootNodeImpl& root : folderCmpView) { - flatTree.push_back(TreeView::TreeLine(0, 0, &root, TreeView::TYPE_ROOT)); - workList.push_back(std::make_pair(root.bytesGross, &flatTree.back().percent_)); + flatTree.emplace_back(0, 0, &root, TreeView::TYPE_ROOT); + workList.emplace_back(root.bytesGross, &flatTree.back().percent_); } calcPercentage(workList); @@ -418,7 +418,7 @@ void TreeView::updateView(Predicate pred) for (const std::shared_ptr<BaseDirPair>& baseObj : folderCmp) { - newView.push_back(TreeView::RootNodeImpl()); + newView.emplace_back(); RootNodeImpl& root = newView.back(); this->extractVisibleSubtree(*baseObj, root, pred); //"this->" is bogus for a static method, but GCC screws this one up @@ -683,7 +683,7 @@ std::unique_ptr<TreeView::Node> TreeView::getLine(size_t row) const case TreeView::TYPE_ROOT: { const auto& root = *static_cast<const TreeView::RootNodeImpl*>(flatTree[row].node_); - return make_unique<TreeView::RootNode>(percent, root.bytesGross, root.itemCountGross, getStatus(row), *root.baseDirObj, root.displayName); + return zen::make_unique<TreeView::RootNode>(percent, root.bytesGross, root.itemCountGross, getStatus(row), *root.baseDirObj, root.displayName); } break; @@ -691,7 +691,7 @@ std::unique_ptr<TreeView::Node> TreeView::getLine(size_t row) const { const auto* dir = static_cast<const TreeView::DirNodeImpl*>(flatTree[row].node_); if (auto dirObj = dynamic_cast<DirPair*>(FileSystemObject::retrieve(dir->objId))) - return make_unique<TreeView::DirNode>(percent, dir->bytesGross, dir->itemCountGross, level, getStatus(row), *dirObj); + return zen::make_unique<TreeView::DirNode>(percent, dir->bytesGross, dir->itemCountGross, level, getStatus(row), *dirObj); } break; @@ -712,7 +712,7 @@ std::unique_ptr<TreeView::Node> TreeView::getLine(size_t row) const if (lastViewFilterPred(fsObj)) filesAndLinks.push_back(&fsObj); - return make_unique<TreeView::FilesNode>(percent, parentDir->bytesNet, parentDir->itemCountNet, level, filesAndLinks); + return zen::make_unique<TreeView::FilesNode>(percent, parentDir->bytesNet, parentDir->itemCountNet, level, filesAndLinks); } } break; @@ -775,9 +775,9 @@ public: bool getShowPercentage() const { return showPercentBar; } private: - virtual size_t getRowCount() const { return treeDataView_ ? treeDataView_->linesTotal() : 0; } + size_t getRowCount() const override { return treeDataView_ ? treeDataView_->linesTotal() : 0; } - virtual wxString getToolTip(size_t row, ColumnType colType) const override + wxString getToolTip(size_t row, ColumnType colType) const override { switch (static_cast<ColumnTypeNavi>(colType)) { @@ -803,7 +803,7 @@ private: return wxString(); } - virtual wxString getValue(size_t row, ColumnType colType) const + wxString getValue(size_t row, ColumnType colType) const override { if (treeDataView_) { @@ -829,7 +829,7 @@ private: return wxString(); } - virtual void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override + void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override { wxRect rectInside = drawColumnLabelBorder(dc, rect); drawColumnLabelBackground(dc, rectInside, highlighted); @@ -852,7 +852,7 @@ private: static const int GAP_SIZE = 2; - virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override + void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override { if (enabled) { @@ -866,7 +866,7 @@ private: clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); } - virtual void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected) override + void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected) override { //wxRect rectTmp= drawCellBorder(dc, rect); wxRect rectTmp = rect; @@ -1036,7 +1036,7 @@ private: } } - virtual int getBestSize(wxDC& dc, size_t row, ColumnType colType) override + int getBestSize(wxDC& dc, size_t row, ColumnType colType) override { // -> synchronize renderCell() <-> getBestSize() <-> onMouseLeft() @@ -1054,7 +1054,7 @@ private: 2 * GAP_SIZE; //include gap from right! } - virtual wxString getColumnLabel(ColumnType colType) const + wxString getColumnLabel(ColumnType colType) const override { switch (static_cast<ColumnTypeNavi>(colType)) { diff --git a/FreeFileSync/Source/ui/triple_splitter.cpp b/FreeFileSync/Source/ui/triple_splitter.cpp index fbdd22d7..f88691ec 100644 --- a/FreeFileSync/Source/ui/triple_splitter.cpp +++ b/FreeFileSync/Source/ui/triple_splitter.cpp @@ -6,6 +6,7 @@ #include "triple_splitter.h" #include <algorithm> +#include <zen/stl_tools.h> using namespace zen; @@ -173,7 +174,7 @@ void TripleSplitter::onMouseLeftDown(wxMouseEvent& event) const int posX = event.GetPosition().x; if (hitOnSashLine(posX)) - activeMove.reset(new SashMove(*this, posX, centerOffset)); + activeMove = zen::make_unique<SashMove>(*this, posX, centerOffset); event.Skip(); } diff --git a/FreeFileSync/Source/version/version.h b/FreeFileSync/Source/version/version.h index 558b09ea..33153cb8 100644 --- a/FreeFileSync/Source/version/version.h +++ b/FreeFileSync/Source/version/version.h @@ -3,7 +3,7 @@ namespace zen { -const wchar_t currentVersion[] = L"6.10"; //internal linkage! +const wchar_t currentVersion[] = L"6.11"; //internal linkage! } #endif diff --git a/wx+/bitmap_button.h b/wx+/bitmap_button.h index 3255ffce..14476324 100644 --- a/wx+/bitmap_button.h +++ b/wx+/bitmap_button.h @@ -60,7 +60,7 @@ void setBitmapTextLabel(wxBitmapButton& btn, const wxImage& img, const wxString& } //SetMinSize() instead of SetSize() is needed here for wxWindows layout determination to work corretly - const int defaultHeight = wxButton::GetDefaultSize().GetHeight(); + const int defaultHeight = wxButton::GetDefaultSize().GetHeight(); btn.SetMinSize(wxSize(dynImage.GetWidth () + 2 * border, std::max(dynImage.GetHeight() + 2 * border, defaultHeight))); diff --git a/wx+/choice_enum.h b/wx+/choice_enum.h index e06931d5..57718158 100644 --- a/wx+/choice_enum.h +++ b/wx+/choice_enum.h @@ -41,7 +41,7 @@ struct EnumDescrList { EnumDescrList& add(Enum value, const wxString& text, const wxString& tooltip = wxEmptyString) { - descrList.push_back(std::make_pair(value, std::make_pair(text, tooltip))); + descrList.emplace_back(value, std::make_pair(text, tooltip)); return *this; } typedef std::vector<std::pair<Enum, std::pair<wxString, wxString>>> DescrList; diff --git a/wx+/context_menu.h b/wx+/context_menu.h index 2557737a..a498c429 100644 --- a/wx+/context_menu.h +++ b/wx+/context_menu.h @@ -28,7 +28,7 @@ namespace zen class ContextMenu : private wxEvtHandler { public: - ContextMenu() : menu(new wxMenu) {} + ContextMenu() : menu(zen::make_unique<wxMenu>()) {} void addItem(const wxString& label, const std::function<void()>& command, const wxBitmap* bmp = nullptr, bool enabled = true) { @@ -7,6 +7,7 @@ #ifndef DC_3813704987123956832143243214 #define DC_3813704987123956832143243214 +#include <unordered_map> #include <wx/dcbuffer.h> //for macro: wxALWAYS_NATIVE_DOUBLE_BUFFER namespace zen @@ -47,7 +48,7 @@ public: auto it = refDcToAreaMap().find(&dc); if (it != refDcToAreaMap().end()) { - oldRect.reset(new wxRect(it->second)); + oldRect = zen::make_unique<wxRect>(it->second); wxRect tmp = r; tmp.Intersect(*oldRect); //better safe than sorry @@ -57,7 +58,7 @@ public: else { dc_.SetClippingRegion(r); - refDcToAreaMap().insert(std::make_pair(&dc_, r)); + refDcToAreaMap().emplace(&dc_, r); } } @@ -75,7 +76,7 @@ public: private: //associate "active" clipping area with each DC - static hash_map<wxDC*, wxRect>& refDcToAreaMap() { static hash_map<wxDC*, wxRect> clippingAreas; return clippingAreas; } + static std::unordered_map<wxDC*, wxRect>& refDcToAreaMap() { static std::unordered_map<wxDC*, wxRect> clippingAreas; return clippingAreas; } std::unique_ptr<wxRect> oldRect; wxDC& dc_; @@ -97,7 +98,7 @@ public: { const wxSize clientSize = wnd.GetClientSize(); if (!buffer_ || clientSize != wxSize(buffer->GetWidth(), buffer->GetHeight())) - buffer.reset(new wxBitmap(clientSize.GetWidth(), clientSize.GetHeight())); + buffer = zen::make_unique<wxBitmap>(clientSize.GetWidth(), clientSize.GetHeight()); SelectObject(*buffer); diff --git a/wx+/file_drop.h b/wx+/file_drop.h index 47019a04..55772a03 100644 --- a/wx+/file_drop.h +++ b/wx+/file_drop.h @@ -59,7 +59,7 @@ public: dropWindow_(dropWindow), dropPos_(dropPos) {} - virtual wxEvent* Clone() const { return new FileDropEvent(*this); } + wxEvent* Clone() const override { return new FileDropEvent(*this); } const std::vector<wxString>& getFiles() const { return filesDropped_; } const wxWindow& getDropWindow() const { return dropWindow_; } @@ -85,7 +85,7 @@ public: WindowDropTarget(wxWindow& dropWindow) : dropWindow_(dropWindow) {} private: - virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& fileArray) + bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& fileArray) override { std::vector<wxString> filepaths(fileArray.begin(), fileArray.end()); if (!filepaths.empty()) diff --git a/wx+/graph.cpp b/wx+/graph.cpp index f4e758c1..67f8e354 100644 --- a/wx+/graph.cpp +++ b/wx+/graph.cpp @@ -119,18 +119,19 @@ void widenRange(double& valMin, double& valMax, //in/out { double valRangePerBlock = (valMax - valMin) * optimalBlockSizePx / graphAreaSize; //proposal valRangePerBlock = labelFmt.getOptimalBlockSize(valRangePerBlock); - if (!numeric::isNull(valRangePerBlock)) - { - int blockMin = std::floor(valMin / valRangePerBlock); - int blockMax = std::ceil (valMax / valRangePerBlock); - if (blockMin == blockMax) //handle valMin == valMax == integer - ++blockMax; - - valMin = blockMin * valRangePerBlock; - valMax = blockMax * valRangePerBlock; - blockCount = blockMax - blockMin; - return; - } + if (numeric::isNull(valRangePerBlock)) //handle valMin == valMax + valRangePerBlock = 1; + warn_static("/| arbitrary!?") + + int blockMin = std::floor(valMin / valRangePerBlock); + int blockMax = std::ceil (valMax / valRangePerBlock); + if (blockMin == blockMax) //handle valMin == valMax == integer + ++blockMax; + + valMin = blockMin * valRangePerBlock; + valMax = blockMax * valRangePerBlock; + blockCount = blockMax - blockMin; + return; } blockCount = 0; } @@ -322,7 +323,7 @@ void ContinuousCurveData::getPoints(double minX, double maxX, int pixelWidth, st for (int i = posFrom; i <= posTo; ++i) { const double x = cvrtX.screenToReal(i); - points.push_back(CurvePoint(x, getValue(x))); + points.emplace_back(x, getValue(x)); } } } @@ -343,7 +344,7 @@ void SparseCurveData::getPoints(double minX, double maxX, int pixelWidth, std::v if (addSteps_) if (pt.y != points.back().y) - points.push_back(CurvePoint(pt.x, points.back().y)); + points.emplace_back(CurvePoint(pt.x, points.back().y)); //[!] aliasing parameter not yet supported via emplace_back: VS bug! => make copy } points.push_back(pt); }; @@ -442,7 +443,7 @@ void Graph2D::onPaintEvent(wxPaintEvent& event) void Graph2D::OnMouseLeftDown(wxMouseEvent& event) { - activeSel.reset(new MouseSelection(*this, event.GetPosition())); + activeSel = zen::make_unique<MouseSelection>(*this, event.GetPosition()); if (!event.ControlDown()) oldSel.clear(); @@ -498,7 +499,7 @@ void Graph2D::addCurve(const std::shared_ptr<CurveData>& data, const CurveAttrib CurveAttributes newAttr = ca; if (newAttr.autoColor) newAttr.setColor(getDefaultColor(curves_.size())); - curves_.push_back(std::make_pair(data, newAttr)); + curves_.emplace_back(data, newAttr); Refresh(); } @@ -699,8 +700,8 @@ void Graph2D::render(wxDC& dc) const std::vector<wxPoint> points = drawPoints[it - curves_.begin()]; if (!points.empty()) { - points.push_back(wxPoint(points.back ().x, graphArea.GetBottom())); //add lower right and left corners - points.push_back(wxPoint(points.front().x, graphArea.GetBottom())); // + points.emplace_back(wxPoint(points.back ().x, graphArea.GetBottom())); //add lower right and left corners + points.emplace_back(wxPoint(points.front().x, graphArea.GetBottom())); //[!] aliasing parameter not yet supported via emplace_back: VS bug! => make copy wxDCBrushChanger dummy(dc, it->second.fillColor); wxDCPenChanger dummy2(dc, it->second.fillColor); diff --git a/wx+/graph.h b/wx+/graph.h index bafbe4eb..00b0b469 100644 --- a/wx+/graph.h +++ b/wx+/graph.h @@ -55,7 +55,7 @@ struct ContinuousCurveData : public CurveData virtual double getValue(double x) const = 0; private: - virtual void getPoints(double minX, double maxX, int pixelWidth, std::vector<CurvePoint>& points) const override; + void getPoints(double minX, double maxX, int pixelWidth, std::vector<CurvePoint>& points) const override; }; struct SparseCurveData : public CurveData @@ -66,19 +66,19 @@ struct SparseCurveData : public CurveData virtual Opt<CurvePoint> getGreaterEq(double x) const = 0; private: - virtual void getPoints(double minX, double maxX, int pixelWidth, std::vector<CurvePoint>& points) const override; + void getPoints(double minX, double maxX, int pixelWidth, std::vector<CurvePoint>& points) const override; bool addSteps_; }; struct ArrayCurveData : public SparseCurveData { virtual double getValue(size_t pos) const = 0; - virtual size_t getSize() const = 0; + virtual size_t getSize () const = 0; private: - virtual std::pair<double, double> getRangeX() const override { const size_t sz = getSize(); return std::make_pair(0.0, sz == 0 ? 0.0 : sz - 1.0); } + std::pair<double, double> getRangeX() const override { const size_t sz = getSize(); return std::make_pair(0.0, sz == 0 ? 0.0 : sz - 1.0); } - virtual Opt<CurvePoint> getLessEq(double x) const override + Opt<CurvePoint> getLessEq(double x) const override { const size_t sz = getSize(); const size_t pos = std::min<ptrdiff_t>(std::floor(x), sz - 1); //[!] expect unsigned underflow if empty! @@ -87,7 +87,7 @@ private: return NoValue(); } - virtual Opt<CurvePoint> getGreaterEq(double x) const override + Opt<CurvePoint> getGreaterEq(double x) const override { const size_t pos = std::max<ptrdiff_t>(std::ceil(x), 0); //[!] use std::max with signed type! if (pos < getSize()) @@ -100,8 +100,8 @@ struct VectorCurveData : public ArrayCurveData { std::vector<double>& refData() { return data; } private: - virtual double getValue(size_t pos) const override { return pos < data.size() ? data[pos] : 0; } - virtual size_t getSize() const override { return data.size(); } + double getValue(size_t pos) const override { return pos < data.size() ? data[pos] : 0; } + size_t getSize() const override { return data.size(); } std::vector<double> data; }; @@ -122,8 +122,8 @@ double nextNiceNumber(double blockSize); //round to next number which is conveni struct DecimalNumberFormatter : public LabelFormatter { - virtual double getOptimalBlockSize(double sizeProposed) const { return nextNiceNumber(sizeProposed); } - virtual wxString formatText(double value, double optimalBlockSize) const { return zen::numberTo<wxString>(value); } + double getOptimalBlockSize(double sizeProposed ) const override { return nextNiceNumber(sizeProposed); } + wxString formatText (double value, double optimalBlockSize) const override { return zen::numberTo<wxString>(value); } }; //------------------------------------------------------------------------------------------------------------ @@ -144,7 +144,7 @@ class GraphSelectEvent : public wxCommandEvent { public: GraphSelectEvent(const SelectionBlock& selBlock) : wxCommandEvent(wxEVT_GRAPH_SELECTION), selBlock_(selBlock) {} - virtual wxEvent* Clone() const { return new GraphSelectEvent(selBlock_); } + wxEvent* Clone() const override { return new GraphSelectEvent(selBlock_); } SelectionBlock getSelection() { return selBlock_; } diff --git a/wx+/grid.cpp b/wx+/grid.cpp index 5bcac1a5..de50d4c6 100644 --- a/wx+/grid.cpp +++ b/wx+/grid.cpp @@ -235,7 +235,7 @@ void GridData::drawColumnLabelText(wxDC& dc, const wxRect& rect, const wxString& CornerWin RowLabelWin ColLabelWin MainWin */ -class Grid::SubWindow : public wxWindow +class Grid::SubWindow : public wxWindow { public: SubWindow(Grid& parent) : @@ -378,9 +378,9 @@ public: CornerWin(Grid& parent) : SubWindow(parent) {} private: - virtual bool AcceptsFocus() const { return false; } + bool AcceptsFocus() const override { return false; } - virtual void render(wxDC& dc, const wxRect& rect) + void render(wxDC& dc, const wxRect& rect) override { const wxRect& clientRect = GetClientRect(); @@ -466,9 +466,9 @@ public: private: static wxString formatRow(size_t row) { return toGuiString(row + 1); } //convert number to std::wstring including thousands separator - virtual bool AcceptsFocus() const { return false; } + bool AcceptsFocus() const override { return false; } - virtual void render(wxDC& dc, const wxRect& rect) + void render(wxDC& dc, const wxRect& rect) override { /* @@ -537,9 +537,9 @@ private: } } - virtual void onMouseLeftDown(wxMouseEvent& event) { refParent().redirectRowLabelEvent(event); } - virtual void onMouseMovement(wxMouseEvent& event) { refParent().redirectRowLabelEvent(event); } - virtual void onMouseLeftUp (wxMouseEvent& event) { refParent().redirectRowLabelEvent(event); } + void onMouseLeftDown(wxMouseEvent& event) override { refParent().redirectRowLabelEvent(event); } + void onMouseMovement(wxMouseEvent& event) override { refParent().redirectRowLabelEvent(event); } + void onMouseLeftUp (wxMouseEvent& event) override { refParent().redirectRowLabelEvent(event); } int rowHeight; }; @@ -608,9 +608,9 @@ public: ColLabelWin(Grid& parent) : SubWindow(parent) {} private: - virtual bool AcceptsFocus() const { return false; } + bool AcceptsFocus() const override { return false; } - virtual void render(wxDC& dc, const wxRect& rect) + void render(wxDC& dc, const wxRect& rect) override { if (IsThisEnabled()) clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); @@ -680,7 +680,7 @@ private: } } - virtual void onMouseLeftDown(wxMouseEvent& event) + void onMouseLeftDown(wxMouseEvent& event) override { if (FindFocus() != &refParent().getMainWin()) refParent().getMainWin().SetFocus(); @@ -702,7 +702,7 @@ private: event.Skip(); } - virtual void onMouseLeftUp(wxMouseEvent& event) + void onMouseLeftUp(wxMouseEvent& event) override { activeResizing.reset(); //nothing else to do, actual work done by onMouseMovement() @@ -734,7 +734,7 @@ private: event.Skip(); } - virtual void onMouseCaptureLost(wxMouseCaptureLostEvent& event) + void onMouseCaptureLost(wxMouseCaptureLostEvent& event) override { activeResizing.reset(); activeMove.reset(); @@ -742,7 +742,7 @@ private: //event.Skip(); -> we DID handle it! } - virtual void onMouseLeftDouble(wxMouseEvent& event) + void onMouseLeftDouble(wxMouseEvent& event) override { if (Opt<ColAction> action = refParent().clientPosToColumnAction(event.GetPosition())) if (action->wantResize) @@ -758,7 +758,7 @@ private: event.Skip(); } - virtual void onMouseMovement(wxMouseEvent& event) + void onMouseMovement(wxMouseEvent& event) override { if (activeResizing) { @@ -820,14 +820,14 @@ private: event.Skip(); } - virtual void onLeaveWindow(wxMouseEvent& event) + void onLeaveWindow(wxMouseEvent& event) override { highlightCol.reset(); //wxEVT_LEAVE_WINDOW does not respect mouse capture! -> however highlight is drawn unconditionally during move/resize! Refresh(); event.Skip(); } - virtual void onMouseRightDown(wxMouseEvent& event) + void onMouseRightDown(wxMouseEvent& event) override { if (const Opt<ColAction> action = refParent().clientPosToColumnAction(event.GetPosition())) { @@ -863,7 +863,7 @@ public: ColLabelWin& colLabelWin) : SubWindow(parent), rowLabelWin_(rowLabelWin), colLabelWin_(colLabelWin), - cursorRow(0), + cursorRow(0), selectionAnchor(0), gridUpdatePending(false) { @@ -883,7 +883,7 @@ public: } private: - virtual void render(wxDC& dc, const wxRect& rect) + void render(wxDC& dc, const wxRect& rect) override { if (IsThisEnabled()) clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); @@ -959,12 +959,12 @@ private: return refParent().isSelected(row); } - virtual void onMouseLeftDown (wxMouseEvent& event) { onMouseDown(event); } - virtual void onMouseLeftUp (wxMouseEvent& event) { onMouseUp (event); } - virtual void onMouseRightDown(wxMouseEvent& event) { onMouseDown(event); } - virtual void onMouseRightUp (wxMouseEvent& event) { onMouseUp (event); } + void onMouseLeftDown (wxMouseEvent& event) override { onMouseDown(event); } + void onMouseLeftUp (wxMouseEvent& event) override { onMouseUp (event); } + void onMouseRightDown(wxMouseEvent& event) override { onMouseDown(event); } + void onMouseRightUp (wxMouseEvent& event) override { onMouseUp (event); } - virtual void onMouseLeftDouble(wxMouseEvent& event) + void onMouseLeftDouble(wxMouseEvent& event) override { const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition()); const auto row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range @@ -1058,14 +1058,14 @@ private: event.Skip(); //allow changing focus } - virtual void onMouseCaptureLost(wxMouseCaptureLostEvent& event) + void onMouseCaptureLost(wxMouseCaptureLostEvent& event) override { activeSelection.reset(); Refresh(); //event.Skip(); -> we DID handle it! } - virtual void onMouseMovement(wxMouseEvent& event) + void onMouseMovement(wxMouseEvent& event) override { if (activeSelection) activeSelection->evalMousePos(); //eval on both mouse movement + timer event! @@ -1089,7 +1089,7 @@ private: event.Skip(); } - virtual void onFocus(wxFocusEvent& event) { Refresh(); event.Skip(); } + void onFocus(wxFocusEvent& event) override { Refresh(); event.Skip(); } class MouseSelection : private wxEvtHandler { @@ -1188,7 +1188,7 @@ private: const std::int64_t ticksPerSec_; }; - virtual void ScrollWindow(int dx, int dy, const wxRect* rect) + void ScrollWindow(int dx, int dy, const wxRect* rect) override { wxWindow::ScrollWindow(dx, dy, rect); rowLabelWin_.ScrollWindow(0, dy, rect); @@ -1678,7 +1678,7 @@ void Grid::setColumnConfig(const std::vector<Grid::ColumnAttribute>& attr) std::vector<VisibleColumn> visCols; for (const ColumnAttribute& ca : attr) if (ca.visible_) - visCols.push_back(VisibleColumn(ca.type_, ca.offset_, ca.stretch_)); + visCols.emplace_back(ca.type_, ca.offset_, ca.stretch_); //"ownership" of visible columns is now within Grid visibleCols = visCols; @@ -2202,7 +2202,7 @@ std::vector<Grid::ColumnWidth> Grid::getColWidths(int mainWinWidth) const //eval else width = std::max(width, 0); //support smaller width than COLUMN_MIN_WIDTH if set via configuration - output.push_back(ColumnWidth(vc.type_, width)); + output.emplace_back(vc.type_, width); } return output; } @@ -39,7 +39,7 @@ extern const wxEventType EVENT_GRID_SELECT_RANGE; //generates: GridRangeSelectEv struct GridClickEvent : public wxMouseEvent { GridClickEvent(wxEventType et, const wxMouseEvent& me, ptrdiff_t row, ColumnType colType) : wxMouseEvent(me), row_(row), colType_(colType) { SetEventType(et); } - virtual wxEvent* Clone() const { return new GridClickEvent(*this); } + wxEvent* Clone() const override { return new GridClickEvent(*this); } const ptrdiff_t row_; //-1 for invalid position, >= rowCount if out of range const ColumnType colType_; //may be DUMMY_COLUMN_TYPE @@ -48,7 +48,7 @@ struct GridClickEvent : public wxMouseEvent struct GridColumnResizeEvent : public wxCommandEvent { GridColumnResizeEvent(int offset, ColumnType colType) : wxCommandEvent(EVENT_GRID_COL_RESIZE), colType_(colType), offset_(offset) {} - virtual wxEvent* Clone() const { return new GridColumnResizeEvent(*this); } + wxEvent* Clone() const override { return new GridColumnResizeEvent(*this); } const ColumnType colType_; const int offset_; @@ -57,7 +57,7 @@ struct GridColumnResizeEvent : public wxCommandEvent struct GridRangeSelectEvent : public wxCommandEvent { GridRangeSelectEvent(size_t rowFirst, size_t rowLast, bool positive) : wxCommandEvent(EVENT_GRID_SELECT_RANGE), positive_(positive), rowFirst_(rowFirst), rowLast_(rowLast) { assert(rowFirst <= rowLast); } - virtual wxEvent* Clone() const { return new GridRangeSelectEvent(*this); } + wxEvent* Clone() const override { return new GridRangeSelectEvent(*this); } const bool positive_; //"false" when clearing selection! const size_t rowFirst_; //selected range: [rowFirst_, rowLast_) @@ -92,10 +92,10 @@ public: //grid area virtual wxString getValue(size_t row, ColumnType colType) const = 0; - virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected); //default implementation - virtual void renderCell (wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected); // - virtual int getBestSize (wxDC& dc, size_t row, ColumnType colType); //must correspond to renderCell()! - virtual wxString getToolTip(size_t row, ColumnType colType) const { return wxString(); } + virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected); //default implementation + virtual void renderCell (wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected); // + virtual int getBestSize (wxDC& dc, size_t row, ColumnType colType ); //must correspond to renderCell()! + virtual wxString getToolTip (size_t row, ColumnType colType) const { return wxString(); } //label area virtual wxString getColumnLabel(ColumnType colType) const = 0; @@ -191,8 +191,8 @@ public: void scrollTo(size_t row); - virtual void Refresh(bool eraseBackground = true, const wxRect* rect = nullptr); - virtual bool Enable( bool enable = true) { Refresh(); return wxScrolledWindow::Enable(enable); } + void Refresh(bool eraseBackground = true, const wxRect* rect = nullptr) override; + bool Enable( bool enable = true) override { Refresh(); return wxScrolledWindow::Enable(enable); } //############################################################################################################ private: @@ -208,10 +208,10 @@ private: void redirectRowLabelEvent(wxMouseEvent& event); - virtual wxSize GetSizeAvailableForScrollTarget(const wxSize& size); //required since wxWidgets 2.9 if SetTargetWindow() is used + wxSize GetSizeAvailableForScrollTarget(const wxSize& size) override; //required since wxWidgets 2.9 if SetTargetWindow() is used #if defined ZEN_WIN || defined ZEN_MAC - virtual void SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh); //get rid of scrollbars, but preserve scrolling behavior! + void SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh) override; //get rid of scrollbars, but preserve scrolling behavior! #endif int getBestColumnSize(size_t col) const; //return -1 on error diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp index 3c471e2c..062ad88c 100644 --- a/wx+/image_resources.cpp +++ b/wx+/image_resources.cpp @@ -84,7 +84,7 @@ void GlobalResources::init(const Zstring& filepath) //generic image loading if (endsWith(name, L".png")) - bitmaps.insert(std::make_pair(name, wxImage(streamIn, wxBITMAP_TYPE_PNG))); + bitmaps.emplace(name, wxImage(streamIn, wxBITMAP_TYPE_PNG)); else if (endsWith(name, L".gif")) loadAnimFromZip(streamIn, anims[name]); } diff --git a/wx+/image_tools.cpp b/wx+/image_tools.cpp index d36fb2fa..b1732032 100644 --- a/wx+/image_tools.cpp +++ b/wx+/image_tools.cpp @@ -156,7 +156,7 @@ wxImage zen::createImageFromText(const wxString& text, const wxFont& font, const dc.SetTextBackground(*wxWHITE); // dc.SetFont(font); - assert(!contains(text, L"&")); //accelerator keys not supported here; see also getTextExtent() + assert(!contains(text, L"&")); //accelerator keys not supported here; see also getTextExtent() wxString textFmt = replaceCpy(text, L"&", L"", false); //for some reason wxDC::DrawText messes up "weak" bidi characters even when wxLayout_RightToLeft is set! (--> arrows in hebrew/arabic) diff --git a/wx+/popup_dlg.cpp b/wx+/popup_dlg.cpp index dff6bdb0..ff0bf125 100644 --- a/wx+/popup_dlg.cpp +++ b/wx+/popup_dlg.cpp @@ -149,8 +149,8 @@ public: } private: - virtual void OnClose (wxCloseEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::CANCEL)); } - virtual void OnCancel(wxCommandEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::CANCEL)); } + void OnClose (wxCloseEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::CANCEL)); } + void OnCancel(wxCommandEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::CANCEL)); } void OnKeyPressed(wxKeyEvent& event) { @@ -163,14 +163,14 @@ private: event.Skip(); } - virtual void OnButtonAffirmative(wxCommandEvent& event) override + void OnButtonAffirmative(wxCommandEvent& event) override { if (checkBoxValue_) * checkBoxValue_ = m_checkBoxCustom->GetValue(); EndModal(static_cast<int>(ConfirmationButton3::DO_IT)); } - virtual void OnButtonNegative(wxCommandEvent& event) override + void OnButtonNegative(wxCommandEvent& event) override { if (checkBoxValue_) * checkBoxValue_ = m_checkBoxCustom->GetValue(); @@ -243,7 +243,7 @@ public: } private: - virtual void OnCheckBoxClick(wxCommandEvent& event) override { updateGui(); event.Skip(); } + void OnCheckBoxClick(wxCommandEvent& event) override { updateGui(); event.Skip(); } void updateGui() { diff --git a/wx+/popup_dlg_generated.cpp b/wx+/popup_dlg_generated.cpp index a0a4cd5d..c3d50a70 100644 --- a/wx+/popup_dlg_generated.cpp +++ b/wx+/popup_dlg_generated.cpp @@ -11,79 +11,79 @@ PopupDialogGenerated::PopupDialogGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); - this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - - wxBoxSizer* bSizer24; - bSizer24 = new wxBoxSizer( wxVERTICAL ); - - m_panel33 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel33->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - - wxBoxSizer* bSizer165; - bSizer165 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapMsgType = new wxStaticBitmap( m_panel33, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer165->Add( m_bitmapMsgType, 0, wxALL, 10 ); - - wxBoxSizer* bSizer16; - bSizer16 = new wxBoxSizer( wxVERTICAL ); - - m_staticTextMain = new wxStaticText( m_panel33, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextMain->Wrap( -1 ); - bSizer16->Add( m_staticTextMain, 0, wxTOP|wxBOTTOM|wxRIGHT, 15 ); - - m_textCtrlTextDetail = new wxTextCtrl( m_panel33, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER ); - bSizer16->Add( m_textCtrlTextDetail, 1, wxEXPAND, 5 ); - - - bSizer165->Add( bSizer16, 1, wxEXPAND, 5 ); - - - m_panel33->SetSizer( bSizer165 ); - m_panel33->Layout(); - bSizer165->Fit( m_panel33 ); - bSizer24->Add( m_panel33, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_staticline6 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer24->Add( m_staticline6, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer25; - bSizer25 = new wxBoxSizer( wxVERTICAL ); - - m_checkBoxCustom = new wxCheckBox( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer25->Add( m_checkBoxCustom, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - - bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonAffirmative = new wxButton( this, wxID_YES, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonAffirmative, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - m_buttonNegative = new wxButton( this, wxID_NO, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonNegative, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); - - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); - - - bSizer25->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); - - - bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - - this->SetSizer( bSizer24 ); - this->Layout(); - bSizer24->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PopupDialogGenerated::OnClose ) ); - m_checkBoxCustom->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnCheckBoxClick ), NULL, this ); - m_buttonAffirmative->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnButtonAffirmative ), NULL, this ); - m_buttonNegative->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnButtonNegative ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnCancel ), NULL, this ); + this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + + wxBoxSizer* bSizer24; + bSizer24 = new wxBoxSizer( wxVERTICAL ); + + m_panel33 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel33->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + + wxBoxSizer* bSizer165; + bSizer165 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapMsgType = new wxStaticBitmap( m_panel33, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 ); + bSizer165->Add( m_bitmapMsgType, 0, wxALL, 10 ); + + wxBoxSizer* bSizer16; + bSizer16 = new wxBoxSizer( wxVERTICAL ); + + m_staticTextMain = new wxStaticText( m_panel33, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextMain->Wrap( -1 ); + bSizer16->Add( m_staticTextMain, 0, wxTOP|wxBOTTOM|wxRIGHT, 15 ); + + m_textCtrlTextDetail = new wxTextCtrl( m_panel33, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER ); + bSizer16->Add( m_textCtrlTextDetail, 1, wxEXPAND, 5 ); + + + bSizer165->Add( bSizer16, 1, wxEXPAND, 5 ); + + + m_panel33->SetSizer( bSizer165 ); + m_panel33->Layout(); + bSizer165->Fit( m_panel33 ); + bSizer24->Add( m_panel33, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + m_staticline6 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer24->Add( m_staticline6, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer25; + bSizer25 = new wxBoxSizer( wxVERTICAL ); + + m_checkBoxCustom = new wxCheckBox( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer25->Add( m_checkBoxCustom, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + + m_buttonAffirmative = new wxButton( this, wxID_YES, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + bSizerStdButtons->Add( m_buttonAffirmative, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_buttonNegative = new wxButton( this, wxID_NO, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + bSizerStdButtons->Add( m_buttonNegative, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); + + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); + + + bSizer25->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 ); + + + bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + + this->SetSizer( bSizer24 ); + this->Layout(); + bSizer24->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PopupDialogGenerated::OnClose ) ); + m_checkBoxCustom->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnCheckBoxClick ), NULL, this ); + m_buttonAffirmative->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnButtonAffirmative ), NULL, this ); + m_buttonNegative->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnButtonNegative ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnCancel ), NULL, this ); } PopupDialogGenerated::~PopupDialogGenerated() diff --git a/wx+/popup_dlg_generated.h b/wx+/popup_dlg_generated.h index ad1bc51c..b0397f1e 100644 --- a/wx+/popup_dlg_generated.h +++ b/wx+/popup_dlg_generated.h @@ -37,35 +37,35 @@ /////////////////////////////////////////////////////////////////////////////// /// Class PopupDialogGenerated /////////////////////////////////////////////////////////////////////////////// -class PopupDialogGenerated : public wxDialog +class PopupDialogGenerated : public wxDialog { - private: - - protected: - wxPanel* m_panel33; - wxStaticBitmap* m_bitmapMsgType; - wxStaticText* m_staticTextMain; - wxTextCtrl* m_textCtrlTextDetail; - wxStaticLine* m_staticline6; - wxCheckBox* m_checkBoxCustom; - wxBoxSizer* bSizerStdButtons; - wxButton* m_buttonAffirmative; - wxButton* m_buttonNegative; - wxButton* m_buttonCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } - virtual void OnCheckBoxClick( wxCommandEvent& event ) { event.Skip(); } - virtual void OnButtonAffirmative( wxCommandEvent& event ) { event.Skip(); } - virtual void OnButtonNegative( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } - - - public: - - PopupDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~PopupDialogGenerated(); - +private: + +protected: + wxPanel* m_panel33; + wxStaticBitmap* m_bitmapMsgType; + wxStaticText* m_staticTextMain; + wxTextCtrl* m_textCtrlTextDetail; + wxStaticLine* m_staticline6; + wxCheckBox* m_checkBoxCustom; + wxBoxSizer* bSizerStdButtons; + wxButton* m_buttonAffirmative; + wxButton* m_buttonNegative; + wxButton* m_buttonCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } + virtual void OnCheckBoxClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnButtonAffirmative( wxCommandEvent& event ) { event.Skip(); } + virtual void OnButtonNegative( wxCommandEvent& event ) { event.Skip(); } + virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } + + +public: + + PopupDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~PopupDialogGenerated(); + }; #endif //__POPUP_DLG_GENERATED_H__ @@ -55,7 +55,7 @@ void drawRtlImpl(wxDC& dc, const wxRect& rect, std::unique_ptr<wxBitmap>& buffer if (dc.GetLayoutDirection() == wxLayout_RightToLeft) { if (!buffer || buffer->GetWidth() != rect.width || buffer->GetHeight() < rect.height) //[!] since we do a mirror, width needs to match exactly! - buffer.reset(new wxBitmap(rect.width, rect.height)); + buffer = zen::make_unique<wxBitmap>(rect.width, rect.height); wxMemoryDC memDc(*buffer); memDc.Blit(wxPoint(0, 0), rect.GetSize(), &dc, rect.GetTopLeft()); //blit in: background is mirrored due to memDc, dc having different layout direction! diff --git a/wx+/std_button_layout.h b/wx+/std_button_layout.h index b7b1af3a..b5e30472 100644 --- a/wx+/std_button_layout.h +++ b/wx+/std_button_layout.h @@ -91,7 +91,7 @@ void setStandardButtonLayout(wxBoxSizer& sizer, const StdButtons& buttons) { assert(btn->GetMinSize().GetHeight() == -1); //let OS or this routine do the sizing! note: OS X does not allow changing the (visible!) button height! #if defined ZEN_WIN || defined ZEN_LINUX - const int defaultHeight = wxButton::GetDefaultSize().GetHeight(); //buffered by wxWidgets + const int defaultHeight = wxButton::GetDefaultSize().GetHeight(); //buffered by wxWidgets btn->SetMinSize(wxSize(-1, std::max(defaultHeight, 30))); //default button height is much too small => increase! #endif diff --git a/wx+/zlib_wrap.h b/wx+/zlib_wrap.h index 4cdc96b3..c271276f 100644 --- a/wx+/zlib_wrap.h +++ b/wx+/zlib_wrap.h @@ -85,12 +85,12 @@ BinContainer decompress(const BinContainer& stream) //throw ZlibInternalError std::copy(&*stream.begin(), &*stream.begin() + sizeof(uncompressedSize), reinterpret_cast<char*>(&uncompressedSize)); - //attention: contOut MUST NOT be empty! Else it will pass a nullptr to zlib_decompress() => Z_STREAM_ERROR although "uncompressedSize == 0"!!! - //secondary bug: don't dereference iterator into empty container! - if (uncompressedSize == 0) //cannot be 0: compress() directly maps empty -> empty container skipping zlib! - throw ZlibInternalError(); + //attention: contOut MUST NOT be empty! Else it will pass a nullptr to zlib_decompress() => Z_STREAM_ERROR although "uncompressedSize == 0"!!! + //secondary bug: don't dereference iterator into empty container! + if (uncompressedSize == 0) //cannot be 0: compress() directly maps empty -> empty container skipping zlib! + throw ZlibInternalError(); - try + try { contOut.resize(static_cast<size_t>(uncompressedSize)); //throw std::bad_alloc } diff --git a/zen/assert_static.h b/zen/assert_static.h deleted file mode 100644 index 17d5c370..00000000 --- a/zen/assert_static.h +++ /dev/null @@ -1,43 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef ASSERTSTATIC_H_INCLUDED -#define ASSERTSTATIC_H_INCLUDED - -/* -//compile time assert based on Loki (http://loki-lib.sourceforge.net) - -#ifdef NDEBUG - -#define assert_static(x) //((void)0) -> leads to error when seen in namespace scope! - -#else // debugging enabled -namespace static_check_impl -{ -template<int> -struct CompileTimeError; - -template<> -struct CompileTimeError<true> {}; -} - -#define LOKI_CONCAT(X, Y) LOKI_CONCAT_SUB(X, Y) -#define LOKI_CONCAT_SUB(X, Y) X ## Y - -#define assert_static(expr) \ - enum { LOKI_CONCAT(loki_enum_dummy_value, __LINE__) = sizeof(StaticCheckImpl::CompileTimeError<static_cast<bool>(expr) >) } - -// #define assert_static(expr) \ -// { Loki::CompileTimeError<((expr) != 0)> Static_Assert_Has_Failed; (void)Static_Assert_Has_Failed; } - -#endif -*/ - -//C++11: please get rid of this pointless string literal requirement! -#define assert_static(X) \ - static_assert(X, "Static assert has failed!"); - -#endif //ASSERTSTATIC_H_INCLUDED diff --git a/zen/basic_math.h b/zen/basic_math.h index 69e861be..41f42dbe 100644 --- a/zen/basic_math.h +++ b/zen/basic_math.h @@ -145,7 +145,7 @@ T clampCpy(const T& val, const T& minVal, const T& maxVal) } template <class T> inline -void clamp(T& val, const T& minVal, const T& maxVal) +void clamp(T& val, const T& minVal, const T& maxVal) { assert(minVal <= maxVal); if (val < minVal) diff --git a/zen/dir_watcher.cpp b/zen/dir_watcher.cpp index 3751e5dd..9a685fc5 100644 --- a/zen/dir_watcher.cpp +++ b/zen/dir_watcher.cpp @@ -40,7 +40,7 @@ public: boost::lock_guard<boost::mutex> dummy(lockAccess); if (bytesWritten == 0) //according to docu this may happen in case of internal buffer overflow: report some "dummy" change - changedFiles.push_back(DirWatcher::Entry(DirWatcher::ACTION_CREATE, L"Overflow.")); + changedFiles.emplace_back(DirWatcher::ACTION_CREATE, L"Overflow."); else { const char* bufPos = &buffer[0]; @@ -67,14 +67,14 @@ public: { case FILE_ACTION_ADDED: case FILE_ACTION_RENAMED_NEW_NAME: //harmonize with "move" which is notified as "create + delete" - changedFiles.push_back(DirWatcher::Entry(DirWatcher::ACTION_CREATE, fullpath)); + changedFiles.emplace_back(DirWatcher::ACTION_CREATE, fullpath); break; case FILE_ACTION_REMOVED: case FILE_ACTION_RENAMED_OLD_NAME: - changedFiles.push_back(DirWatcher::Entry(DirWatcher::ACTION_DELETE, fullpath)); + changedFiles.emplace_back(DirWatcher::ACTION_DELETE, fullpath); break; case FILE_ACTION_MODIFIED: - changedFiles.push_back(DirWatcher::Entry(DirWatcher::ACTION_UPDATE, fullpath)); + changedFiles.emplace_back(DirWatcher::ACTION_UPDATE, fullpath); break; } }(); @@ -193,8 +193,8 @@ public: nullptr); //__in_opt LPCTSTR lpName if (overlapped.hEvent == nullptr) { - const DWORD lastError = ::GetLastError(); //copy before directly or indirectly making other system calls! - return shared_->reportError(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(dirpathPf)), formatSystemError(L"CreateEvent", lastError), lastError); + const DWORD ec = ::GetLastError(); //copy before directly or indirectly making other system calls! + return shared_->reportError(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(dirpathPf)), formatSystemError(L"CreateEvent", ec), ec); } ZEN_ON_SCOPE_EXIT(::CloseHandle(overlapped.hEvent)); @@ -213,8 +213,8 @@ public: &overlapped, // __inout_opt LPOVERLAPPED lpOverlapped, nullptr)) // __in_opt LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine { - const DWORD lastError = ::GetLastError(); //copy before directly or indirectly making other system calls! - return shared_->reportError(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(dirpathPf)), formatSystemError(L"ReadDirectoryChangesW", lastError), lastError); + const DWORD ec = ::GetLastError(); //copy before directly or indirectly making other system calls! + return shared_->reportError(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(dirpathPf)), formatSystemError(L"ReadDirectoryChangesW", ec), ec); } //async I/O is a resource that needs to be guarded since it will write to local variable "buffer"! @@ -236,9 +236,9 @@ public: &bytesWritten, //__out LPDWORD lpNumberOfBytesTransferred, false)) //__in BOOL bWait { - const DWORD lastError = ::GetLastError(); //copy before directly or indirectly making other system calls! - if (lastError != ERROR_IO_INCOMPLETE) - return shared_->reportError(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(dirpathPf)), formatSystemError(L"GetOverlappedResult", lastError), lastError); + const DWORD ec = ::GetLastError(); //copy before directly or indirectly making other system calls! + if (ec != ERROR_IO_INCOMPLETE) + return shared_->reportError(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(dirpathPf)), formatSystemError(L"GetOverlappedResult", ec), ec); //execute asynchronous procedure calls (APC) queued on this thread ::SleepEx(50, // __in DWORD dwMilliseconds, @@ -287,7 +287,7 @@ public: bool finished() const { return operationComplete; } private: - virtual void onRequestRemoval(HANDLE hnd) + void onRequestRemoval(HANDLE hnd) override { //must release hDir immediately => stop monitoring! if (worker_.joinable()) //= join() precondition: play safe; can't trust Windows to only call-back once @@ -300,7 +300,7 @@ private: removalRequested = true; } //don't throw! - virtual void onRemovalFinished(HANDLE hnd, bool successful) { operationComplete = true; } //throw()! + void onRemovalFinished(HANDLE hnd, bool successful) override { operationComplete = true; } //throw()! boost::thread& worker_; bool removalRequested; @@ -320,13 +320,13 @@ struct DirWatcher::Pimpl DirWatcher::DirWatcher(const Zstring& directory) : //throw FileError - pimpl_(new Pimpl) + pimpl_(zen::make_unique<Pimpl>()) { pimpl_->shared = std::make_shared<SharedData>(); pimpl_->dirpath = directory; ReadChangesAsync reader(directory, pimpl_->shared); //throw FileError - pimpl_->volRemoval.reset(new HandleVolumeRemoval(reader.getDirHandle(), pimpl_->worker)); //throw FileError + pimpl_->volRemoval = zen::make_unique<HandleVolumeRemoval>(reader.getDirHandle(), pimpl_->worker); //throw FileError pimpl_->worker = boost::thread(std::move(reader)); } @@ -360,7 +360,7 @@ std::vector<DirWatcher::Entry> DirWatcher::getChanges(const std::function<void() boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(50)); } - output.push_back(Entry(ACTION_DELETE, pimpl_->dirpath)); //report removal as change to main directory + output.emplace_back(ACTION_DELETE, pimpl_->dirpath); //report removal as change to main directory } else //the normal case... pimpl_->shared->fetchChanges(output); //throw FileError @@ -376,15 +376,15 @@ class DirsOnlyTraverser : public zen::TraverseCallback public: DirsOnlyTraverser(std::vector<Zstring>& dirs) : dirs_(dirs) {} - virtual void onFile (const Zchar* shortName, const Zstring& filepath, const FileInfo& details) {} - virtual HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) { return LINK_SKIP; } - virtual TraverseCallback* onDir(const Zchar* shortName, const Zstring& dirpath) + void onFile (const Zchar* shortName, const Zstring& filepath, const FileInfo& details ) override {} + HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) override { return LINK_SKIP; } + TraverseCallback* onDir (const Zchar* shortName, const Zstring& dirpath ) override { dirs_.push_back(dirpath); return this; } - virtual HandleError reportDirError (const std::wstring& msg, size_t retryNumber) { throw FileError(msg); } - virtual HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) { throw FileError(msg); } + HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override { throw FileError(msg); } + HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) override { throw FileError(msg); } private: std::vector<Zstring>& dirs_; @@ -403,7 +403,7 @@ struct DirWatcher::Pimpl DirWatcher::DirWatcher(const Zstring& directory) : //throw FileError - pimpl_(new Pimpl) + pimpl_(zen::make_unique<Pimpl>()) { //get all subdirectories Zstring dirpathFmt = directory; @@ -449,9 +449,15 @@ DirWatcher::DirWatcher(const Zstring& directory) : //throw FileError IN_MOVED_TO | IN_MOVE_SELF); if (wd == -1) - throwFileError(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(subdir)), L"inotify_add_watch", getLastError()); + { + const auto ec = getLastError(); + if (ec == ENOSPC) //fix misleading system message "No space left on device" + throw FileError(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(subdir)), formatSystemError(L"inotify_add_watch", ec, L"The user limit on the total number of inotify watches was reached or the kernel failed to allocate a needed resource.")); + + throw FileError(replaceCpy(_("Cannot monitor directory %x."), L"%x", fmtFileName(subdir)), formatSystemError(L"inotify_add_watch", ec)); + } - pimpl_->watchDescrs.insert(std::make_pair(wd, appendSeparator(subdir))); + pimpl_->watchDescrs.emplace(wd, appendSeparator(subdir)); } guardDescr.dismiss(); @@ -502,15 +508,15 @@ std::vector<DirWatcher::Entry> DirWatcher::getChanges(const std::function<void() if ((evt.mask & IN_CREATE) || (evt.mask & IN_MOVED_TO)) - output.push_back(Entry(ACTION_CREATE, fullname)); + output.emplace_back(ACTION_CREATE, fullname); else if ((evt.mask & IN_MODIFY) || (evt.mask & IN_CLOSE_WRITE)) - output.push_back(Entry(ACTION_UPDATE, fullname)); + output.emplace_back(ACTION_UPDATE, fullname); else if ((evt.mask & IN_DELETE ) || (evt.mask & IN_DELETE_SELF) || (evt.mask & IN_MOVE_SELF ) || (evt.mask & IN_MOVED_FROM)) - output.push_back(Entry(ACTION_DELETE, fullname)); + output.emplace_back(ACTION_DELETE, fullname); } } bytePos += sizeof(struct ::inotify_event) + evt.len; @@ -541,7 +547,7 @@ void eventCallback(ConstFSEventStreamRef streamRef, if (eventFlags[i] & kFSEventStreamEventFlagItemCreated || eventFlags[i] & kFSEventStreamEventFlagMount) - changedFiles.push_back(DirWatcher::Entry(DirWatcher::ACTION_CREATE, paths[i])); + changedFiles.emplace_back(DirWatcher::ACTION_CREATE, paths[i]); if (eventFlags[i] & kFSEventStreamEventFlagItemModified || // eventFlags[i] & kFSEventStreamEventFlagItemXattrMod || // eventFlags[i] & kFSEventStreamEventFlagItemChangeOwner || //aggregate these into a single event @@ -549,11 +555,11 @@ void eventCallback(ConstFSEventStreamRef streamRef, eventFlags[i] & kFSEventStreamEventFlagItemFinderInfoMod || // eventFlags[i] & kFSEventStreamEventFlagItemRenamed || //OS X sends the same event flag for both old and new names!!! eventFlags[i] & kFSEventStreamEventFlagMustScanSubDirs) //something changed in one of the subdirs: NOT expected due to kFSEventStreamCreateFlagFileEvents - changedFiles.push_back(DirWatcher::Entry(DirWatcher::ACTION_UPDATE, paths[i])); + changedFiles.emplace_back(DirWatcher::ACTION_UPDATE, paths[i]); if (eventFlags[i] & kFSEventStreamEventFlagItemRemoved || eventFlags[i] & kFSEventStreamEventFlagRootChanged || //root is (indirectly) deleted or renamed eventFlags[i] & kFSEventStreamEventFlagUnmount) - changedFiles.push_back(DirWatcher::Entry(DirWatcher::ACTION_DELETE, paths[i])); + changedFiles.emplace_back(DirWatcher::ACTION_DELETE, paths[i]); //kFSEventStreamEventFlagEventIdsWrapped -> irrelevant! //kFSEventStreamEventFlagHistoryDone -> not expected due to kFSEventStreamEventIdSinceNow below @@ -571,7 +577,7 @@ struct DirWatcher::Pimpl DirWatcher::DirWatcher(const Zstring& directory) : - pimpl_(new Pimpl) + pimpl_(zen::make_unique<Pimpl>()) { CFStringRef dirpathCf = osx::createCFString(directory.c_str()); //returns nullptr on error if (!dirpathCf) diff --git a/zen/dst_hack.cpp b/zen/dst_hack.cpp deleted file mode 100644 index b38f73b4..00000000 --- a/zen/dst_hack.cpp +++ /dev/null @@ -1,368 +0,0 @@ -#include "dst_hack.h" -#include <bitset> -#include "basic_math.h" -#include "long_path_prefix.h" -#include "utf.h" -#include "assert_static.h" -#include "int64.h" -#include "file_error.h" -#include "dll.h" - -using namespace zen; - - -namespace -{ -//fast ::GetVolumePathName() clone: let's hope it's not too simple (doesn't honor mount points) -Zstring getVolumeName(const Zstring& filepath) -{ - //this call is expensive: ~1.5 ms! - // if (!::GetVolumePathName(filepath.c_str(), //__in LPCTSTR lpszFileName, - // fsName, //__out LPTSTR lpszVolumePathName, - // BUFFER_SIZE)) //__in DWORD cchBufferLength - // ... - // Zstring volumePath = appendSeparator(fsName); - - const Zstring nameFmt = appendSeparator(removeLongPathPrefix(filepath)); //throw() - - if (startsWith(nameFmt, Zstr("\\\\"))) //UNC path: "\\ComputerName\SharedFolder\" - { - size_t nameSize = nameFmt.size(); - const size_t posFirstSlash = nameFmt.find(Zstr("\\"), 2); - if (posFirstSlash != Zstring::npos) - { - nameSize = posFirstSlash + 1; - const size_t posSecondSlash = nameFmt.find(Zstr("\\"), posFirstSlash + 1); - if (posSecondSlash != Zstring::npos) - nameSize = posSecondSlash + 1; - } - return Zstring(nameFmt.c_str(), nameSize); //include trailing backslash! - } - else //local path: "C:\Folder\" - { - const size_t pos = nameFmt.find(Zstr(":\\")); - if (pos == 1) //expect single letter volume - return Zstring(nameFmt.c_str(), 3); - } - - return Zstring(); -} -} - - -bool dst::isFatDrive(const Zstring& filepath) //throw() -{ - const Zstring volumePath = getVolumeName(filepath); - if (volumePath.empty()) - return false; - - const DWORD bufferSize = MAX_PATH + 1; - wchar_t fsName[bufferSize] = {}; - - //suprisingly fast: ca. 0.03 ms per call! - if (!::GetVolumeInformation(appendSeparator(volumePath).c_str(), //__in_opt LPCTSTR lpRootPathName, - nullptr, //__out LPTSTR lpVolumeNameBuffer, - 0, //__in DWORD nVolumeNameSize, - nullptr, //__out_opt LPDWORD lpVolumeSerialNumber, - nullptr, //__out_opt LPDWORD lpMaximumComponentLength, - nullptr, //__out_opt LPDWORD lpFileSystemFlags, - fsName, //__out LPTSTR lpFileSystemNameBuffer, - bufferSize)) //__in DWORD nFileSystemNameSize - { - assert(false); //shouldn't happen - return false; - } - //DST hack seems to be working equally well for FAT and FAT32 (in particular creation time has 10^-2 s precision as advertised) - return fsName == Zstring(L"FAT") || - fsName == Zstring(L"FAT32"); -} - - -/* -bool dst::isFatDrive(HANDLE hFile) //throw() -{ -Requires Windows Vista! - //dynamically load windows API function - typedef BOOL (WINAPI* GetVolumeInformationByHandleWFunc)(HANDLE hFile, - LPWSTR lpVolumeNameBuffer, - DWORD nVolumeNameSize, - LPDWORD lpVolumeSerialNumber, - LPDWORD lpMaximumComponentLength, - LPDWORD lpFileSystemFlags, - LPWSTR lpFileSystemNameBuffer, - DWORD nFileSystemNameSize); - - const SysDllFun<GetVolumeInformationByHandleWFunc> getVolumeInformationByHandle(L"kernel32.dll", "GetVolumeInformationByHandleW"); - if (!getVolumeInformationByHandle) - { - assert(false); - return false; - } - - const size_t BUFFER_SIZE = MAX_PATH + 1; - wchar_t fsName[BUFFER_SIZE]; - - if (!getVolumeInformationByHandle(hFile, //__in HANDLE hFile, - nullptr, //__out LPTSTR lpVolumeNameBuffer, - 0, //__in DWORD nVolumeNameSize, - nullptr, //__out_opt LPDWORD lpVolumeSerialNumber, - nullptr, //__out_opt LPDWORD lpMaximumComponentLength, - nullptr, //__out_opt LPDWORD lpFileSystemFlags, - fsName, //__out LPTSTR lpFileSystemNameBuffer, - BUFFER_SIZE)) //__in DWORD nFileSystemNameSize - { - assert(false); //shouldn't happen - return false; - } - //DST hack seems to be working equally well for FAT and FAT32 (in particular creation time has 10^-2 s precision as advertised) - return fsName == Zstring(L"FAT") || - fsName == Zstring(L"FAT32"); -} -*/ - - -namespace -{ -//convert std::uint64_t and std::int64_t to FILETIME -inline -FILETIME toFiletime(std::uint64_t number) -{ - ULARGE_INTEGER cvt = {}; - cvt.QuadPart = number; - - const FILETIME output = { cvt.LowPart, cvt.HighPart }; - return output; -} - -inline -FILETIME toFiletime(std::int64_t number) -{ - return toFiletime(static_cast<std::uint64_t>(number)); -} - -inline -std::uint64_t toUInt64(const FILETIME& fileTime) -{ - return get64BitUInt(fileTime.dwLowDateTime, fileTime.dwHighDateTime); -} - - -inline -std::int64_t toInt64(const FILETIME& fileTime) -{ - return get64BitUInt(fileTime.dwLowDateTime, fileTime.dwHighDateTime); //convert unsigned to signed in return -} - - -inline -FILETIME utcToLocal(const FILETIME& utcTime) //throw std::runtime_error -{ - //treat binary local time representation (which is invariant under DST time zone shift) as logical UTC: - FILETIME localTime = {}; - if (!::FileTimeToLocalFileTime( - &utcTime, //__in const FILETIME *lpFileTime, - &localTime)) //__out LPFILETIME lpLocalFileTime - { - const DWORD lastError = ::GetLastError(); //copy before directly or indirectly making other system calls! - throw std::runtime_error(utfCvrtTo<std::string>(_("Conversion error:") + L" FILETIME -> local FILETIME: " + L"(" + - L"High: " + numberTo<std::wstring>(utcTime.dwHighDateTime) + L" " + - L"Low: " + numberTo<std::wstring>(utcTime.dwLowDateTime) + L") " + L"\n\n" + formatSystemError(L"FileTimeToLocalFileTime", lastError))); - } - return localTime; -} - - -inline -FILETIME localToUtc(const FILETIME& localTime) //throw std::runtime_error -{ - //treat binary local time representation (which is invariant under DST time zone shift) as logical UTC: - FILETIME utcTime = {}; - if (!::LocalFileTimeToFileTime( - &localTime, //__in const FILETIME *lpLocalFileTime, - &utcTime)) //__out LPFILETIME lpFileTime - { - const DWORD lastError = ::GetLastError(); //copy before directly or indirectly making other system calls! - throw std::runtime_error(utfCvrtTo<std::string>(_("Conversion error:") + L" local FILETIME -> FILETIME: " + L"(" + - L"High: " + numberTo<std::wstring>(localTime.dwHighDateTime) + L" " + - L"Low: " + numberTo<std::wstring>(localTime.dwLowDateTime) + L") " + L"\n\n" + formatSystemError(L"LocalFileTimeToFileTime", lastError))); - } - return utcTime; -} - - -//struct FILETIME {DWORD dwLowDateTime; DWORD dwHighDateTime;}; -const FILETIME FAT_MIN_TIME = { 13374976, 27846544 }; //1980 \ both are valid max/min FAT dates for 2 second precision -const FILETIME FAT_MAX_TIME = { 14487552, 37251238 }; //2107 / - -//http://en.wikipedia.org/wiki/File_Allocation_Table -const size_t PRECISION_WRITE_TIME = 20000000; //number of 100 ns per step -> 2 s -const size_t PRECISION_CREATE_TIME = 100000; // -> 1/100 s - -/* -Number of bits of information in create time: ln_2((FAT_MAX_TIME - FAT_MIN_TIME) / PRECISION_CREATE_TIME) = 38.55534023 -Number of bits of information in write time: 30.91148404 -*/ -//total size available to store data: -const size_t CREATE_TIME_INFO_BITS = 38; -// I. indicator that offset in II) is present -const size_t INDICATOR_EXISTING_BITS = 1; -// II. local<->UTC time offset -const size_t UTC_LOCAL_OFFSET_BITS = 7; -// III. indicator that offset in II) corresponds to current local write time (this could be a hash of the write time) -const size_t WRITE_TIME_HASH_BITS = CREATE_TIME_INFO_BITS - INDICATOR_EXISTING_BITS - UTC_LOCAL_OFFSET_BITS; - - -template <size_t precision> inline -FILETIME encodeRawInformation(std::uint64_t rawInfo) -{ - rawInfo *= precision; - rawInfo += toUInt64(FAT_MIN_TIME); - - assert(rawInfo <= toUInt64(FAT_MAX_TIME)); - return toFiletime(rawInfo); -} - - -template <size_t precision> inline -std::uint64_t extractRawInformation(const FILETIME& createTime) -{ - assert(toUInt64(FAT_MIN_TIME) <= toUInt64(createTime)); - assert(toUInt64(createTime) <= toUInt64(FAT_MAX_TIME)); - - //FAT create time ranges from 1980 - 2107 (2^7 years) with 1/100 seconds precision - std::uint64_t rawInfo = toUInt64(createTime); - - rawInfo -= toUInt64(FAT_MIN_TIME); - rawInfo /= precision; //reduce precision (FILETIME has unit 10^-7 s) - - assert(toUInt64(encodeRawInformation<precision>(rawInfo)) == toUInt64(createTime)); //must be reversible - return rawInfo; -} - - -//convert write time to it's minimal representation (no restriction to FAT range "1980 - 2107") -inline -std::uint64_t extractRawWriteTime(const FILETIME& writeTime) -{ - std::uint64_t rawInfo = toUInt64(writeTime); - assert(rawInfo % PRECISION_WRITE_TIME == 0U); - rawInfo /= PRECISION_WRITE_TIME; //reduce precision (FILETIME has unit 10^-7 s) - return rawInfo; -} - - -//files with different resolution than 2 seconds are rounded up when written to FAT -inline -FILETIME roundToFatWriteTime(const FILETIME& writeTime) -{ - std::uint64_t rawData = toUInt64(writeTime); - - if (rawData % PRECISION_WRITE_TIME != 0U) - rawData += PRECISION_WRITE_TIME; - - rawData /= PRECISION_WRITE_TIME; - rawData *= PRECISION_WRITE_TIME; - return toFiletime(rawData); -} - - -//get 7-bit value representing time shift in number of quarter-hours -std::bitset<UTC_LOCAL_OFFSET_BITS> getUtcLocalShift() -{ - FILETIME utcTime = FAT_MIN_TIME; - utcTime.dwHighDateTime += 5000000; //some arbitrary valid time - - const FILETIME localTime = utcToLocal(utcTime); - - const int timeShiftSec = static_cast<int>((toInt64(localTime) - toInt64(utcTime)) / 10000000); //time shift in seconds - - const int timeShiftQuarter = timeShiftSec / (60 * 15); //time shift in quarter-hours - - const int absValue = numeric::abs(timeShiftQuarter); //MSVC C++0x bug: std::bitset<>(unsigned long) is ambiguous - - if (std::bitset < UTC_LOCAL_OFFSET_BITS - 1 > (absValue).to_ulong() != static_cast<unsigned long>(absValue) || //time shifts that big shouldn't be possible! - timeShiftSec % (60 * 15) != 0) //all known time shift have at least 15 minute granularity! - { - const std::wstring errorMsg = _("Conversion error:") + L" Unexpected UTC <-> local time shift: " + L"(" + numberTo<std::wstring>(timeShiftSec) + L")"; - throw std::runtime_error(utfCvrtTo<std::string>(errorMsg)); - } - - std::bitset<UTC_LOCAL_OFFSET_BITS> output(absValue); - output[UTC_LOCAL_OFFSET_BITS - 1] = timeShiftQuarter < 0; //sign bit - return output; -} - - -//get time-zone shift in seconds -inline -int convertUtcLocalShift(std::bitset<UTC_LOCAL_OFFSET_BITS> rawShift) -{ - const bool hasSign = rawShift[UTC_LOCAL_OFFSET_BITS - 1]; - rawShift[UTC_LOCAL_OFFSET_BITS - 1] = false; - - assert_static(UTC_LOCAL_OFFSET_BITS <= sizeof(unsigned long) * 8); - return hasSign ? - static_cast<int>(rawShift.to_ulong()) * 15 * 60 * -1 : - static_cast<int>(rawShift.to_ulong()) * 15 * 60; -} -} - - -bool dst::fatHasUtcEncoded(const RawTime& rawTime) //"createTimeRaw" as retrieved by ::FindFirstFile() and ::GetFileAttributesEx(); throw std::runtime_error -{ - if (toUInt64(rawTime.createTimeRaw) < toUInt64(FAT_MIN_TIME) || - toUInt64(FAT_MAX_TIME) < toUInt64(rawTime.createTimeRaw)) - { - assert(false); //shouldn't be possible according to FAT specification - return false; - } - - const std::uint64_t rawInfo = extractRawInformation<PRECISION_CREATE_TIME>(utcToLocal(rawTime.createTimeRaw)); - - assert_static(WRITE_TIME_HASH_BITS == 30); - return (extractRawWriteTime(utcToLocal(rawTime.writeTimeRaw)) & 0x3FFFFFFFU) == (rawInfo & 0x3FFFFFFFU) && //ensure write time wasn't changed externally - rawInfo >> (CREATE_TIME_INFO_BITS - INDICATOR_EXISTING_BITS) == 1U; //extended data available -} - - -dst::RawTime dst::fatEncodeUtcTime(const FILETIME& writeTimeRealUtc) //throw std::runtime_error -{ - const FILETIME fatWriteTimeUtc = roundToFatWriteTime(writeTimeRealUtc); //writeTimeRealUtc may have incompatible precision (NTFS) - - //create time lets us store 40 bit of information - - //indicator that utc time is encoded -> hopefully results in a date long way in the future; but even if this bit is accidentally set, we still have the hash! - std::uint64_t data = 1U; - - const std::bitset<UTC_LOCAL_OFFSET_BITS> utcShift = getUtcLocalShift(); - data <<= UTC_LOCAL_OFFSET_BITS; - data |= utcShift.to_ulong(); - - data <<= WRITE_TIME_HASH_BITS; - data |= extractRawWriteTime(utcToLocal(fatWriteTimeUtc)) & 0x3FFFFFFFU; //trim to last 30 bit of information - assert_static(WRITE_TIME_HASH_BITS == 30); - - const FILETIME encodedData = localToUtc(encodeRawInformation<PRECISION_CREATE_TIME>(data)); //localToUtc: make sure data is physically saved as FAT local time - assert(toUInt64(FAT_MIN_TIME) <= toUInt64(encodedData)); - assert(toUInt64(encodedData) <= toUInt64(FAT_MAX_TIME)); - - return RawTime(encodedData, fatWriteTimeUtc); //keep compatible with other applications, at least until DST shift actually occurs -} - - -FILETIME dst::fatDecodeUtcTime(const RawTime& rawTime) //return real UTC time; throw (std::runtime_error) -{ - if (!fatHasUtcEncoded(rawTime)) - return rawTime.writeTimeRaw; - - const std::uint64_t rawInfo = extractRawInformation<PRECISION_CREATE_TIME>(utcToLocal(rawTime.createTimeRaw)); - - const std::bitset<UTC_LOCAL_OFFSET_BITS> rawShift(static_cast<int>((rawInfo >> WRITE_TIME_HASH_BITS) & 0x7FU)); //static_cast<int>: a shame MSC... "unsigned long long" should be supported instead! - assert_static(UTC_LOCAL_OFFSET_BITS == 7); - - const std::int64_t timeShiftSec = convertUtcLocalShift(rawShift); - const FILETIME writeTimeLocal = utcToLocal(rawTime.writeTimeRaw); - - const std::int64_t realUTC = toInt64(writeTimeLocal) - timeShiftSec * 10000000; - return toFiletime(realUTC); -} diff --git a/zen/dst_hack.h b/zen/dst_hack.h deleted file mode 100644 index 600107bb..00000000 --- a/zen/dst_hack.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef DST_HACK_H_INCLUDED -#define DST_HACK_H_INCLUDED - -#include "win.h" //includes "windows.h" -#include "zstring.h" -#include <stdexcept> - - -namespace dst -{ -/* -Solve DST +-1h and time zone shift issues on FAT drives -------------------------------------------------------- -- (local) last write time is not touched! -- all additional metadata is encoded in local create time: - I. indicator that offset in II) is present - II. local<->UTC time offset - III. indicator that offset in II) corresponds to current local write time (a hash of local last write time) -*/ - -bool isFatDrive(const Zstring& fileName); //throw () - -//all subsequent functions may throw the std::runtime_error exception! - -struct RawTime //time as retrieved by ::FindFirstFile() and ::GetFileAttributesEx() -{ - RawTime(const FILETIME& create, const FILETIME& lastWrite) : createTimeRaw(create), writeTimeRaw(lastWrite) {} - FILETIME createTimeRaw; - FILETIME writeTimeRaw; -}; -//save UTC time resistant against DST/time zone shifts -bool fatHasUtcEncoded(const RawTime& rawTime); //throw std::runtime_error; as retrieved by ::FindFirstFile() and ::GetFileAttributesEx() - -RawTime fatEncodeUtcTime(const FILETIME& writeTimeRealUtc); //throw std::runtime_error -FILETIME fatDecodeUtcTime(const RawTime& rawTime); //throw std::runtime_error; return last write time in real UTC -} - -#endif // DST_HACK_H_INCLUDED diff --git a/zen/file_handling.cpp b/zen/file_access.cpp index 75062462..c4768dd2 100644 --- a/zen/file_handling.cpp +++ b/zen/file_access.cpp @@ -4,7 +4,7 @@ // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** -#include "file_handling.h" +#include "file_access.h" #include <map> #include <algorithm> #include <stdexcept> @@ -13,7 +13,6 @@ #include "scope_guard.h" #include "symlink_target.h" #include "file_io.h" -#include "assert_static.h" #include "file_id_def.h" #ifdef ZEN_WIN @@ -21,7 +20,6 @@ #include "privilege.h" #include "dll.h" #include "long_path_prefix.h" -#include "dst_hack.h" #include "win_ver.h" #include "IFileOperation/file_op.h" @@ -134,6 +132,70 @@ bool zen::somethingExists(const Zstring& objname) namespace { #ifdef ZEN_WIN +//fast ::GetVolumePathName() clone: let's hope it's not too simple (doesn't honor mount points) +Zstring getVolumeNameFast(const Zstring& filepath) +{ + //this call is expensive: ~1.5 ms! + // if (!::GetVolumePathName(filepath.c_str(), //__in LPCTSTR lpszFileName, + // fsName, //__out LPTSTR lpszVolumePathName, + // BUFFER_SIZE)) //__in DWORD cchBufferLength + // ... + // Zstring volumePath = appendSeparator(fsName); + + const Zstring nameFmt = appendSeparator(removeLongPathPrefix(filepath)); //throw() + + if (startsWith(nameFmt, Zstr("\\\\"))) //UNC path: "\\ComputerName\SharedFolder\" + { + size_t nameSize = nameFmt.size(); + const size_t posFirstSlash = nameFmt.find(Zstr("\\"), 2); + if (posFirstSlash != Zstring::npos) + { + nameSize = posFirstSlash + 1; + const size_t posSecondSlash = nameFmt.find(Zstr("\\"), posFirstSlash + 1); + if (posSecondSlash != Zstring::npos) + nameSize = posSecondSlash + 1; + } + return Zstring(nameFmt.c_str(), nameSize); //include trailing backslash! + } + else //local path: "C:\Folder\" + { + const size_t pos = nameFmt.find(Zstr(":\\")); + if (pos == 1) //expect single letter volume + return Zstring(nameFmt.c_str(), 3); + } + + return Zstring(); +} + + +bool isFatDrive(const Zstring& filepath) //throw() +{ + const Zstring volumePath = getVolumeNameFast(filepath); + if (volumePath.empty()) + return false; + + const DWORD bufferSize = MAX_PATH + 1; + wchar_t fsName[bufferSize] = {}; + + //suprisingly fast: ca. 0.03 ms per call! + if (!::GetVolumeInformation(appendSeparator(volumePath).c_str(), //__in_opt LPCTSTR lpRootPathName, + nullptr, //__out LPTSTR lpVolumeNameBuffer, + 0, //__in DWORD nVolumeNameSize, + nullptr, //__out_opt LPDWORD lpVolumeSerialNumber, + nullptr, //__out_opt LPDWORD lpMaximumComponentLength, + nullptr, //__out_opt LPDWORD lpFileSystemFlags, + fsName, //__out LPTSTR lpFileSystemNameBuffer, + bufferSize)) //__in DWORD nFileSystemNameSize + { + assert(false); //shouldn't happen + return false; + } + //DST hack seems to be working equally well for FAT and FAT32 (in particular creation time has 10^-2 s precision as advertised) + return fsName == Zstring(L"FAT") || + fsName == Zstring(L"FAT32"); +} + + //(try to) enhance error messages by showing which processes lock the file Zstring getLockingProcessNames(const Zstring& filepath) //throw(), empty string if none found or error occurred { @@ -159,40 +221,38 @@ Zstring getLockingProcessNames(const Zstring& filepath) //throw(), empty string std::uint64_t zen::getFilesize(const Zstring& filepath) //throw FileError { #ifdef ZEN_WIN - WIN32_FIND_DATA fileInfo = {}; { + WIN32_FIND_DATA fileInfo = {}; const HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(filepath).c_str(), &fileInfo); if (searchHandle == INVALID_HANDLE_VALUE) throwFileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtFileName(filepath)), L"FindFirstFile", getLastError()); ::FindClose(searchHandle); + + if (!isSymlink(fileInfo)) + return get64BitUInt(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh); } // WIN32_FILE_ATTRIBUTE_DATA sourceAttr = {}; - // if (!::GetFileAttributesEx(applyLongPathPrefix(sourceObj).c_str(), //__in LPCTSTR lpFileName, - // GetFileExInfoStandard, //__in GET_FILEEX_INFO_LEVELS fInfoLevelId, - // &sourceAttr)) //__out LPVOID lpFileInformation - - if (!isSymlink(fileInfo)) - return get64BitUInt(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh); - else - { - //open handle to target of symbolic link - const HANDLE hFile = ::CreateFile(applyLongPathPrefix(filepath).c_str(), //_In_ LPCTSTR lpFileName, - 0, //_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, - FILE_FLAG_BACKUP_SEMANTICS, /*needed to open a directory*/ //_In_ DWORD dwFlagsAndAttributes, - nullptr); //_In_opt_ HANDLE hTemplateFile - if (hFile == INVALID_HANDLE_VALUE) - throwFileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtFileName(filepath)), L"CreateFile", getLastError()); - ZEN_ON_SCOPE_EXIT(::CloseHandle(hFile)); + // if (!::GetFileAttributesEx(applyLongPathPrefix(filepath).c_str(), //__in LPCTSTR lpFileName, + // GetFileExInfoStandard, //__in GET_FILEEX_INFO_LEVELS fInfoLevelId, + // &sourceAttr)) //__out LPVOID lpFileInformation + + //open handle to target of symbolic link + const HANDLE hFile = ::CreateFile(applyLongPathPrefix(filepath).c_str(), //_In_ LPCTSTR lpFileName, + 0, //_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, + FILE_FLAG_BACKUP_SEMANTICS, /*needed to open a directory*/ //_In_ DWORD dwFlagsAndAttributes, + nullptr); //_In_opt_ HANDLE hTemplateFile + if (hFile == INVALID_HANDLE_VALUE) + throwFileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtFileName(filepath)), L"CreateFile", getLastError()); + ZEN_ON_SCOPE_EXIT(::CloseHandle(hFile)); - BY_HANDLE_FILE_INFORMATION fileInfoHnd = {}; - if (!::GetFileInformationByHandle(hFile, &fileInfoHnd)) - throwFileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtFileName(filepath)), L"GetFileInformationByHandle", getLastError()); + BY_HANDLE_FILE_INFORMATION fileInfoHnd = {}; + if (!::GetFileInformationByHandle(hFile, &fileInfoHnd)) + throwFileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtFileName(filepath)), L"GetFileInformationByHandle", getLastError()); - return get64BitUInt(fileInfoHnd.nFileSizeLow, fileInfoHnd.nFileSizeHigh); - } + return get64BitUInt(fileInfoHnd.nFileSizeLow, fileInfoHnd.nFileSizeHigh); #elif defined ZEN_LINUX || defined ZEN_MAC struct ::stat fileInfo = {}; @@ -494,11 +554,11 @@ public: files_(files), dirs_(dirs) {} - virtual void onFile(const Zchar* shortName, const Zstring& filepath, const FileInfo& details) + void onFile(const Zchar* shortName, const Zstring& filepath, const FileInfo& details) override { files_.push_back(filepath); } - virtual HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) + HandleLink onSymlink(const Zchar* shortName, const Zstring& linkpath, const SymlinkInfo& details) override { if (dirExists(linkpath)) //dir symlink dirs_.push_back(shortName); @@ -506,13 +566,13 @@ public: files_.push_back(shortName); return LINK_SKIP; } - virtual TraverseCallback* onDir(const Zchar* shortName, const Zstring& dirpath) + TraverseCallback* onDir(const Zchar* shortName, const Zstring& dirpath) override { dirs_.push_back(dirpath); return nullptr; //DON'T traverse into subdirs; removeDirectory works recursively! } - virtual HandleError reportDirError (const std::wstring& msg, size_t retryNumber) { throw FileError(msg); } - virtual HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) { throw FileError(msg); } + HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override { throw FileError(msg); } + HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) override { throw FileError(msg); } private: CollectFilesFlat (const CollectFilesFlat&) = delete; @@ -525,7 +585,7 @@ private: void removeDirectoryImpl(const Zstring& directory, //throw FileError const std::function<void (const Zstring& filepath)>& onBeforeFileDeletion, - const std::function<void (const Zstring& dirpath)>& onBeforeDirDeletion) + const std::function<void (const Zstring& dirpath )>& onBeforeDirDeletion) { assert(somethingExists(directory)); //[!] @@ -592,7 +652,10 @@ void removeDirectoryImpl(const Zstring& directory, //throw FileError #ifdef ZEN_WIN -void setFileTimeRaw(const Zstring& filepath, const FILETIME& creationTime, const FILETIME& lastWriteTime, ProcSymlink procSl) //throw FileError +void setFileTimeRaw(const Zstring& filepath, + const FILETIME* creationTime, //optional + const FILETIME& lastWriteTime, + ProcSymlink procSl) //throw FileError { { //extra scope for debug check below @@ -696,7 +759,7 @@ void setFileTimeRaw(const Zstring& filepath, const FILETIME& creationTime, const auto isNullTime = [](const FILETIME& ft) { return ft.dwLowDateTime == 0 && ft.dwHighDateTime == 0; }; if (!::SetFileTime(hFile, //__in HANDLE hFile, - !isNullTime(creationTime) ? &creationTime : nullptr, //__in_opt const FILETIME *lpCreationTime, + creationTime, //__in_opt const FILETIME *lpCreationTime, nullptr, //__in_opt const FILETIME *lpLastAccessTime, &lastWriteTime)) //__in_opt const FILETIME *lpLastWriteTime { @@ -736,8 +799,8 @@ void setFileTimeRaw(const Zstring& filepath, const FILETIME& creationTime, const 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 (!isNullTime(creationTime)) - basicInfo.CreationTime = toLargeInteger(creationTime); + if (creationTime) + basicInfo.CreationTime = toLargeInteger(*creationTime); //set file time + attributes setFileInfo(basicInfo); //throw FileError @@ -759,7 +822,7 @@ void setFileTimeRaw(const Zstring& filepath, const FILETIME& creationTime, const //add more meaningful message: FAT accepts only a subset of the NTFS date range if (lastError == ERROR_INVALID_PARAMETER && - dst::isFatDrive(filepath)) + isFatDrive(filepath)) { //we need a low-level reliable routine to format a potentially invalid date => don't use strftime!!! auto fmtDate = [](const FILETIME& ft) -> Zstring @@ -800,7 +863,7 @@ void setFileTimeRaw(const Zstring& filepath, const FILETIME& creationTime, const errorMsg += std::wstring(L"\nA FAT volume can only store dates between 1980 and 2107:\n") + L"\twrite (UTC): \t" + fmtDate(lastWriteTime) + - (!isNullTime(creationTime) ? L"\n\tcreate (UTC): \t" + fmtDate(creationTime) : L""); + (creationTime ? L"\n\tcreate (UTC): \t" + fmtDate(*creationTime) : L""); } if (lastError != ERROR_SUCCESS) @@ -827,8 +890,8 @@ void setFileTimeRaw(const Zstring& filepath, const FILETIME& creationTime, const nullptr, &lastWriteTimeDbg)); - assert(std::abs(filetimeToTimeT(lastWriteTimeDbg) - filetimeToTimeT(lastWriteTime)) <= 2); //respect 2 second FAT/FAT32 precision - //assert(std::abs(filetimeToTimeT(creationTimeDbg ) - filetimeToTimeT(creationTime )) <= 2); -> creation time not available for Linux-hosted Samba shares! + assert(std::abs(filetimeToTimeT(lastWriteTimeDbg) - filetimeToTimeT(lastWriteTime)) <= 2); //respect 2 second FAT/FAT32 precision + //assert(std::abs(filetimeToTimeT(creationTimeDbg ) - filetimeToTimeT(creationTime )) <= 2); -> creation time not available for Linux-hosted Samba shares! #endif } #endif @@ -849,22 +912,7 @@ void zen::removeDirectory(const Zstring& directory, //throw FileError void zen::setFileTime(const Zstring& filepath, std::int64_t modTime, ProcSymlink procSl) //throw FileError { #ifdef ZEN_WIN - FILETIME creationTime = {}; - FILETIME lastWriteTime = timetToFileTime(modTime); - - //####################################### DST hack ########################################### - warn_static("let's tentatively disable the DST hack:") -#if 0 - if (dst::isFatDrive(filepath)) //throw(); hacky: does not consider symlinks pointing to FAT! - { - const dst::RawTime encodedTime = dst::fatEncodeUtcTime(lastWriteTime); //throw std::runtime_error - creationTime = encodedTime.createTimeRaw; - lastWriteTime = encodedTime.writeTimeRaw; - } -#endif - //####################################### DST hack ########################################### - - setFileTimeRaw(filepath, creationTime, lastWriteTime, procSl); //throw FileError + setFileTimeRaw(filepath, nullptr, timetToFileTime(modTime), procSl); //throw FileError #elif defined ZEN_LINUX || defined ZEN_MAC //sigh, we can't use utimensat on NTFS volumes on Ubuntu: silent failure!!! what morons are programming this shit??? @@ -878,7 +926,7 @@ void zen::setFileTime(const Zstring& filepath, std::int64_t modTime, ProcSymlink //=> fallback to "retarded-idiot version"! -- DarkByte - //OS X: utime() is obsoleted by utimes()! utimensat() not yet implemented + //OS X: utime() is obsoleted by utimes()! utimensat() not yet implemented struct ::timeval newTimes[2] = {}; newTimes[0].tv_sec = ::time(nullptr); //access time (seconds) @@ -1300,7 +1348,7 @@ void zen::makeDirectoryPlain(const Zstring& directory, //throw FileError, ErrorT if (!templateDir.empty()) { #ifdef ZEN_WIN - //try to copy file attributes (dereference symlinks and junctions) + //optional: try to copy file attributes (dereference symlinks and junctions) const HANDLE hDirSrc = ::CreateFile(zen::applyLongPathPrefix(templateDir).c_str(), //_In_ LPCTSTR lpFileName, 0, //_In_ DWORD dwDesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //_In_ DWORD dwShareMode, @@ -1343,14 +1391,14 @@ void zen::makeDirectoryPlain(const Zstring& directory, //throw FileError, ErrorT { USHORT cmpState = COMPRESSION_FORMAT_DEFAULT; DWORD bytesReturned = 0; - /*bool rv = */::DeviceIoControl(hDirTrg, //handle to file or directory - FSCTL_SET_COMPRESSION, //dwIoControlCode - &cmpState, //input buffer - sizeof(cmpState), //size of input buffer - nullptr, //lpOutBuffer - 0, //OutBufferSize - &bytesReturned, //number of bytes returned - nullptr); //OVERLAPPED structure + /*bool rv = */::DeviceIoControl(hDirTrg, //_In_ HANDLE hDevice, + FSCTL_SET_COMPRESSION, //_In_ DWORD dwIoControlCode, + &cmpState, //_In_opt_ LPVOID lpInBuffer, + sizeof(cmpState), //_In_ DWORD nInBufferSize, + nullptr, //_Out_opt_ LPVOID lpOutBuffer, + 0, //_In_ DWORD nOutBufferSize, + &bytesReturned, //_Out_opt_ LPDWORD lpBytesReturned, + nullptr); //_Inout_opt_ LPOVERLAPPED lpOverlapped } //(try to) set creation and modification time @@ -1385,12 +1433,12 @@ void zen::copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool return ret != INVALID_FILE_ATTRIBUTES && (ret & FILE_ATTRIBUTE_DIRECTORY); }(); - //dynamically load windows API function typedef BOOLEAN (WINAPI* CreateSymbolicLinkFunc)(LPCTSTR lpSymlinkFileName, LPCTSTR lpTargetFileName, DWORD dwFlags); const SysDllFun<CreateSymbolicLinkFunc> createSymbolicLink(L"kernel32.dll", "CreateSymbolicLinkW"); if (!createSymbolicLink) - throw FileError(replaceCpy(_("Cannot create symbolic link %x."), L"%x", fmtFileName(targetLink)), replaceCpy(_("Cannot find system function %x."), L"%x", L"\"CreateSymbolicLinkW\"")); + throw FileError(replaceCpy(replaceCpy(_("Cannot copy symbolic link %x to %y."), L"%x", L"\n" + fmtFileName(sourceLink)), L"%y", L"\n" + fmtFileName(targetLink)), + replaceCpy(_("Cannot find system function %x."), L"%x", L"\"CreateSymbolicLinkW\"")); const wchar_t functionName[] = L"CreateSymbolicLinkW"; if (!createSymbolicLink(targetLink.c_str(), //__in LPTSTR lpSymlinkFileName, - seems no long path prefix is required... @@ -1400,9 +1448,9 @@ void zen::copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool const wchar_t functionName[] = L"symlink"; if (::symlink(linkPath.c_str(), targetLink.c_str()) != 0) #endif - throwFileError(replaceCpy(_("Cannot create symbolic link %x."), L"%x", fmtFileName(targetLink)), functionName, getLastError()); + throwFileError(replaceCpy(replaceCpy(_("Cannot copy symbolic link %x to %y."), L"%x", L"\n" + fmtFileName(sourceLink)), L"%y", L"\n" + fmtFileName(targetLink)), functionName, getLastError()); - //allow only consistent objects to be created -> don't place before ::symlink, targetLink may already exist + //allow only consistent objects to be created -> don't place before ::symlink, targetLink may already exist! zen::ScopeGuard guardNewLink = zen::makeGuard([&] { try @@ -1425,7 +1473,7 @@ void zen::copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool &sourceAttr)) //__out LPVOID lpFileInformation throwFileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtFileName(sourceLink)), L"GetFileAttributesEx", getLastError()); - setFileTimeRaw(targetLink, sourceAttr.ftCreationTime, sourceAttr.ftLastWriteTime, ProcSymlink::DIRECT); //throw FileError + setFileTimeRaw(targetLink, &sourceAttr.ftCreationTime, sourceAttr.ftLastWriteTime, ProcSymlink::DIRECT); //throw FileError #elif defined ZEN_LINUX || defined ZEN_MAC struct ::stat srcInfo = {}; @@ -1547,7 +1595,7 @@ bool canCopyAsSparse(const Zstring& sourceFile, const Zstring& targetFile) //thr void copyFileWindowsSparse(const Zstring& sourceFile, const Zstring& targetFile, const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus, - InSyncAttributes* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked + InSyncAttributes* newAttrib) //throw FileError, ErrorTargetExisting, ErrorFileLocked { assert(canCopyAsSparse(sourceFile, targetFile)); @@ -1626,8 +1674,7 @@ void copyFileWindowsSparse(const Zstring& sourceFile, lastError == ERROR_ALREADY_EXISTS) //comment on msdn claims, this one is used on Windows Mobile 6 throw ErrorTargetExisting(errorMsg, errorDescr); - if (lastError == ERROR_PATH_NOT_FOUND) - throw ErrorTargetPathMissing(errorMsg, errorDescr); + //if (lastError == ERROR_PATH_NOT_FOUND) throw ErrorTargetPathMissing(errorMsg, errorDescr); throw FileError(errorMsg, errorDescr); } @@ -1655,14 +1702,14 @@ void copyFileWindowsSparse(const Zstring& sourceFile, { USHORT cmpState = COMPRESSION_FORMAT_DEFAULT; DWORD bytesReturned = 0; - if (!::DeviceIoControl(hFileTarget, //handle to file or directory - FSCTL_SET_COMPRESSION, //dwIoControlCode - &cmpState, //input buffer - sizeof(cmpState), //size of input buffer - nullptr, //lpOutBuffer - 0, //OutBufferSize - &bytesReturned, //number of bytes returned - nullptr)) //OVERLAPPED structure + if (!::DeviceIoControl(hFileTarget, //_In_ HANDLE hDevice, + FSCTL_SET_COMPRESSION, //_In_ DWORD dwIoControlCode, + &cmpState, //_In_opt_ LPVOID lpInBuffer, + sizeof(cmpState), //_In_ DWORD nInBufferSize, + nullptr, //_Out_opt_ LPVOID lpOutBuffer, + 0, //_In_ DWORD nOutBufferSize, + &bytesReturned, //_Out_opt_ LPDWORD lpBytesReturned, + nullptr)) //_Inout_opt_ LPOVERLAPPED lpOverlapped {} //may legitimately fail with ERROR_INVALID_FUNCTION if: // - target folder is encrypted // - target volume does not support compressed attribute -> unlikely in this context @@ -1678,14 +1725,14 @@ void copyFileWindowsSparse(const Zstring& sourceFile, //if (sourceIsSparse && targetSupportsSparse) -> no need to check, this is our precondition! { DWORD bytesReturned = 0; - if (!::DeviceIoControl(hFileTarget, //handle to file - FSCTL_SET_SPARSE, //dwIoControlCode - nullptr, //input buffer - 0, //size of input buffer - nullptr, //lpOutBuffer - 0, //OutBufferSize - &bytesReturned, //number of bytes returned - nullptr)) //OVERLAPPED structure + if (!::DeviceIoControl(hFileTarget, //_In_ HANDLE hDevice, + FSCTL_SET_SPARSE, //_In_ DWORD dwIoControlCode, + nullptr, //_In_opt_ LPVOID lpInBuffer, + 0, //_In_ DWORD nInBufferSize, + nullptr, //_Out_opt_ LPVOID lpOutBuffer, + 0, //_In_ DWORD nOutBufferSize, + &bytesReturned, //_Out_opt_ LPDWORD lpBytesReturned, + nullptr)) //_Inout_opt_ LPOVERLAPPED lpOverlapped throwFileError(replaceCpy(_("Cannot write file attributes of %x."), L"%x", fmtFileName(targetFile)), L"DeviceIoControl, FSCTL_SET_SPARSE", getLastError()); } @@ -1805,7 +1852,7 @@ public: //call context: copyCallbackInternal() void reportErrorShouldCopyAsSparse() { shouldCopyAsSparse = true; } - void reportUserException(const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus) { exceptionInUserCallback = onUpdateCopyStatus; } + void reportUserException(const std::exception_ptr& e) { exception = e; } void reportError(const std::wstring& msg, const std::wstring& description) { errorMsg = std::make_pair(msg, description); } @@ -1815,11 +1862,8 @@ public: if (shouldCopyAsSparse) throw ErrorShouldCopyAsSparse(L"sparse dummy value"); - if (exceptionInUserCallback) - { - exceptionInUserCallback(0); //should throw again!!! - assert(false); // - } + if (exception) + std::rethrow_exception(exception); if (!errorMsg.first.empty()) throw FileError(errorMsg.first, errorMsg.second); @@ -1828,7 +1872,7 @@ public: private: bool shouldCopyAsSparse; // std::pair<std::wstring, std::wstring> errorMsg; //these are exclusive! - std::function<void(std::int64_t bytesDelta)> exceptionInUserCallback; // -> optional + std::exception_ptr exception; }; @@ -1924,15 +1968,16 @@ DWORD CALLBACK copyCallbackInternal(LARGE_INTEGER totalFileSize, { USHORT cmpState = COMPRESSION_FORMAT_DEFAULT; DWORD bytesReturned = 0; - if (!::DeviceIoControl(hDestinationFile, //handle to file or directory - FSCTL_SET_COMPRESSION, //dwIoControlCode - &cmpState, //input buffer - sizeof(cmpState), //size of input buffer - nullptr, //lpOutBuffer - 0, //OutBufferSize - &bytesReturned, //number of bytes returned - nullptr)) //OVERLAPPED structure + if (!::DeviceIoControl(hDestinationFile, //_In_ HANDLE hDevice, + FSCTL_SET_COMPRESSION, //_In_ DWORD dwIoControlCode, + &cmpState, //_In_opt_ LPVOID lpInBuffer, + sizeof(cmpState), //_In_ DWORD nInBufferSize, + nullptr, //_Out_opt_ LPVOID lpOutBuffer, + 0, //_In_ DWORD nOutBufferSize, + &bytesReturned, //_Out_opt_ LPDWORD lpBytesReturned + nullptr)) //_Inout_opt_ LPOVERLAPPED lpOverlapped {} //may legitimately fail with ERROR_INVALID_FUNCTION if + // - if target folder is encrypted // - target volume does not support compressed attribute //############################################################################# @@ -1949,9 +1994,7 @@ DWORD CALLBACK copyCallbackInternal(LARGE_INTEGER totalFileSize, } catch (...) { - //#warning migrate to std::exception_ptr when available - - cbd.errorHandler.reportUserException(cbd.onUpdateCopyStatus_); + cbd.errorHandler.reportUserException(std::current_exception()); return PROGRESS_CANCEL; } return PROGRESS_CONTINUE; @@ -1965,7 +2008,7 @@ const bool supportNonEncryptedDestination = winXpOrLater(); //encrypted destinat void copyFileWindowsDefault(const Zstring& sourceFile, const Zstring& targetFile, const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus, - InSyncAttributes* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked, ErrorShouldCopyAsSparse + InSyncAttributes* newAttrib) //throw FileError, ErrorTargetExisting, ErrorFileLocked, ErrorShouldCopyAsSparse { //try to get backup read and write privileges: who knows, maybe this helps solve some obscure "access denied" errors try { activatePrivilege(SE_BACKUP_NAME); } @@ -1979,7 +2022,7 @@ void copyFileWindowsDefault(const Zstring& sourceFile, DWORD copyFlags = COPY_FILE_FAIL_IF_EXISTS; if (supportNonEncryptedDestination) - copyFlags |= COPY_FILE_ALLOW_DECRYPTED_DESTINATION; //allow copying from encrypted to non-encrytped location + copyFlags |= COPY_FILE_ALLOW_DECRYPTED_DESTINATION; //allow copying from encrypted to non-encrypted location //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, huge improvement for large files (20% in test NTFS -> NTFS) @@ -1989,13 +2032,12 @@ void copyFileWindowsDefault(const Zstring& sourceFile, CallbackData cbd(onUpdateCopyStatus, sourceFile, targetFile); - const bool success = ::CopyFileEx( //same performance like CopyFile() - applyLongPathPrefix(sourceFile).c_str(), //__in LPCTSTR lpExistingFileName, - applyLongPathPrefix(targetFile).c_str(), //__in LPCTSTR lpNewFileName, - copyCallbackInternal, //__in_opt LPPROGRESS_ROUTINE lpProgressRoutine, - &cbd, //__in_opt LPVOID lpData, - nullptr, //__in_opt LPBOOL pbCancel, - copyFlags) != FALSE; //__in DWORD dwCopyFlags + const bool success = ::CopyFileEx(applyLongPathPrefix(sourceFile).c_str(), //__in LPCTSTR lpExistingFileName, + applyLongPathPrefix(targetFile).c_str(), //__in LPCTSTR lpNewFileName, + copyCallbackInternal, //__in_opt LPPROGRESS_ROUTINE lpProgressRoutine, + &cbd, //__in_opt LPVOID lpData, + nullptr, //__in_opt LPBOOL pbCancel, + copyFlags) != FALSE; //__in DWORD dwCopyFlags cbd.errorHandler.evaluateErrors(); //throw ?, process errors in callback first! if (!success) @@ -2005,7 +2047,7 @@ void copyFileWindowsDefault(const Zstring& sourceFile, //don't suppress "lastError == ERROR_REQUEST_ABORTED": a user aborted operation IS an error condition! //trying to copy huge sparse files may directly fail with ERROR_DISK_FULL before entering the callback function - if (canCopyAsSparse(sourceFile, targetFile)) //throw () + if (canCopyAsSparse(sourceFile, targetFile)) //noexcept throw ErrorShouldCopyAsSparse(L"sparse dummy value2"); //assemble error message... @@ -2030,20 +2072,16 @@ void copyFileWindowsDefault(const Zstring& sourceFile, throw ErrorTargetExisting(errorMsg, errorDescr); } - if (lastError == ERROR_PATH_NOT_FOUND) - { - guardTarget.dismiss(); //not relevant - throw ErrorTargetPathMissing(errorMsg, errorDescr); //could this also be source path missing!? - } + //if (lastError == ERROR_PATH_NOT_FOUND) throw ErrorTargetPathMissing(errorMsg, errorDescr); //could this also be source path missing!? try //add more meaningful message { //trying to copy > 4GB file to FAT/FAT32 volume gives obscure ERROR_INVALID_PARAMETER (FAT can indeed handle files up to 4 Gig, tested!) if (lastError == ERROR_INVALID_PARAMETER && - dst::isFatDrive(targetFile) && + isFatDrive(targetFile) && getFilesize(sourceFile) >= 4U * std::uint64_t(1024U * 1024 * 1024)) //throw FileError errorDescr += L"\nFAT volumes cannot store files larger than 4 gigabyte."; - //see "Limitations of the FAT32 File System": http://support.microsoft.com/kb/314463/en-us + //see "Limitations of the FAT32 File System": http://support.microsoft.com/kb/314463/en-us //note: ERROR_INVALID_PARAMETER can also occur when copying to a SharePoint server or MS SkyDrive and the target filepath is of a restricted type. } @@ -2055,51 +2093,15 @@ void copyFileWindowsDefault(const Zstring& sourceFile, if (newAttrib) { newAttrib->fileSize = get64BitUInt(cbd.fileInfoSrc.nFileSizeLow, cbd.fileInfoSrc.nFileSizeHigh); - //newAttrib->modificationTime = -> set further below + newAttrib->modificationTime = filetimeToTimeT(cbd.fileInfoSrc.ftLastWriteTime); newAttrib->sourceFileId = extractFileId(cbd.fileInfoSrc); newAttrib->targetFileId = extractFileId(cbd.fileInfoTrg); } + warn_static("new perf check + investigate improvements now that DST hcak is gone! =>") - { - FILETIME creationtime = cbd.fileInfoSrc.ftCreationTime; - FILETIME lastWriteTimeRaw = cbd.fileInfoSrc.ftLastWriteTime; - //####################################### DST hack ########################################### - warn_static("let's tentatively disable the DST hack:") -#if 0 - if (dst::isFatDrive(sourceFile)) //throw(); hacky: does not consider symlinks pointing to FAT! - { - const dst::RawTime rawTime(creationtime, lastWriteTimeRaw); - if (dst::fatHasUtcEncoded(rawTime)) //throw std::runtime_error - { - lastWriteTimeRaw = dst::fatDecodeUtcTime(rawTime); //return last write time in real UTC, throw (std::runtime_error) - ::GetSystemTimeAsFileTime(&creationtime); //real creation time information is not available... - } - } -#endif - //####################################### DST hack ########################################### - - if (newAttrib) - newAttrib->modificationTime = filetimeToTimeT(lastWriteTimeRaw); - - //caveat: - ::CopyFileEx() silently *ignores* failure to set modification time!!! => we always need to set it again but with proper error checking! - // - perf-loss on USB sticks with many small files of about 30%! - FILETIME creationTimeOut = creationtime; - FILETIME lastWriteTimeOut = lastWriteTimeRaw; - - //####################################### DST hack ########################################### - warn_static("let's tentatively disable the DST hack:") -#if 0 - if (dst::isFatDrive(targetFile)) //throw(); target cannot be a symlink in this context! - { - const dst::RawTime encodedTime = dst::fatEncodeUtcTime(lastWriteTimeRaw); //throw std::runtime_error - creationTimeOut = encodedTime.createTimeRaw; - lastWriteTimeOut = encodedTime.writeTimeRaw; - } -#endif - //####################################### DST hack ########################################### - - setFileTimeRaw(targetFile, creationTimeOut, lastWriteTimeOut, ProcSymlink::FOLLOW); //throw FileError - } + //caveat: - ::CopyFileEx() silently *ignores* failure to set modification time!!! => we always need to set it again but with proper error checking! + // - perf-loss on USB sticks with many small files of about 30%! + setFileTimeRaw(targetFile, &cbd.fileInfoSrc.ftCreationTime, cbd.fileInfoSrc.ftLastWriteTime, ProcSymlink::FOLLOW); //throw FileError guardTarget.dismiss(); //target has been created successfully! } @@ -2111,11 +2113,11 @@ void copyFileWindowsSelectRoutine(const Zstring& sourceFile, const Zstring& targ { try { - copyFileWindowsDefault(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw ErrorShouldCopyAsSparse et al. + copyFileWindowsDefault(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetExisting, ErrorFileLocked, ErrorShouldCopyAsSparse } - catch (ErrorShouldCopyAsSparse&) //we cheaply check for this condition within callback of ::CopyFileEx()! + catch (ErrorShouldCopyAsSparse&) //we quickly check for this condition within callback of ::CopyFileEx()! { - copyFileWindowsSparse(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); + copyFileWindowsSparse(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetExisting, ErrorFileLocked } } @@ -2129,7 +2131,7 @@ void copyFileWindows(const Zstring& sourceFile, { try { - copyFileWindowsSelectRoutine(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked + copyFileWindowsSelectRoutine(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetExisting, ErrorFileLocked } catch (const ErrorTargetExisting&) { @@ -2149,22 +2151,19 @@ void copyFileWindows(const Zstring& sourceFile, void copyFileLinuxMac(const Zstring& sourceFile, const Zstring& targetFile, const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus, - InSyncAttributes* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting + InSyncAttributes* newAttrib) //throw FileError, ErrorTargetExisting { - //open sourceFile for reading FileInputUnbuffered fileIn(sourceFile); //throw FileError struct ::stat sourceInfo = {}; - if (::fstat(fileIn.getDescriptor(), &sourceInfo) != 0) //read file attributes from source + if (::fstat(fileIn.getDescriptor(), &sourceInfo) != 0) throwFileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtFileName(sourceFile)), L"fstat", getLastError()); zen::ScopeGuard guardTarget = zen::makeGuard([&] { try { removeFile(targetFile); } catch (FileError&) {} }); //transactional behavior: place guard before lifetime of FileOutput try { - //create targetFile and open it for writing - FileOutputUnbuffered fileOut(targetFile, sourceInfo.st_mode); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting + FileOutputUnbuffered fileOut(targetFile, sourceInfo.st_mode); //throw FileError, ErrorTargetExisting - //copy contents of sourceFile to targetFile std::vector<char> buffer(128 * 1024); //see comment in FileInputUnbuffered::read do { @@ -2172,7 +2171,6 @@ void copyFileLinuxMac(const Zstring& sourceFile, fileOut.write(&buffer[0], bytesRead); //throw FileError - //invoke callback method to update progress indicators if (onUpdateCopyStatus) onUpdateCopyStatus(bytesRead); //throw X! } @@ -2229,20 +2227,31 @@ copyFileWindowsDefault(::CopyFileEx) copyFileWindowsSparse(::BackupRead/::Backu inline void copyFileSelectOs(const Zstring& sourceFile, const Zstring& targetFile, + bool copyFilePermissions, const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus, InSyncAttributes* sourceAttr) { #ifdef ZEN_WIN - copyFileWindows(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked + copyFileWindows(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetExisting, ErrorFileLocked #elif defined ZEN_LINUX || defined ZEN_MAC - copyFileLinuxMac(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting + copyFileLinuxMac(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetExisting #endif + + if (copyFilePermissions) + { + //at this point we know we created a new file, so it's fine to delete it for cleanup! + zen::ScopeGuard guardTargetFile = zen::makeGuard([&] { try { removeFile(targetFile); } catch (FileError&) {}}); + + copyObjectPermissions(sourceFile, targetFile, ProcSymlink::FOLLOW); //throw FileError + + guardTargetFile.dismiss(); //target has been created successfully! + } } } -void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPathMissing, ErrorFileLocked +void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorFileLocked const Zstring& targetFile, bool copyFilePermissions, bool transactionalCopy, @@ -2252,13 +2261,12 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath { if (transactionalCopy) { - Zstring tmpTarget = targetFile + TEMP_FILE_ENDING; //use temporary file until a correct date has been set + Zstring tmpTarget = targetFile + TEMP_FILE_ENDING; - //raw file copy for (int i = 0;; ++i) try { - copyFileSelectOs(sourceFile, tmpTarget, onUpdateCopyStatus, sourceAttr); //throw FileError: ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked + copyFileSelectOs(sourceFile, tmpTarget, copyFilePermissions, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetExisting, ErrorFileLocked break; } catch (const ErrorTargetExisting&) //optimistic strategy: assume everything goes well, but recover on error -> minimize file accesses @@ -2274,7 +2282,6 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath if (onDeleteTargetFile) onDeleteTargetFile(); //throw X - //rename temporary file: //perf: this call is REALLY expensive on unbuffered volumes! ~40% performance decrease on FAT USB stick! renameFile(tmpTarget, targetFile); //throw FileError @@ -2284,45 +2291,23 @@ void zen::copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPath This "feature" is called "File System Tunneling": http://blogs.msdn.com/b/oldnewthing/archive/2005/07/15/439261.aspx http://support.microsoft.com/kb/172190/en-us - - However during the next comparison the DST hack will be applied correctly since the DST-hash of the mod.time is invalid. - - EXCEPTION: the hash may match!!! reproduce: - 1. set system time back to date within previous DST - 2. save some file on FAT32 usb stick and FFS-compare to make sure the DST hack is applied correctly - 4. pull out usb stick, put back in - 3. restore system time - 4. copy file from USB to local drive via explorer - => - NTFS <-> FAT, file exists on both sides; mod times match, DST hack on USB stick causes 1-hour offset when comparing in FFS. - When syncing, modification time is copied correctly, but new DST hack fails to apply and old creation time is reused (see above). - Unfortunately, the old DST hash matches mod time! => On next comparison FFS will *still* see both sides as different!!!!!!!!! */ guardTempFile.dismiss(); } else { + /* + Note: non-transactional file copy solves at least four problems: + -> skydrive - doesn't allow for .ffs_tmp extension and returns ERROR_INVALID_PARAMETER + -> network renaming issues + -> allow for true delete before copy to handle low disk space problems + -> higher performance on non-buffered drives (e.g. usb sticks) + */ + if (onDeleteTargetFile) onDeleteTargetFile(); - copyFileSelectOs(sourceFile, targetFile, onUpdateCopyStatus, sourceAttr); //throw FileError: ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked - } - /* - Note: non-transactional file copy solves at least four problems: - -> skydrive - doesn't allow for .ffs_tmp extension and returns ERROR_INVALID_PARAMETER - -> network renaming issues - -> allow for true delete before copy to handle low disk space problems - -> higher performance on non-buffered drives (e.g. usb sticks) - */ - - //file permissions - if (copyFilePermissions) - { - zen::ScopeGuard guardTargetFile = zen::makeGuard([&] { try { removeFile(targetFile); } catch (FileError&) {}}); - - copyObjectPermissions(sourceFile, targetFile, ProcSymlink::FOLLOW); //throw FileError - - guardTargetFile.dismiss(); //target has been created successfully! + copyFileSelectOs(sourceFile, targetFile, copyFilePermissions, onUpdateCopyStatus, sourceAttr); //throw FileError, ErrorTargetExisting, ErrorFileLocked } } diff --git a/zen/file_handling.h b/zen/file_access.h index b58f6c07..7cac889c 100644 --- a/zen/file_handling.h +++ b/zen/file_access.h @@ -4,8 +4,8 @@ // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** -#ifndef FILE_HANDLING_H_8017341345614857 -#define FILE_HANDLING_H_8017341345614857 +#ifndef FILE_ACCESS_H_8017341345614857 +#define FILE_ACCESS_H_8017341345614857 #include <functional> #include "zstring.h" @@ -57,15 +57,13 @@ struct InSyncAttributes FileId targetFileId; }; -void copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPathMissing, ErrorFileLocked (Windows-only) +void copyFile(const Zstring& sourceFile, //throw FileError, ErrorFileLocked (Windows-only) const Zstring& targetFile, //symlink handling: dereference source bool copyFilePermissions, bool transactionalCopy, //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, //may be nullptr; may throw! - //Linux: unconditionally - //Windows: first exception is swallowed, updateCopyStatus() is then called again where it should throw again and the exception will propagate as expected //accummulated delta != file size! consider ADS, sparse, compressed files const std::function<void(std::int64_t bytesDelta)>& onUpdateCopyStatus, //may be nullptr; may throw! @@ -79,4 +77,4 @@ const Zchar TEMP_FILE_ENDING[] = Zstr(".ffs_tmp"); //don't use Zstring as global void copySymlink(const Zstring& sourceLink, const Zstring& targetLink, bool copyFilePermissions); //throw FileError } -#endif //FILE_HANDLING_H_8017341345614857 +#endif //FILE_ACCESS_H_8017341345614857 diff --git a/zen/file_id_def.h b/zen/file_id_def.h index daadd391..3b217b3d 100644 --- a/zen/file_id_def.h +++ b/zen/file_id_def.h @@ -8,7 +8,6 @@ #define FILE_ID_INTERNAL_HEADER_013287632486321493 #include <utility> -#include "assert_static.h" #ifdef ZEN_WIN #include "win.h" //includes "windows.h" @@ -44,9 +43,9 @@ FileId extractFileId(DWORD volumeSerialNumber, ULONGLONG fileIndex) FileId(volumeSerialNumber, fileIndex) : FileId(); } -assert_static(sizeof(FileId().first ) == sizeof(BY_HANDLE_FILE_INFORMATION().dwVolumeSerialNumber)); -assert_static(sizeof(FileId().second) == sizeof(BY_HANDLE_FILE_INFORMATION().nFileIndexHigh) + sizeof(BY_HANDLE_FILE_INFORMATION().nFileIndexLow)); -assert_static(sizeof(FileId().second) == sizeof(ULARGE_INTEGER)); +static_assert(sizeof(FileId().first ) == sizeof(BY_HANDLE_FILE_INFORMATION().dwVolumeSerialNumber), ""); +static_assert(sizeof(FileId().second) == sizeof(BY_HANDLE_FILE_INFORMATION().nFileIndexHigh) + sizeof(BY_HANDLE_FILE_INFORMATION().nFileIndexLow), ""); +static_assert(sizeof(FileId().second) == sizeof(ULARGE_INTEGER), ""); #elif defined ZEN_LINUX || defined ZEN_MAC diff --git a/zen/file_io.cpp b/zen/file_io.cpp index e11a1201..8f4b6cb2 100644 --- a/zen/file_io.cpp +++ b/zen/file_io.cpp @@ -187,7 +187,7 @@ size_t FileInput::read(void* buffer, size_t bytesToRead) //returns actual number FileOutput::FileOutput(FileHandle handle, const Zstring& filepath) : FileOutputBase(filepath), fileHandle(handle) {} -FileOutput::FileOutput(const Zstring& filepath, AccessFlag access) : //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting +FileOutput::FileOutput(const Zstring& filepath, AccessFlag access) : //throw FileError, ErrorTargetExisting FileOutputBase(filepath) { #ifdef ZEN_WIN @@ -246,8 +246,7 @@ FileOutput::FileOutput(const Zstring& filepath, AccessFlag access) : //throw Fil lastError == ERROR_ALREADY_EXISTS) //comment on msdn claims, this one is used on Windows Mobile 6 throw ErrorTargetExisting(errorMsg, errorDescr); - if (lastError == ERROR_PATH_NOT_FOUND) - throw ErrorTargetPathMissing(errorMsg, errorDescr); + //if (lastError == ERROR_PATH_NOT_FOUND) throw ErrorTargetPathMissing(errorMsg, errorDescr); throw FileError(errorMsg, errorDescr); } @@ -267,8 +266,7 @@ FileOutput::FileOutput(const Zstring& filepath, AccessFlag access) : //throw Fil if (lastError == EEXIST) throw ErrorTargetExisting(errorMsg, errorDescr); - if (lastError == ENOENT) - throw ErrorTargetPathMissing(errorMsg, errorDescr); + //if (lastError == ENOENT) throw ErrorTargetPathMissing(errorMsg, errorDescr); throw FileError(errorMsg, errorDescr); } @@ -348,7 +346,7 @@ size_t FileInputUnbuffered::read(void* buffer, size_t bytesToRead) //throw FileE } -FileOutputUnbuffered::FileOutputUnbuffered(const Zstring& filepath, mode_t mode) : FileOutputBase(filepath) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting +FileOutputUnbuffered::FileOutputUnbuffered(const Zstring& filepath, mode_t mode) : FileOutputBase(filepath) //throw FileError, ErrorTargetExisting { //checkForUnsupportedType(filepath); -> not needed, open() + O_EXCL shoul fail fast @@ -363,8 +361,7 @@ FileOutputUnbuffered::FileOutputUnbuffered(const Zstring& filepath, mode_t mode) if (lastError == EEXIST) throw ErrorTargetExisting(errorMsg, errorDescr); - if (lastError == ENOENT) - throw ErrorTargetPathMissing(errorMsg, errorDescr); + //if (lastError == ENOENT) throw ErrorTargetPathMissing(errorMsg, errorDescr); throw FileError(errorMsg, errorDescr); } diff --git a/zen/file_io.h b/zen/file_io.h index 5ae6eb1c..7ccef05b 100644 --- a/zen/file_io.h +++ b/zen/file_io.h @@ -26,7 +26,7 @@ static const char LINE_BREAK[] = "\r\n"; static const char LINE_BREAK[] = "\n"; //since OS X apple uses newline, too #endif -//buffered file IO optimized for sequential read/write accesses + better error reporting + long path support (following symlinks) +//buffered file IO optimized for sequential read/write accesses + better error reporting + long path support + following symlinks #ifdef ZEN_WIN typedef HANDLE FileHandle; @@ -41,8 +41,7 @@ public: FileInput(FileHandle handle, const Zstring& filepath); //takes ownership! ~FileInput(); - virtual size_t read(void* buffer, size_t bytesToRead) override; //throw FileError; returns actual number of bytes read - //expected to fill buffer completely unless "end of file" + size_t read(void* buffer, size_t bytesToRead) override; //throw FileError; returns actual number of bytes read private: FileHandle fileHandle; @@ -52,17 +51,19 @@ private: class FileOutput : public FileOutputBase { public: - FileOutput(const Zstring& filepath, AccessFlag access); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting + FileOutput(const Zstring& filepath, AccessFlag access); //throw FileError, ErrorTargetExisting FileOutput(FileHandle handle, const Zstring& filepath); //takes ownership! ~FileOutput(); - virtual void write(const void* buffer, size_t bytesToWrite) override; //throw FileError + void write(const void* buffer, size_t bytesToWrite) override; //throw FileError private: FileHandle fileHandle; }; #if defined ZEN_LINUX || defined ZEN_MAC +warn_static("get rid of FileInputUnbuffered/FileOutputUnbuffered, use fdopen instead") + class FileInputUnbuffered : public FileInputBase { public: @@ -70,7 +71,7 @@ public: ~FileInputUnbuffered(); //considering safe-read.c it seems buffer size should be a multiple of 8192 - virtual size_t read(void* buffer, size_t bytesToRead) override; //throw FileError; returns actual number of bytes read + size_t read(void* buffer, size_t bytesToRead) override; //throw FileError; returns actual number of bytes read //do NOT rely on partially filled buffer meaning EOF! int getDescriptor() { return fdFile;} @@ -83,11 +84,11 @@ class FileOutputUnbuffered : public FileOutputBase { public: //creates a new file (no overwrite allowed!) - FileOutputUnbuffered(const Zstring& filepath, mode_t mode); //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting + FileOutputUnbuffered(const Zstring& filepath, mode_t mode); //throw FileError, ErrorTargetExisting FileOutputUnbuffered(int fd, const Zstring& filepath); //takes ownership! ~FileOutputUnbuffered(); - virtual void write(const void* buffer, size_t bytesToWrite) override; //throw FileError + void write(const void* buffer, size_t bytesToWrite) override; //throw FileError int getDescriptor() { return fdFile;} private: diff --git a/zen/file_io_base.h b/zen/file_io_base.h index 8e9bf12e..e56ea189 100644 --- a/zen/file_io_base.h +++ b/zen/file_io_base.h @@ -21,8 +21,8 @@ protected: ~FileBase() {} private: - FileBase(const FileBase&); //=delete - FileBase& operator=(const FileBase&); // + FileBase (const FileBase&) = delete; + FileBase& operator=(const FileBase&) = delete; const Zstring filename_; }; diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp index d8f2d0cf..7b423faa 100644 --- a/zen/file_traverser.cpp +++ b/zen/file_traverser.cpp @@ -6,15 +6,13 @@ #include "file_traverser.h" #include "sys_error.h" -#include "assert_static.h" #include "symlink_target.h" #include "int64.h" #ifdef ZEN_WIN #include "win_ver.h" #include "long_path_prefix.h" -#include "dst_hack.h" -#include "file_handling.h" //remove this huge dependency when getting rid of DST hack!! until then we need "setFileTime" +#include "file_access.h" #include "dll.h" #include "FindFilePlus/find_file_plus.h" @@ -30,7 +28,7 @@ using namespace zen; - + namespace { //implement "retry" in a generic way: @@ -179,8 +177,8 @@ struct Win32Traverser { struct DirHandle { - DirHandle(HANDLE hnd, const WIN32_FIND_DATA& d) : searchHandle(hnd), haveData(true), data(d) {} - explicit DirHandle(HANDLE hnd) : searchHandle(hnd), haveData(false) {} + DirHandle(HANDLE hnd, const WIN32_FIND_DATA& d) : searchHandle(hnd), haveData(true), data(d) {} + explicit DirHandle(HANDLE hnd) : searchHandle(hnd), haveData(false) {} HANDLE searchHandle; bool haveData; @@ -193,7 +191,7 @@ struct Win32Traverser { const Zstring& dirpathPf = appendSeparator(dirpath); - WIN32_FIND_DATA fileData = {}; + WIN32_FIND_DATA fileData = {}; HANDLE hnd = ::FindFirstFile(applyLongPathPrefix(dirpathPf + L'*').c_str(), &fileData); //no noticable performance difference compared to FindFirstFileEx with FindExInfoBasic, FIND_FIRST_EX_CASE_SENSITIVE and/or FIND_FIRST_EX_LARGE_FETCH if (hnd == INVALID_HANDLE_VALUE) @@ -208,7 +206,7 @@ struct Win32Traverser } throwFileError(replaceCpy(_("Cannot open directory %x."), L"%x", fmtFileName(dirpath)), L"FindFirstFile", lastError); } - return DirHandle(hnd, fileData); + return DirHandle(hnd, fileData); } static void destroy(const DirHandle& hnd) { ::FindClose(hnd.searchHandle); } //throw() @@ -271,11 +269,11 @@ struct FilePlusTraverser static DirHandle create(const Zstring& dirpath) //throw FileError { - const findplus::FindHandle hnd = ::openDir(applyLongPathPrefix(dirpath).c_str()); + const findplus::FindHandle hnd = ::openDir(applyLongPathPrefix(dirpath).c_str()); if (!hnd) - throwFileError(replaceCpy(_("Cannot open directory %x."), L"%x", fmtFileName(dirpath)), L"openDir", getLastError()); + throwFileError(replaceCpy(_("Cannot open directory %x."), L"%x", fmtFileName(dirpath)), L"openDir", getLastError()); - return DirHandle(hnd); + return DirHandle(hnd); } static void destroy(DirHandle hnd) { ::closeDir(hnd.searchHandle); } //throw() @@ -325,13 +323,13 @@ struct FilePlusTraverser class DirTraverser { public: - static void execute(const Zstring& baseDirectory, TraverseCallback& sink, DstHackCallback* dstCallback) + static void execute(const Zstring& baseDirectory, TraverseCallback& sink) { - DirTraverser(baseDirectory, sink, dstCallback); + DirTraverser(baseDirectory, sink); } private: - DirTraverser(const Zstring& baseDirectory, TraverseCallback& sink, DstHackCallback* dstCallback); + DirTraverser(const Zstring& baseDirectory, TraverseCallback& sink); DirTraverser (const DirTraverser&) = delete; DirTraverser& operator=(const DirTraverser&) = delete; @@ -340,58 +338,6 @@ private: template <class Trav> void traverseWithException(const Zstring& dirpath, TraverseCallback& sink, DWORD volumeSerial /*may be 0!*/); //throw FileError, NeedFallbackToWin32Traverser - - //####################################### DST hack ########################################### - void applyDstHack(zen::DstHackCallback& dstCallback) - { - int failedAttempts = 0; - int filesToValidate = 50; //don't let data verification become a performance issue - - for (auto it = markForDstHack.begin(); it != markForDstHack.end(); ++it) - { - if (failedAttempts >= 10) //some cloud storages don't support changing creation/modification times => don't waste (a lot of) time trying to - return; - - dstCallback.requestUiRefresh(it->first); - - try - { - //set modification time including DST hack: this function is too clever to not introduce this dependency - setFileTime(it->first, it->second, ProcSymlink::FOLLOW); //throw FileError - } - catch (FileError&) - { - ++failedAttempts; - assert(false); //don't throw exceptions due to dst hack here - continue; - } - - //even at this point it's not sure whether data was written correctly, again cloud storages tend to lie about success status - if (filesToValidate-- > 0) - { - const dst::RawTime encodedTime = dst::fatEncodeUtcTime(timetToFileTime(it->second)); //throw std::runtime_error - - //dst hack: verify data written; attention: this check may fail for "sync.ffs_lock" - WIN32_FILE_ATTRIBUTE_DATA debugeAttr = {}; - ::GetFileAttributesEx(zen::applyLongPathPrefix(it->first).c_str(), //__in LPCTSTR lpFileName, - GetFileExInfoStandard, //__in GET_FILEEX_INFO_LEVELS fInfoLevelId, - &debugeAttr); //__out LPVOID lpFileInformation - - if (::CompareFileTime(&debugeAttr.ftCreationTime, &encodedTime.createTimeRaw) != 0 || - ::CompareFileTime(&debugeAttr.ftLastWriteTime, &encodedTime.writeTimeRaw) != 0) - { - ++failedAttempts; - assert(false); //don't throw exceptions due to dst hack here - continue; - } - } - } - } - - const bool needDstHack; - typedef std::vector<std::pair<Zstring, std::int64_t>> FilenameTimeList; - FilenameTimeList markForDstHack; - //####################################### DST hack ########################################### }; @@ -420,8 +366,7 @@ void DirTraverser::traverse<FilePlusTraverser>(const Zstring& dirpath, TraverseC inline -DirTraverser::DirTraverser(const Zstring& baseDirectory, TraverseCallback& sink, DstHackCallback* dstCallback) : - needDstHack(dstCallback ? dst::isFatDrive(baseDirectory) : false) +DirTraverser::DirTraverser(const Zstring& baseDirectory, TraverseCallback& sink) { try //traversing certain folders with restricted permissions requires this privilege! (but copying these files may still fail) { @@ -433,11 +378,6 @@ DirTraverser::DirTraverser(const Zstring& baseDirectory, TraverseCallback& sink, traverse<FilePlusTraverser>(baseDirectory, sink, retrieveVolumeSerial(baseDirectory)); //retrieveVolumeSerial returns 0 on error else //fallback traverse<Win32Traverser>(baseDirectory, sink, 0); - - //apply daylight saving time hack AFTER file traversing, to give separate feedback to user - if (needDstHack) - if (dstCallback) //bound if "needDstHack == true" - applyDstHack(*dstCallback); } @@ -507,20 +447,7 @@ void DirTraverser::traverseWithException(const Zstring& dirpath, TraverseCallbac } else //a file { - TraverseCallback::FileInfo fileInfo = Trav::extractFileInfo(findData, volumeSerial); - - //####################################### DST hack ########################################### - if (needDstHack) - { - const dst::RawTime rawTime(Trav::getCreateTimeRaw(findData), Trav::getModTimeRaw(findData)); - - if (dst::fatHasUtcEncoded(rawTime)) //throw std::runtime_error - fileInfo.lastWriteTime = filetimeToTimeT(dst::fatDecodeUtcTime(rawTime)); //return real UTC time; throw std::runtime_error - else - markForDstHack.push_back(std::make_pair(itempath, filetimeToTimeT(rawTime.writeTimeRaw))); - } - //####################################### DST hack ########################################### - + const TraverseCallback::FileInfo fileInfo = Trav::extractFileInfo(findData, volumeSerial); sink.onFile(shortName, itempath, fileInfo); } } @@ -531,13 +458,13 @@ void DirTraverser::traverseWithException(const Zstring& dirpath, TraverseCallbac class DirTraverser { public: - static void execute(const Zstring& baseDirectory, TraverseCallback& sink, DstHackCallback* dstCallback) + static void execute(const Zstring& baseDirectory, TraverseCallback& sink) { - DirTraverser(baseDirectory, sink, dstCallback); + DirTraverser(baseDirectory, sink); } private: - DirTraverser(const Zstring& baseDirectory, zen::TraverseCallback& sink, zen::DstHackCallback* dstCallback) + DirTraverser(const Zstring& baseDirectory, zen::TraverseCallback& sink) { const Zstring directoryFormatted = //remove trailing slash baseDirectory.size() > 1 && endsWith(baseDirectory, FILE_NAME_SEPARATOR) ? //exception: allow '/' @@ -701,12 +628,4 @@ private: } -void zen::traverseFolder(const Zstring& dirpath, TraverseCallback& sink, DstHackCallback* dstCallback) -{ - warn_static("let's tentatively disable the DST hack:") - DirTraverser::execute(dirpath, sink, nullptr); - return; -#if 0 - DirTraverser::execute(dirpath, sink, dstCallback); -#endif -} +void zen::traverseFolder(const Zstring& dirpath, TraverseCallback& sink) { DirTraverser::execute(dirpath, sink); } diff --git a/zen/file_traverser.h b/zen/file_traverser.h index f240d8c7..c9efbdb1 100644 --- a/zen/file_traverser.h +++ b/zen/file_traverser.h @@ -58,23 +58,10 @@ struct TraverseCallback virtual HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) = 0; //failed to get data for single file/dir/symlink only! }; - -#ifdef ZEN_WIN -struct DstHackCallback -{ - virtual ~DstHackCallback() {} - virtual void requestUiRefresh(const Zstring& filepath) = 0; //applying DST hack imposes significant one-time performance drawback => callback to inform user -}; -#elif defined ZEN_LINUX || defined ZEN_MAC -struct DstHackCallback; //DST hack not required on Unix -#endif - //custom traverser with detail information about files //- client needs to handle duplicate file reports! (FilePlusTraverser fallback, retrying to read directory contents, ...) //- directory may end with PATH_SEPARATOR -void traverseFolder(const Zstring& dirpath, //throw() - TraverseCallback& sink, - DstHackCallback* dstCallback = nullptr); //apply DST hack if callback is supplied +void traverseFolder(const Zstring& dirpath, TraverseCallback& sink); //noexcept } #endif // FILETRAVERSER_H_INCLUDED diff --git a/zen/fixed_list.h b/zen/fixed_list.h index 63ef3f2f..627584df 100644 --- a/zen/fixed_list.h +++ b/zen/fixed_list.h @@ -11,22 +11,15 @@ namespace zen { -//std::list(C++11) compatible class for inplace element construction supporting non-copyable/movable types +//std::list(C++11)-like class for inplace element construction supporting non-copyable/movable types //may be replaced by C++11 std::list when available...or never... template <class T> class FixedList { struct Node { - Node() : next(nullptr), val() {} - //no variadic templates on VC2010... :( - template <class A> Node(A&& a) : next(nullptr), val(std::forward<A>(a)) {} - template <class A, class B> Node(A&& a, B&& b) : next(nullptr), val(std::forward<A>(a), std::forward<B>(b)) {} - template <class A, class B, class C> Node(A&& a, B&& b, C&& c) : next(nullptr), val(std::forward<A>(a), std::forward<B>(b), std::forward<C>(c)) {} - template <class A, class B, class C, class D> Node(A&& a, B&& b, C&& c, D&& d) : next(nullptr), val(std::forward<A>(a), std::forward<B>(b), std::forward<C>(c), std::forward<D>(d)) {} - template <class A, class B, class C, class D, class E> Node(A&& a, B&& b, C&& c, D&& d, E&& e) : next(nullptr), val(std::forward<A>(a), std::forward<B>(b), std::forward<C>(c), std::forward<D>(d), std::forward<E>(e)) {} - template <class A, class B, class C, class D, class E, class F> Node(A&& a, B&& b, C&& c, D&& d, E&& e, F&& f) : next(nullptr), val(std::forward<A>(a), std::forward<B>(b), std::forward<C>(c), std::forward<D>(d), std::forward<E>(e), std::forward<F>(f)) {} - template <class A, class B, class C, class D, class E, class F, class G> Node(A&& a, B&& b, C&& c, D&& d, E&& e, F&& f, G&& g) : next(nullptr), val(std::forward<A>(a), std::forward<B>(b), std::forward<C>(c), std::forward<D>(d), std::forward<E>(e), std::forward<F>(f), std::forward<G>(g)) {} + template <class... Args> + Node(Args&& ... args) : next(nullptr), val(std::forward<Args>(args)...) {} Node* next; //singly linked list is sufficient T val; @@ -48,20 +41,20 @@ public: ListIterator& operator++() { iter = iter->next; return *this; } inline friend bool operator==(const ListIterator& lhs, const ListIterator& rhs) { return lhs.iter == rhs.iter; } inline friend bool operator!=(const ListIterator& lhs, const ListIterator& rhs) { return !(lhs == rhs); } - U& operator* () { return iter->val; } - U* operator->() { return &iter->val; } + U& operator* () const { return iter->val; } + U* operator->() const { return &iter->val; } private: NodeT* iter; }; typedef T value_type; - typedef ListIterator<Node, T> iterator; + typedef ListIterator< Node, T> iterator; typedef ListIterator<const Node, const T> const_iterator; - typedef T& reference; + typedef T& reference; typedef const T& const_reference; iterator begin() { return firstInsert; } - iterator end() { return iterator(); } + iterator end () { return iterator(); } const_iterator begin() const { return firstInsert; } const_iterator end () const { return const_iterator(); } @@ -75,14 +68,8 @@ public: reference& back() { return lastInsert->val; } const_reference& back() const { return lastInsert->val; } - void emplace_back() { pushNode(new Node); } - template <class A> void emplace_back(A&& a) { pushNode(new Node(std::forward<A>(a))); } - template <class A, class B> void emplace_back(A&& a, B&& b) { pushNode(new Node(std::forward<A>(a), std::forward<B>(b))); } - template <class A, class B, class C> void emplace_back(A&& a, B&& b, C&& c) { pushNode(new Node(std::forward<A>(a), std::forward<B>(b), std::forward<C>(c))); } - template <class A, class B, class C, class D> void emplace_back(A&& a, B&& b, C&& c, D&& d) { pushNode(new Node(std::forward<A>(a), std::forward<B>(b), std::forward<C>(c), std::forward<D>(d))); } - template <class A, class B, class C, class D, class E> void emplace_back(A&& a, B&& b, C&& c, D&& d, E&& e) { pushNode(new Node(std::forward<A>(a), std::forward<B>(b), std::forward<C>(c), std::forward<D>(d), std::forward<E>(e))); } - template <class A, class B, class C, class D, class E, class F> void emplace_back(A&& a, B&& b, C&& c, D&& d, E&& e, F&& f) { pushNode(new Node(std::forward<A>(a), std::forward<B>(b), std::forward<C>(c), std::forward<D>(d), std::forward<E>(e), std::forward<F>(f))); } - template <class A, class B, class C, class D, class E, class F, class G> void emplace_back(A&& a, B&& b, C&& c, D&& d, E&& e, F&& f, G&& g) { pushNode(new Node(std::forward<A>(a), std::forward<B>(b), std::forward<C>(c), std::forward<D>(d), std::forward<E>(e), std::forward<F>(f), std::forward<G>(g))); } + template <class... Args> + void emplace_back(Args&& ... args) { pushNode(new Node(std::forward<Args>(args)...)); } template <class Predicate> void remove_if(Predicate pred) @@ -126,6 +113,7 @@ public: } bool empty() const { return firstInsert == nullptr; } + size_t size() const { return sz; } private: diff --git a/zen/format_unit.h b/zen/format_unit.h index 237b9f04..9416e3e5 100644 --- a/zen/format_unit.h +++ b/zen/format_unit.h @@ -44,7 +44,7 @@ std::wstring includeNumberSeparator(const std::wstring& number); template <class NumberType> inline std::wstring toGuiString(NumberType number) { - assert_static(IsInteger<NumberType>::value); + static_assert(IsInteger<NumberType>::value, ""); return ffs_Impl::includeNumberSeparator(zen::numberTo<std::wstring>(number)); } } @@ -4,8 +4,8 @@ // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** -#ifndef GUID_H_INCLUDED -#define GUID_H_INCLUDED +#ifndef GUID_H_INCLUDED_80425780237502345 +#define GUID_H_INCLUDED_80425780237502345 #include <string> #include <boost/uuid/uuid.hpp> @@ -35,4 +35,4 @@ std::string generateGUID() //creates a 16 byte GUID } } -#endif // GUID_H_INCLUDED +#endif //GUID_H_INCLUDED_80425780237502345 @@ -37,7 +37,7 @@ struct TranslationHandler virtual std::wstring translate(const std::wstring& singular, const std::wstring& plural, std::int64_t n) = 0; }; -void setTranslator(TranslationHandler* newHandler = nullptr); //takes ownership +void setTranslator(std::unique_ptr<TranslationHandler>&& newHandler = nullptr); //take ownership TranslationHandler* getTranslator(); @@ -58,7 +58,10 @@ namespace implementation inline std::wstring translate(const std::wstring& text) { - return getTranslator() ? getTranslator()->translate(text) : text; + if (TranslationHandler* t = getTranslator()) + return t->translate(text); + + return text; } //translate plural forms: "%x day" "%x days" @@ -68,13 +71,13 @@ std::wstring translate(const std::wstring& singular, const std::wstring& plural, { assert(contains(plural, L"%x")); - if (getTranslator()) + if (TranslationHandler* t = getTranslator()) { - std::wstring translation = getTranslator()->translate(singular, plural, n); + std::wstring translation = t->translate(singular, plural, n); assert(!contains(translation, L"%x")); return translation; } - else + return replaceCpy(std::abs(n) == 1 ? singular : plural, L"%x", toGuiString(n)); } @@ -94,7 +97,7 @@ std::unique_ptr<TranslationHandler>& globalHandler() } inline -void setTranslator(TranslationHandler* newHandler) { implementation::globalHandler().reset(newHandler); } //takes ownership +void setTranslator(std::unique_ptr<TranslationHandler>&& newHandler) { implementation::globalHandler() = std::move(newHandler); } inline TranslationHandler* getTranslator() { return implementation::globalHandler().get(); } diff --git a/zen/int64.h b/zen/int64.h index 4183c8da..671f3372 100644 --- a/zen/int64.h +++ b/zen/int64.h @@ -18,29 +18,29 @@ namespace zen { #ifdef ZEN_WIN inline - std::int64_t get64BitInt(DWORD low, LONG high) - { - static_assert(sizeof(low) + sizeof(high) == sizeof(std::int64_t), ""); +std::int64_t get64BitInt(DWORD low, LONG high) +{ + static_assert(sizeof(low) + sizeof(high) == sizeof(std::int64_t), ""); - LARGE_INTEGER cvt = {}; - cvt.LowPart = low; - cvt.HighPart = high; - return cvt.QuadPart; - } + LARGE_INTEGER cvt = {}; + cvt.LowPart = low; + cvt.HighPart = high; + return cvt.QuadPart; +} std::int64_t get64BitInt(std::uint64_t low, std::int64_t high) = delete; inline std::uint64_t get64BitUInt(DWORD low, DWORD high) - { - static_assert(sizeof(low) + sizeof(high) == sizeof(std::uint64_t), ""); +{ + static_assert(sizeof(low) + sizeof(high) == sizeof(std::uint64_t), ""); - ULARGE_INTEGER cvt = {}; - cvt.LowPart = low; - cvt.HighPart = high; - return cvt.QuadPart; - } + ULARGE_INTEGER cvt = {}; + cvt.LowPart = low; + cvt.HighPart = high; + return cvt.QuadPart; +} std::int64_t get64BitUInt(std::uint64_t low, std::uint64_t high) = delete; @@ -52,15 +52,15 @@ std::int64_t get64BitUInt(std::uint64_t low, std::uint64_t high) = delete; inline std::int64_t filetimeToTimeT(const FILETIME& ft) { - return static_cast<std::int64_t>(get64BitUInt(ft.dwLowDateTime, ft.dwHighDateTime) / 10000000U) - get64BitInt(3054539008UL, 2); //caveat: signed/unsigned arithmetics! + return static_cast<std::int64_t>(get64BitUInt(ft.dwLowDateTime, ft.dwHighDateTime) / 10000000U) - get64BitInt(3054539008UL, 2); //caveat: signed/unsigned arithmetics! //timeshift between ansi C time and FILETIME in seconds == 11644473600s } inline FILETIME timetToFileTime(std::int64_t utcTime) -{ - ULARGE_INTEGER cvt = {}; - cvt.QuadPart = (utcTime + get64BitInt(3054539008UL, 2)) * 10000000U; //caveat: signed/unsigned arithmetics! +{ + ULARGE_INTEGER cvt = {}; + cvt.QuadPart = (utcTime + get64BitInt(3054539008UL, 2)) * 10000000U; //caveat: signed/unsigned arithmetics! const FILETIME output = { cvt.LowPart, cvt.HighPart }; return output; diff --git a/zen/notify_removal.cpp b/zen/notify_removal.cpp index 45a39c48..639264a6 100644 --- a/zen/notify_removal.cpp +++ b/zen/notify_removal.cpp @@ -169,7 +169,7 @@ private: Pimpl (const Pimpl&) = delete; Pimpl& operator=(const Pimpl&) = delete; - virtual void onMessage(UINT message, WPARAM wParam, LPARAM lParam) //throw()! + void onMessage(UINT message, WPARAM wParam, LPARAM lParam) override //throw()! { //DBT_DEVICEQUERYREMOVE example: http://msdn.microsoft.com/en-us/library/aa363427(v=VS.85).aspx if (message == WM_DEVICECHANGE) @@ -205,10 +205,7 @@ private: //#################################################################################################### -NotifyRequestDeviceRemoval::NotifyRequestDeviceRemoval(HANDLE hDir) -{ - pimpl.reset(new Pimpl(*this, hDir)); -} +NotifyRequestDeviceRemoval::NotifyRequestDeviceRemoval(HANDLE hDir) : pimpl(zen::make_unique<Pimpl>(*this, hDir)) {} NotifyRequestDeviceRemoval::~NotifyRequestDeviceRemoval() {} //make sure ~unique_ptr() works with complete type diff --git a/zen/notify_removal.h b/zen/notify_removal.h index aca0912f..ba560f96 100644 --- a/zen/notify_removal.h +++ b/zen/notify_removal.h @@ -4,8 +4,8 @@ // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** -#ifndef NOTIFY_H_INCLUDED -#define NOTIFY_H_INCLUDED +#ifndef NOTIFY_H_INCLUDED_257804267562 +#define NOTIFY_H_INCLUDED_257804267562 #include <memory> #include "win.h" //includes "windows.h" @@ -24,12 +24,11 @@ private: //NOTE: onRemovalFinished is NOT guaranteed to execute after onRequestRemoval()! but most likely will virtual void onRemovalFinished(HANDLE hnd, bool successful) = 0; //throw()! - NotifyRequestDeviceRemoval(NotifyRequestDeviceRemoval&); //no copying - void operator=(NotifyRequestDeviceRemoval&); // + NotifyRequestDeviceRemoval (NotifyRequestDeviceRemoval&) = delete; + NotifyRequestDeviceRemoval& operator=(NotifyRequestDeviceRemoval&) = delete; class Pimpl; std::unique_ptr<Pimpl> pimpl; }; - -#endif // NOTIFY_H_INCLUDED +#endif //NOTIFY_H_INCLUDED_257804267562 diff --git a/zen/osx_string.h b/zen/osx_string.h deleted file mode 100644 index ba83ca27..00000000 --- a/zen/osx_string.h +++ /dev/null @@ -1,82 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef OSX_STRING_1873641732143214324 -#define OSX_STRING_1873641732143214324 - -#include <CoreFoundation/CoreFoundation.h> //CFString -#include "zstring.h" - -namespace osx -{ -Zstring cfStringToZstring(const CFStringRef& cfStr); - -CFStringRef createCFString (const char* utf8Str); //returns nullptr on error -CFMutableStringRef createMutableCFString(const char* utf8Str); //pass ownership! => ZEN_ON_SCOPE_EXIT(::CFRelease(str)); - - - - - - - - - - - - - -//################# implementation ##################### -inline -Zstring cfStringToZstring(const CFStringRef& cfStr) -{ - if (cfStr) - { - //perf: try to get away cheap: - if (const char* utf8Str = ::CFStringGetCStringPtr(cfStr, kCFStringEncodingUTF8)) - return utf8Str; - - CFIndex length = ::CFStringGetLength(cfStr); - if (length > 0) - { - CFIndex bufferSize = ::CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); - Zstring buffer; - buffer.resize(bufferSize); - - if (::CFStringGetCString(cfStr, &*buffer.begin(), bufferSize, kCFStringEncodingUTF8)) - { - buffer.resize(zen::strLength(buffer.c_str())); //caveat: memory consumption of returned string! - return buffer; - } - } - } - return Zstring(); -} - - -inline -CFStringRef createCFString(const char* utf8Str) -{ - //don't bother with CFStringCreateWithBytes: it's slightly slower, despite passing length info - return ::CFStringCreateWithCString(nullptr, //CFAllocatorRef alloc, - utf8Str, //const char *cStr, - kCFStringEncodingUTF8); //CFStringEncoding encoding -} - - -inline -CFMutableStringRef createMutableCFString(const char* utf8Str) -{ - if (CFMutableStringRef strRef = ::CFStringCreateMutable(NULL, 0)) - { - ::CFStringAppendCString(strRef, utf8Str, kCFStringEncodingUTF8); - return strRef; - } - return nullptr; -} -} - -#endif //OSX_STRING_1873641732143214324 diff --git a/zen/osx_throw_exception.h b/zen/osx_throw_exception.h deleted file mode 100644 index 07e3af3e..00000000 --- a/zen/osx_throw_exception.h +++ /dev/null @@ -1,56 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef OSX_EXCEPTION_89274305834255 -#define OSX_EXCEPTION_89274305834255 - -#import <Cocoa/Cocoa.h> -#include "sys_error.h" -#include "utf.h" - -namespace osx -{ -//for use in Objective C implementation files only! -void throwSysError(NSException* e); //throw SysError - -#define ZEN_OSX_ASSERT(obj) ZEN_OSX_ASSERT_IMPL(obj, #obj) //throw SysError -/* -Example: ZEN_OSX_ASSERT(obj); - -Equivalent to: - if (!obj) - throw zen::SysError(L"Assertion failed: \"obj\"."); -*/ - - - - - - -//######################## implmentation ############################ -inline -void throwSysError(NSException* e) //throw SysError -{ - std::string msg; - if (const char* name = [[e name ] cStringUsingEncoding:NSUTF8StringEncoding]) //"const char*" NOT owned by us! - msg += name; - if (const char* descr = [[e reason] cStringUsingEncoding:NSUTF8StringEncoding]) - { - msg += "\n"; - msg += descr; - } - throw zen::SysError(zen::utfCvrtTo<std::wstring>(msg)); - /* - e.g. - NSInvalidArgumentException - *** +[NSString stringWithCString:encoding:]: NULL cString - */ -} -} - -#define ZEN_OSX_ASSERT_IMPL(obj, txt) if (!(obj)) throw zen::SysError(std::wstring(L"Assertion failed: \"") + L ## txt + L"\"."); - -#endif //OSX_EXCEPTION_89274305834255 diff --git a/zen/privilege.cpp b/zen/privilege.cpp deleted file mode 100644 index c2db4701..00000000 --- a/zen/privilege.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include "privilege.h" -#include <map> -//#include <mutex> -#include "win.h" //includes "windows.h" -#include "thread.h" -#include "zstring.h" -#include "scope_guard.h" -#include "win_ver.h" - -using namespace zen; - - -namespace -{ -bool privilegeIsActive(const wchar_t* privilege) //throw FileError -{ - HANDLE hToken = nullptr; - if (!::OpenProcessToken(::GetCurrentProcess(), //__in HANDLE ProcessHandle, - TOKEN_QUERY, //__in DWORD DesiredAccess, - &hToken)) //__out PHANDLE TokenHandle - throwFileError(replaceCpy(_("Cannot set privilege %x."), L"%x", std::wstring(L"\"") + privilege + L"\""), L"OpenProcessToken", getLastError()); - ZEN_ON_SCOPE_EXIT(::CloseHandle(hToken)); - - LUID luid = {}; - if (!::LookupPrivilegeValue(nullptr, //__in_opt LPCTSTR lpSystemName, - privilege, //__in LPCTSTR lpName, - &luid )) //__out PLUID lpLuid - throwFileError(replaceCpy(_("Cannot set privilege %x."), L"%x", std::wstring(L"\"") + privilege + L"\""), L"LookupPrivilegeValue", getLastError()); - - PRIVILEGE_SET priv = {}; - priv.PrivilegeCount = 1; - priv.Control = PRIVILEGE_SET_ALL_NECESSARY; - priv.Privilege[0].Luid = luid; - priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; - - BOOL alreadyGranted = FALSE; - if (!::PrivilegeCheck(hToken, //__in HANDLE ClientToken, - &priv, //__inout PPRIVILEGE_SET RequiredPrivileges, - &alreadyGranted)) //__out LPBOOL pfResult - throwFileError(replaceCpy(_("Cannot set privilege %x."), L"%x", std::wstring(L"\"") + privilege + L"\""), L"PrivilegeCheck", getLastError()); - - return alreadyGranted != FALSE; -} - - -void setPrivilege(const wchar_t* privilege, bool enable) //throw FileError -{ - HANDLE hToken = nullptr; - if (!::OpenProcessToken(::GetCurrentProcess(), //__in HANDLE ProcessHandle, - TOKEN_ADJUST_PRIVILEGES, //__in DWORD DesiredAccess, - &hToken)) //__out PHANDLE TokenHandle - throwFileError(replaceCpy(_("Cannot set privilege %x."), L"%x", std::wstring(L"\"") + privilege + L"\""), L"OpenProcessToken", getLastError()); - ZEN_ON_SCOPE_EXIT(::CloseHandle(hToken)); - - LUID luid = {}; - if (!::LookupPrivilegeValue(nullptr, //__in_opt LPCTSTR lpSystemName, - privilege, //__in LPCTSTR lpName, - &luid )) //__out PLUID lpLuid - throwFileError(replaceCpy(_("Cannot set privilege %x."), L"%x", std::wstring(L"\"") + privilege + L"\""), L"LookupPrivilegeValue", getLastError()); - - TOKEN_PRIVILEGES tp = {}; - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; - - if (!::AdjustTokenPrivileges(hToken, //__in HANDLE TokenHandle, - false, //__in BOOL DisableAllPrivileges, - &tp, //__in_opt PTOKEN_PRIVILEGES NewState, - 0, //__in DWORD BufferLength, - nullptr, //__out_opt PTOKEN_PRIVILEGES PreviousState, - nullptr)) //__out_opt PDWORD ReturnLength - throwFileError(replaceCpy(_("Cannot set privilege %x."), L"%x", std::wstring(L"\"") + privilege + L"\""), L"AdjustTokenPrivileges", getLastError()); - - DWORD lastError = ::GetLastError(); //copy before directly or indirectly making other system calls! - if (lastError == ERROR_NOT_ALL_ASSIGNED) //check although previous function returned with success! - { -#ifdef __MINGW32__ //Shobjidl.h -#define ERROR_ELEVATION_REQUIRED 740L -#endif - if (vistaOrLater()) //replace this useless error code with what it *really* means! - lastError = ERROR_ELEVATION_REQUIRED; - - throwFileError(replaceCpy(_("Cannot set privilege %x."), L"%x", std::wstring(L"\"") + privilege + L"\""), L"AdjustTokenPrivileges", lastError); - } -} - - -class Privileges -{ -public: - static Privileges& getInstance() - { - //meyers singleton: avoid static initialization order problem in global namespace! - static Privileges inst; - return inst; - } - - void ensureActive(const wchar_t* privilege) //throw FileError - { - boost::lock_guard<boost::mutex> dummy(lockPrivileges); - - if (activePrivileges.find(privilege) != activePrivileges.end()) - return; //privilege already active - - if (privilegeIsActive(privilege)) //privilege was already active before starting this tool - activePrivileges.insert(std::make_pair(privilege, false)); - else - { - setPrivilege(privilege, true); - activePrivileges.insert(std::make_pair(privilege, true)); - } - } - -private: - Privileges() {} - Privileges (const Privileges&) = delete; - Privileges& operator=(const Privileges&) = delete; - - ~Privileges() //clean up: deactivate all privileges that have been activated by this application - { - for (const auto& priv : activePrivileges) - if (priv.second) - { - try - { - setPrivilege(priv.first.c_str(), false); //throw FileError - } - catch (FileError&) {} - } - } - - std::map<Zstring, bool> activePrivileges; //bool: enabled by this application -boost::mutex lockPrivileges; -}; - -//caveat: function scope static initialization is not thread-safe in VS 2010! -auto& dummy = Privileges::getInstance(); -} - - -void zen::activatePrivilege(const wchar_t* privilege) //throw FileError -{ - Privileges::getInstance().ensureActive(privilege); -} diff --git a/zen/privilege.h b/zen/privilege.h deleted file mode 100644 index e9b83be9..00000000 --- a/zen/privilege.h +++ /dev/null @@ -1,17 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef PRIVILEGE_H_INCLUDED -#define PRIVILEGE_H_INCLUDED - -#include "file_error.h" - -namespace zen -{ -void activatePrivilege(const wchar_t* privilege); //throw FileError; thread-safe!!! -} - -#endif // PRIVILEGE_H_INCLUDED diff --git a/zen/recycler.cpp b/zen/recycler.cpp index 930b05ac..5b5e44d4 100644 --- a/zen/recycler.cpp +++ b/zen/recycler.cpp @@ -5,12 +5,11 @@ // ************************************************************************** #include "recycler.h" -#include "file_handling.h" +#include "file_access.h" #ifdef ZEN_WIN #include "thread.h" #include "dll.h" -#include "assert_static.h" #include "win_ver.h" #include "long_path_prefix.h" #include "IFileOperation/file_op.h" @@ -46,11 +45,10 @@ Nevertheless, let's use IFileOperation for better error reporting (including det struct CallbackData { CallbackData(const std::function<void (const Zstring& currentItem)>& notifyDeletionStatus) : - notifyDeletionStatus_(notifyDeletionStatus), - exceptionInUserCallback(false) {} + notifyDeletionStatus_(notifyDeletionStatus) {} - const std::function<void (const Zstring& currentItem)>& notifyDeletionStatus_; //optional! - bool exceptionInUserCallback; + const std::function<void (const Zstring& currentItem)>& notifyDeletionStatus_; //in, optional + std::exception_ptr exception; //out }; @@ -65,7 +63,7 @@ bool onRecyclerCallback(const wchar_t* itempath, void* sink) } catch (...) { - cbd.exceptionInUserCallback = true; //try again outside the C call stack! + cbd.exception = std::current_exception(); return false; } return true; @@ -85,8 +83,8 @@ void zen::recycleOrDelete(const std::vector<Zstring>& itempaths, const std::func if (vistaOrLater()) //new recycle bin usage: available since Vista { #define DEF_DLL_FUN(name) const DllFun<fileop::FunType_##name> name(fileop::getDllName(), fileop::funName_##name); -DEF_DLL_FUN(moveToRecycleBin); -DEF_DLL_FUN(getLastErrorMessage); + DEF_DLL_FUN(moveToRecycleBin); + DEF_DLL_FUN(getLastErrorMessage); #undef DEF_DLL_FUN if (!moveToRecycleBin || !getLastErrorMessage) @@ -100,12 +98,8 @@ DEF_DLL_FUN(getLastErrorMessage); CallbackData cbd(notifyDeletionStatus); if (!moveToRecycleBin(&cNames[0], cNames.size(), onRecyclerCallback, &cbd)) { - if (cbd.exceptionInUserCallback) - { - assert(notifyDeletionStatus); - notifyDeletionStatus(Zstring()); //should throw again!!! - assert(false); - } + if (cbd.exception) + std::rethrow_exception(cbd.exception); std::wstring itempathFmt = fmtFileName(itempaths[0]); //probably not the correct file name for file lists larger than 1! if (itempaths.size() > 1) @@ -188,7 +182,7 @@ bool zen::recycleOrDelete(const Zstring& itempath) //throw FileError #elif defined ZEN_MAC //we cannot use FSPathMoveObjectToTrashSync directly since it follows symlinks! - assert_static(sizeof(Zchar) == sizeof(char)); + static_assert(sizeof(Zchar) == sizeof(char), ""); const UInt8* itempathUtf8 = reinterpret_cast<const UInt8*>(itempath.c_str()); auto throwFileError = [&](OSStatus oss) diff --git a/zen/recycler.h b/zen/recycler.h index e900dfa3..b406408f 100644 --- a/zen/recycler.h +++ b/zen/recycler.h @@ -39,7 +39,6 @@ bool recycleOrDelete(const Zstring& itempath); //throw FileError, return "true" bool recycleBinExists(const Zstring& pathName, const std::function<void ()>& onUpdateGui); //throw FileError void recycleOrDelete(const std::vector<Zstring>& filepaths, //throw FileError, return "true" if file/dir was actually deleted - //may throw: first exception is swallowed, updateStatus() is then called again where it should throw again and the exception will propagate as expected const std::function<void (const Zstring& currentItem)>& notifyDeletionStatus); //optional; currentItem may be empty #endif } diff --git a/zen/scope_guard.h b/zen/scope_guard.h index d48eb922..761c6aea 100644 --- a/zen/scope_guard.h +++ b/zen/scope_guard.h @@ -40,8 +40,8 @@ protected: bool isDismissed() const { return dismissed_; } private: - ScopeGuardBase (const ScopeGuardBase&); // = delete - ScopeGuardBase& operator=(const ScopeGuardBase&); // + ScopeGuardBase (const ScopeGuardBase&) = delete; + ScopeGuardBase& operator=(const ScopeGuardBase&) = delete; bool dismissed_; }; @@ -52,7 +52,7 @@ class ScopeGuardImpl : public ScopeGuardBase { public: explicit ScopeGuardImpl(const F& fun) : fun_(fun) {} - explicit ScopeGuardImpl(F&& fun) : fun_(std::move(fun)) {} + explicit ScopeGuardImpl( F&& fun) : fun_(std::move(fun)) {} ScopeGuardImpl(ScopeGuardImpl&& other) : ScopeGuardBase(std::move(other)), fun_(std::move(other.fun_)) {} ~ScopeGuardImpl() diff --git a/zen/serialize.h b/zen/serialize.h index 64df0329..cd427c9c 100644 --- a/zen/serialize.h +++ b/zen/serialize.h @@ -7,6 +7,7 @@ #ifndef SERIALIZE_H_INCLUDED_83940578357 #define SERIALIZE_H_INCLUDED_83940578357 +#include <functional> #include <cstdint> #include "string_base.h" #include "file_io.h" @@ -54,8 +55,8 @@ private: //---------------------------------------------------------------------- //functions based on binary container abstraction -template <class BinContainer> void saveBinStream(const Zstring& filepath, const BinContainer& cont); //throw FileError -template <class BinContainer> BinContainer loadBinStream(const Zstring& filepath); //throw FileError +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 /* @@ -135,20 +136,38 @@ template < class BinInputStream> void readArray (BinInputStream& stre //-----------------------implementation------------------------------- template <class BinContainer> inline -void saveBinStream(const Zstring& filepath, const BinContainer& cont) //throw FileError +void saveBinStream(const Zstring& filepath, //throw FileError + const BinContainer& cont, + const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus) //optional { - assert_static(sizeof(typename BinContainer::value_type) == 1); //expect: bytes (until further) + static_assert(sizeof(typename BinContainer::value_type) == 1, ""); //expect: bytes (until further) FileOutput fileOut(filepath, zen::FileOutput::ACC_OVERWRITE); //throw FileError if (!cont.empty()) - fileOut.write(&*cont.begin(), cont.size()); //throw FileError + { + const size_t blockSize = 128 * 1024; + auto bytePtr = &*cont.begin(); + size_t bytesLeft = cont.size(); + + while (bytesLeft > blockSize) + { + fileOut.write(bytePtr, blockSize); //throw FileError + bytePtr += blockSize; + bytesLeft -= blockSize; + if (onUpdateStatus) onUpdateStatus(blockSize); + } + + fileOut.write(bytePtr, bytesLeft); //throw FileError + if (onUpdateStatus) onUpdateStatus(bytesLeft); + } } template <class BinContainer> inline -BinContainer loadBinStream(const Zstring& filepath) //throw FileError +BinContainer loadBinStream(const Zstring& filepath, //throw FileError + const std::function<void(std::int64_t bytesDelta)>& onUpdateStatus) //optional { - assert_static(sizeof(typename BinContainer::value_type) == 1); //expect: bytes (until further) + static_assert(sizeof(typename BinContainer::value_type) == 1, ""); //expect: bytes (until further) FileInput fileIn(filepath); //throw FileError @@ -161,6 +180,8 @@ BinContainer loadBinStream(const Zstring& filepath) //throw FileError const size_t bytesRead = fileIn.read(&*contOut.begin() + contOut.size() - blockSize, blockSize); //throw FileError if (bytesRead < blockSize) contOut.resize(contOut.size() - (blockSize - bytesRead)); //caveat: unsigned arithmetics + + if (onUpdateStatus) onUpdateStatus(bytesRead); } while (!fileIn.eof()); @@ -180,7 +201,7 @@ void writeArray(BinOutputStream& stream, const void* data, size_t len) template <class N, class BinOutputStream> inline void writeNumber(BinOutputStream& stream, const N& num) { - assert_static((IsArithmetic<N>::value || IsSameType<N, bool>::value)); + static_assert(IsArithmetic<N>::value || IsSameType<N, bool>::value, ""); writeArray(stream, &num, sizeof(N)); } @@ -198,7 +219,7 @@ 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 { - //expect external write of len bytes: + //expect external write of len bytes: const char* const src = static_cast<const char*>(stream.requestRead(len)); //throw UnexpectedEndOfStreamError std::copy(src, src + len, static_cast<char*>(data)); } @@ -207,7 +228,7 @@ void readArray(BinInputStream& stream, void* data, size_t len) //throw Unexpecte template <class N, class BinInputStream> inline N readNumber(BinInputStream& stream) //throw UnexpectedEndOfStreamError { - assert_static((IsArithmetic<N>::value || IsSameType<N, bool>::value)); + static_assert(IsArithmetic<N>::value || IsSameType<N, bool>::value, ""); N num = 0; readArray(stream, &num, sizeof(N)); //throw UnexpectedEndOfStreamError return num; @@ -219,8 +240,8 @@ C readContainer(BinInputStream& stream) //throw UnexpectedEndOfStreamError { C cont; auto strLength = readNumber<std::uint32_t>(stream); - if (strLength > 0) - { + if (strLength > 0) + { try { cont.resize(strLength); //throw std::bad_alloc @@ -229,8 +250,8 @@ C readContainer(BinInputStream& stream) //throw UnexpectedEndOfStreamError { throw UnexpectedEndOfStreamError(); } - readArray(stream, &*cont.begin(), sizeof(typename C::value_type) * strLength); //throw UnexpectedEndOfStreamError - } + readArray(stream, &*cont.begin(), sizeof(typename C::value_type) * strLength); //throw UnexpectedEndOfStreamError + } return cont; } } diff --git a/zen/shell_execute.h b/zen/shell_execute.h index 9f99315a..c2ccd837 100644 --- a/zen/shell_execute.h +++ b/zen/shell_execute.h @@ -31,7 +31,7 @@ enum ExecutionType namespace { -void shellExecute2(const Zstring& command, ExecutionType type) //throw FileError +void shellExecute(const Zstring& command, ExecutionType type) //throw FileError { #ifdef ZEN_WIN //parse commandline diff --git a/zen/stl_tools.h b/zen/stl_tools.h index 38752e67..eb94b4a1 100644 --- a/zen/stl_tools.h +++ b/zen/stl_tools.h @@ -9,13 +9,6 @@ #include <memory> #include <algorithm> -#if defined _MSC_VER && _MSC_VER <= 1600 -#include <set> -#include <map> -#else -#include <unordered_set> -#include <unordered_map> -#endif //enhancements for <algorithm> @@ -38,8 +31,8 @@ template <class M, class K, class V> V& map_add_or_update(M& map, const K& key, const V& value); //efficient add or update without "default-constructible" requirement (Effective STL, item 24) //binary search returning an iterator -template <class ForwardIterator, class T, typename Compare> -ForwardIterator binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); +template <class ForwardIterator, class T, typename CompLess> +ForwardIterator binary_search(ForwardIterator first, ForwardIterator last, const T& value, CompLess less); template <class BidirectionalIterator, class T> BidirectionalIterator find_last(BidirectionalIterator first, BidirectionalIterator last, const T& value); @@ -53,26 +46,9 @@ template <class InputIterator1, class InputIterator2> bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); -//hash container: proper name + mitigate MSVC performance bug -template <class T> class hash_set; -template <class K, class V> class hash_map; - -template<typename T, typename Arg1> -std::unique_ptr<T> make_unique(Arg1&& arg1); //should eventually make it into the std at some time - - - - - - - - - - - - - - +//until std::make_unique is available in GCC: +template <class T, class... Args> inline +std::unique_ptr<T> make_unique(Args&& ... args) { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); } @@ -127,11 +103,11 @@ V& map_add_or_update(M& map, const K& key, const V& value) //efficient add or up } -template <class ForwardIterator, class T, typename Compare> inline -ForwardIterator binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) +template <class ForwardIterator, class T, typename CompLess> inline +ForwardIterator binary_search(ForwardIterator first, ForwardIterator last, const T& value, CompLess less) { - first = std::lower_bound(first, last, value, comp); - if (first != last && !comp(value, *first)) + first = std::lower_bound(first, last, value, less); + if (first != last && !less(value, *first)) return first; else return last; @@ -187,32 +163,10 @@ bool equal(InputIterator1 first1, InputIterator1 last1, } -#if defined _MSC_VER && _MSC_VER <= 1600 //VS2010 performance bug in std::unordered_set<>: http://drdobbs.com/blogs/cpp/232200410 -> should be fixed in VS11 -template <class T> class hash_set : public std::set<T> {}; -template <class K, class V> class hash_map : public std::map<K, V> {}; -#else -template <class T> class hash_set : public std::unordered_set<T> {}; -template <class K, class V> class hash_map : public std::unordered_map<K, V> {}; -//C++11: -//template <class T> using hash_set = std::unordered_set<T>; -//template <class K, class V> using hash_map = std::unordered_map<K, V>; +#if defined _MSC_VER && _MSC_VER <= 1600 +//VS2010 performance bug in std::unordered_set<>: http://drdobbs.com/blogs/cpp/232200410 -> should be fixed in VS11 +static_assert(false, ""); #endif - -//as long as variadic templates are not available in MSVC -template<class T> inline std::unique_ptr<T> make_unique() { return std::unique_ptr<T>(new T); } -template<class T, class Arg1> inline std::unique_ptr<T> make_unique(Arg1&& arg1) { return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1))); } -template<class T, class Arg1, class Arg2> inline std::unique_ptr<T> make_unique(Arg1&& arg1, Arg2&& arg2) { return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2))); } -template<class T, class Arg1, class Arg2, class Arg3> inline std::unique_ptr<T> make_unique(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3) { return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3))); } -template<class T, class Arg1, class Arg2, class Arg3, class Arg4> inline std::unique_ptr<T> make_unique(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4) { return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4))); } -template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5> inline std::unique_ptr<T> make_unique(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4, Arg5&& arg5) { return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), std::forward<Arg5>(arg5))); } -template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6> inline std::unique_ptr<T> make_unique(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4, Arg5&& arg5, Arg6&& arg6) { return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), std::forward<Arg5>(arg5), std::forward<Arg6>(arg6))); } -template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7> inline std::unique_ptr<T> make_unique(Arg1&& arg1, Arg2&& arg2, Arg3&& arg3, Arg4&& arg4, Arg5&& arg5, Arg6&& arg6, Arg7&& arg7) { return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), std::forward<Arg7>(arg7))); } - -//template<typename T, typename ...Args> inline -//std::unique_ptr<T> make_unique(Args&& ...args) -//{ -// return std::unique_ptr<T>(new T( std::forward<Args>(args)... )); -//} } #endif //STL_TOOLS_HEADER_84567184321434 diff --git a/zen/string_base.h b/zen/string_base.h index a458ef15..0f9ad479 100644 --- a/zen/string_base.h +++ b/zen/string_base.h @@ -21,7 +21,7 @@ namespace zen Allocator Policy: ----------------- void* allocate(size_t size) //throw std::bad_alloc - void deallocate(void* ptr) //must handle deallocate(nullptr)! + void deallocate(void* ptr) size_t calcCapacity(size_t length) */ class AllocatorOptimalSpeed //exponential growth + min size @@ -53,7 +53,7 @@ template <typename Char, //Character Type Char* create(size_t size) Char* create(size_t size, size_t minCapacity) Char* clone(Char* ptr) - void destroy(Char* ptr) //must handle destroy(nullptr)! + void destroy(Char* ptr) //must handle "destroy(nullptr)"! bool canWrite(const Char* ptr, size_t minCapacity) //needs to be checked before writing to "ptr" size_t length(const Char* ptr) void setLength(Char* ptr, size_t newLength) @@ -66,29 +66,34 @@ class StorageDeepCopy : public AP protected: ~StorageDeepCopy() {} - static Char* create(size_t size) { return create(size, size); } - static Char* create(size_t size, size_t minCapacity) + Char* create(size_t size) { return create(size, size); } + Char* create(size_t size, size_t minCapacity) { assert(size <= minCapacity); const size_t newCapacity = AP::calcCapacity(minCapacity); assert(newCapacity >= minCapacity); - Descriptor* const newDescr = static_cast<Descriptor*>(AP::allocate(sizeof(Descriptor) + (newCapacity + 1) * sizeof(Char))); - - newDescr->length = size; - newDescr->capacity = newCapacity; + Descriptor* const newDescr = static_cast<Descriptor*>(this->allocate(sizeof(Descriptor) + (newCapacity + 1) * sizeof(Char))); //throw std::bad_alloc + new (newDescr) Descriptor(size, newCapacity); return reinterpret_cast<Char*>(newDescr + 1); //alignment note: "newDescr + 1" is Descriptor-aligned, which is larger than alignment for Char-array! => no problem! } - static Char* clone(Char* ptr) + Char* clone(Char* ptr) { - Char* newData = create(length(ptr)); + Char* newData = create(length(ptr)); //throw std::bad_alloc std::copy(ptr, ptr + length(ptr) + 1, newData); return newData; } - static void destroy(Char* ptr) { AP::deallocate(descr(ptr)); } //should support destroy(nullptr)! + void destroy(Char* ptr) + { + if (!ptr) return; //support "destroy(nullptr)" + + Descriptor* const d = descr(ptr); + d->~Descriptor(); + this->deallocate(d); + } //this needs to be checked before writing to "ptr" static bool canWrite(const Char* ptr, size_t minCapacity) { return minCapacity <= descr(ptr)->capacity; } @@ -103,6 +108,10 @@ protected: private: struct Descriptor { + Descriptor(size_t len, size_t cap) : + length (static_cast<std::uint32_t>(len)), + capacity(static_cast<std::uint32_t>(cap)) {} + std::uint32_t length; std::uint32_t capacity; //allocated size without null-termination }; @@ -119,42 +128,44 @@ class StorageRefCountThreadSafe : public AP protected: ~StorageRefCountThreadSafe() {} - static Char* create(size_t size) { return create(size, size); } - static Char* create(size_t size, size_t minCapacity) + Char* create(size_t size) { return create(size, size); } + Char* create(size_t size, size_t minCapacity) { assert(size <= minCapacity); const size_t newCapacity = AP::calcCapacity(minCapacity); assert(newCapacity >= minCapacity); - Descriptor* const newDescr = static_cast<Descriptor*>(AP::allocate(sizeof(Descriptor) + (newCapacity + 1) * sizeof(Char))); - new (newDescr) Descriptor(1, size, newCapacity); + Descriptor* const newDescr = static_cast<Descriptor*>(this->allocate(sizeof(Descriptor) + (newCapacity + 1) * sizeof(Char))); //throw std::bad_alloc + new (newDescr) Descriptor(size, newCapacity); return reinterpret_cast<Char*>(newDescr + 1); } static Char* clone(Char* ptr) { - assert(descr(ptr)->refCount > 0); ++descr(ptr)->refCount; return ptr; } - static void destroy(Char* ptr) + void destroy(Char* ptr) { - if (!ptr) return; //support destroy(nullptr) - assert(descr(ptr)->refCount > 0); - if (--descr(ptr)->refCount == 0) //operator--() is overloaded to decrement and evaluate in a single atomic operation! + if (!ptr) return; //support "destroy(nullptr)" + + Descriptor* const d = descr(ptr); + + if (--(d->refCount) == 0) //operator--() is overloaded to decrement and evaluate in a single atomic operation! { - descr(ptr)->~Descriptor(); - AP::deallocate(descr(ptr)); + d->~Descriptor(); + this->deallocate(d); } } static bool canWrite(const Char* ptr, size_t minCapacity) //needs to be checked before writing to "ptr" { - assert(descr(ptr)->refCount > 0); - return descr(ptr)->refCount == 1 && minCapacity <= descr(ptr)->capacity; + const Descriptor* const d = descr(ptr); + assert(d->refCount > 0); + return d->refCount == 1 && minCapacity <= d->capacity; } static size_t length(const Char* ptr) { return descr(ptr)->length; } @@ -168,14 +179,14 @@ protected: private: struct Descriptor { - Descriptor(int rc, size_t len, size_t cap) : + Descriptor(size_t len, size_t cap) : + refCount(1), length (static_cast<std::uint32_t>(len)), - capacity(static_cast<std::uint32_t>(cap)), - refCount(rc) { assert_static(ATOMIC_INT_LOCK_FREE == 2); } //2: "the types are always lock-free" + capacity(static_cast<std::uint32_t>(cap)) { static_assert(ATOMIC_INT_LOCK_FREE == 2, ""); } //2: "the types are always lock-free" + std::atomic<unsigned int> refCount; std::uint32_t length; std::uint32_t capacity; //allocated size without null-termination - std::atomic<int> refCount; //practically no perf loss: ~0.2%! (FFS comparison) }; static Descriptor* descr( Char* ptr) { return reinterpret_cast< Descriptor*>(ptr) - 1; } @@ -237,7 +248,7 @@ public: Zbase& assign(const Char* source, size_t len); Zbase& append(const Char* source, size_t len); void resize(size_t newSize, Char fillChar = 0); - void swap(Zbase& other); + void swap(Zbase& other); //make noexcept in C++11 void push_back(Char val) { operator+=(val); } //STL access Zbase& operator=(const Zbase& source); @@ -251,10 +262,10 @@ public: static const size_t npos = static_cast<size_t>(-1); private: - Zbase(int); // - Zbase& operator=(int); //detect usage errors by creating an intentional ambiguity with "Char" - Zbase& operator+=(int); // - void push_back(int); // + Zbase (int) = delete; // + Zbase& operator= (int) = delete; //detect usage errors by creating an intentional ambiguity with "Char" + Zbase& operator+=(int) = delete; // + void push_back (int) = delete; // Char* rawStr; }; @@ -626,8 +637,7 @@ Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator=(const Zbase<Char, SP, AP>& o template <class Char, template <class, class> class SP, class AP> inline Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator=(Zbase<Char, SP, AP>&& tmp) { - //don't use unifying assignment but save one move-construction in the r-value case instead! - swap(tmp); + swap(tmp); //don't use unifying assignment but save one move-construction in the r-value case instead! return *this; } diff --git a/zen/string_tools.h b/zen/string_tools.h index a0b02d14..addf2bd5 100644 --- a/zen/string_tools.h +++ b/zen/string_tools.h @@ -82,7 +82,7 @@ bool isWhiteSpace(wchar_t ch) { return std::iswspace(ch) != 0; } template <class Char> inline bool isDigit(Char ch) //similar to implmenetation of std::::isdigit()! { - assert_static((IsSameType<Char, char>::value || IsSameType<Char, wchar_t>::value)); + static_assert(IsSameType<Char, char>::value || IsSameType<Char, wchar_t>::value, ""); return static_cast<Char>('0') <= ch && ch <= static_cast<Char>('9'); } @@ -90,7 +90,7 @@ bool isDigit(Char ch) //similar to implmenetation of std::::isdigit()! template <class S, class T> inline bool startsWith(const S& str, const T& prefix) { - assert_static(IsStringLike<S>::value && IsStringLike<T>::value); + static_assert(IsStringLike<S>::value && IsStringLike<T>::value, ""); typedef typename GetCharType<S>::Type CharType; const size_t pfLength = strLength(prefix); @@ -106,7 +106,7 @@ bool startsWith(const S& str, const T& prefix) template <class S, class T> inline bool endsWith(const S& str, const T& postfix) { - assert_static(IsStringLike<S>::value && IsStringLike<T>::value); + static_assert(IsStringLike<S>::value && IsStringLike<T>::value, ""); typedef typename GetCharType<S>::Type CharType; const size_t strLen = strLength(str); @@ -123,7 +123,7 @@ bool endsWith(const S& str, const T& postfix) template <class S, class T> inline bool contains(const S& str, const T& term) { - assert_static(IsStringLike<S>::value && IsStringLike<T>::value); + static_assert(IsStringLike<S>::value && IsStringLike<T>::value, ""); typedef typename GetCharType<S>::Type CharType; const size_t strLen = strLength(str); @@ -144,7 +144,7 @@ bool contains(const S& str, const T& term) template <class S, class T> inline S afterLast(const S& str, const T& term) { - assert_static(IsStringLike<T>::value); + static_assert(IsStringLike<T>::value, ""); typedef typename GetCharType<S>::Type CharType; const size_t termLen = strLength(term); @@ -167,7 +167,7 @@ S afterLast(const S& str, const T& term) template <class S, class T> inline S beforeLast(const S& str, const T& term) { - assert_static(IsStringLike<T>::value); + static_assert(IsStringLike<T>::value, ""); typedef typename GetCharType<S>::Type CharType; const CharType* const strFirst = strBegin(str); @@ -187,7 +187,7 @@ S beforeLast(const S& str, const T& term) template <class S, class T> inline S afterFirst(const S& str, const T& term) { - assert_static(IsStringLike<T>::value); + static_assert(IsStringLike<T>::value, ""); typedef typename GetCharType<S>::Type CharType; const size_t termLen = strLength(term); @@ -209,7 +209,7 @@ S afterFirst(const S& str, const T& term) template <class S, class T> inline S beforeFirst(const S& str, const T& term) { - assert_static(IsStringLike<T>::value); + static_assert(IsStringLike<T>::value, ""); typedef typename GetCharType<S>::Type CharType; const CharType* const strFirst = strBegin(str); @@ -223,7 +223,7 @@ S beforeFirst(const S& str, const T& term) template <class S, class T> inline std::vector<S> split(const S& str, const T& delimiter) { - assert_static(IsStringLike<T>::value); + static_assert(IsStringLike<T>::value, ""); typedef typename GetCharType<S>::Type CharType; std::vector<S> output; @@ -245,7 +245,7 @@ std::vector<S> split(const S& str, const T& delimiter) const CharType* const blockEnd = std::search(blockStart, strLast, delimFirst, delimLast); - output.push_back(S(blockStart, blockEnd - blockStart)); + output.emplace_back(blockStart, blockEnd - blockStart); if (blockEnd == strLast) break; blockStart = blockEnd + delimLen; @@ -271,7 +271,7 @@ typename EnableIf<!HasMember_append<S>::value>::Type stringAppend(S& str, const template <class S, class T, class U> inline S replaceCpy(const S& str, const T& oldTerm, const U& newTerm, bool replaceAll) { - assert_static(IsStringLike<T>::value && IsStringLike<U>::value); + static_assert(IsStringLike<T>::value && IsStringLike<U>::value, ""); typedef typename GetCharType<S>::Type CharType; const size_t oldLen = strLength(oldTerm); @@ -395,10 +395,10 @@ int saferPrintf(wchar_t* buffer, size_t bufferSize, const wchar_t* format, const template <class S, class T, class Num> inline S printNumber(const T& format, const Num& number) //format a single number using ::sprintf { - assert_static(IsStringLike<T>::value); - assert_static((IsSameType< - typename GetCharType<S>::Type, - typename GetCharType<T>::Type>::value)); + static_assert(IsStringLike<T>::value, ""); + static_assert(IsSameType< + typename GetCharType<S>::Type, + typename GetCharType<T>::Type>::value, ""); typedef typename GetCharType<S>::Type CharType; diff --git a/zen/string_traits.h b/zen/string_traits.h index 69c1fbc8..ba97397c 100644 --- a/zen/string_traits.h +++ b/zen/string_traits.h @@ -8,8 +8,6 @@ #define STRING_TRAITS_HEADER_813274321443234 #include "type_tools.h" -#include "assert_static.h" - //uniform access to string-like types, both classes and character arrays namespace zen @@ -165,7 +163,11 @@ namespace implementation template <class C> inline size_t cStringLength(const C* str) //naive implementation seems somewhat faster than "optimized" strlen/wcslen! { - assert_static((IsSameType<C, char>::value || IsSameType<C, wchar_t>::value)); +#if defined _MSC_VER && _MSC_VER > 1800 + static_assert(false, "strlen/wcslen are vectorized in VS14 CTP3 -> test again!"); +#endif + + static_assert(IsSameType<C, char>::value || IsSameType<C, wchar_t>::value, ""); size_t len = 0; while (*str++ != 0) ++len; @@ -184,8 +186,8 @@ inline const char* strBegin(const char* str) { return str; } inline const wchar_t* strBegin(const wchar_t* str) { return str; } inline const char* strBegin(const char& ch) { return &ch; } inline const wchar_t* strBegin(const wchar_t& ch) { return &ch; } -inline const char* strBegin(const StringRef<char >& ref) { return ref.data(); } -inline const wchar_t* strBegin(const StringRef<wchar_t>& ref) { return ref.data(); } +inline const char* strBegin(const StringRef<char >& ref) { return ref.data(); } +inline const wchar_t* strBegin(const StringRef<wchar_t>& ref) { return ref.data(); } template <class S> inline diff --git a/zen/sys_error.h b/zen/sys_error.h index 8afab138..9cfc762f 100644 --- a/zen/sys_error.h +++ b/zen/sys_error.h @@ -35,7 +35,7 @@ typedef int ErrorCode; ErrorCode getLastError(); std::wstring formatSystemError(const std::wstring& functionName, ErrorCode lastError); - +std::wstring formatSystemError(const std::wstring& functionName, ErrorCode lastError, const std::wstring& lastErrorMsg); //A low-level exception class giving (non-translated) detail information only - same conceptional level like "GetLastError()"! class SysError @@ -75,11 +75,7 @@ std::wstring formatSystemError(const std::wstring& functionName, ErrorCode lastE { const ErrorCode currentError = getLastError(); //not necessarily == lastError - //determine error code if none was specified - if (lastError == 0) - lastError = currentError; - - std::wstring output = replaceCpy(_("Error Code %x:"), L"%x", numberTo<std::wstring>(lastError)); + std::wstring lastErrorMsg; #ifdef ZEN_WIN ZEN_ON_SCOPE_EXIT(::SetLastError(currentError)); //this function must not change active system error variable! @@ -92,22 +88,37 @@ std::wstring formatSystemError(const std::wstring& functionName, ErrorCode lastE if (buffer) //"don't trust nobody" { ZEN_ON_SCOPE_EXIT(::LocalFree(buffer)); - output += L" "; - output += buffer; + lastErrorMsg = buffer; } #elif defined ZEN_LINUX || defined ZEN_MAC ZEN_ON_SCOPE_EXIT(errno = currentError); - output += L" "; - output += utfCvrtTo<std::wstring>(::strerror(lastError)); + lastErrorMsg = utfCvrtTo<std::wstring>(::strerror(lastError)); #endif + + return formatSystemError(functionName, lastError, lastErrorMsg); +} + + +inline +std::wstring formatSystemError(const std::wstring& functionName, ErrorCode lastError, const std::wstring& lastErrorMsg) +{ + std::wstring output = replaceCpy(_("Error Code %x:"), L"%x", numberTo<std::wstring>(lastError)); + + if (!lastErrorMsg.empty()) + { + output += L" "; + output += lastErrorMsg; + } + if (!endsWith(output, L" ")) //Windows messages seem to end with a blank... output += L" "; output += L"(" + functionName + L")"; return output; } + } #endif //SYS_ERROR_H_3284791347018951324534 diff --git a/zen/thread.h b/zen/thread.h index 8c72e43f..a834f070 100644 --- a/zen/thread.h +++ b/zen/thread.h @@ -88,13 +88,15 @@ private: #error just some paranoia check... #endif -template <class T, class Function> inline -auto async2(Function fun) -> boost::unique_future<T> //support for workaround of VS2010 bug: bool (*fun)(); decltype(fun()) == int! +template <class Function> inline +auto async(Function fun) -> boost::unique_future<decltype(fun())> { + typedef decltype(fun()) ResultType; + #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK //mirror "boost/thread/future.hpp", hopefully they know what they're doing - boost::packaged_task<T()> pt(std::move(fun)); //packaged task seems to even require r-value reference: https://sourceforge.net/p/freefilesync/bugs/234/ + boost::packaged_task<ResultType()> pt(std::move(fun)); //packaged task seems to even require r-value reference: https://sourceforge.net/p/freefilesync/bugs/234/ #else - boost::packaged_task<T> pt(std::move(fun)); + boost::packaged_task<ResultType> pt(std::move(fun)); #endif auto fut = pt.get_future(); boost::thread(std::move(pt)).detach(); //we have to explicitly detach since C++11: [thread.thread.destr] ~thread() calls std::terminate() if joinable()!!! @@ -102,10 +104,6 @@ auto async2(Function fun) -> boost::unique_future<T> //support for workaround of } -template <class Function> inline -auto async(Function fun) -> boost::unique_future<decltype(fun())> { return async2<decltype(fun())>(fun); } - - template<class InputIterator, class Duration> inline bool wait_for_all_timed(InputIterator first, InputIterator last, const Duration& wait_duration) { diff --git a/zen/tick_count.h b/zen/tick_count.h index 482689d7..56179b62 100644 --- a/zen/tick_count.h +++ b/zen/tick_count.h @@ -64,9 +64,9 @@ public: #ifdef ZEN_WIN return numeric::dist(lhs.val_.QuadPart, rhs.val_.QuadPart); //std::abs(a - b) can lead to overflow! #elif defined ZEN_LINUX -//structure timespec documented with members: -// time_t tv_sec seconds -// long tv_nsec nanoseconds + //structure timespec documented with members: + // time_t tv_sec seconds + // long tv_nsec nanoseconds const int64_t deltaSec = lhs.val_.tv_sec - rhs.val_.tv_sec; const int64_t deltaNsec = lhs.val_.tv_nsec - rhs.val_.tv_nsec; return numeric::abs(deltaSec * 1000000000 + deltaNsec); @@ -113,9 +113,9 @@ int64_t ticksPerSec() //return 0 on error mach_timebase_info_data_t tbi = {}; if (::mach_timebase_info(&tbi) != KERN_SUCCESS) return 0; -//structure mach_timebase_info_data_t documented with members: -// uint32_t numer; -// uint32_t denom; + //structure mach_timebase_info_data_t documented with members: + // uint32_t numer; + // uint32_t denom; return static_cast<int64_t>(1000000000) * tbi.denom / tbi.numer; #endif } @@ -126,10 +126,10 @@ TickVal getTicks() //return !isValid() on error { #ifdef ZEN_WIN LARGE_INTEGER now = {}; - if (!::QueryPerformanceCounter(&now)) + if (!::QueryPerformanceCounter(&now)) return TickVal(); - //detailed info about QPC: http://msdn.microsoft.com/en-us/library/windows/desktop/dn553408%28v=vs.85%29.aspx - //- MSDN: "No need to set the thread affinity" + //detailed info about QPC: http://msdn.microsoft.com/en-us/library/windows/desktop/dn553408%28v=vs.85%29.aspx + //- MSDN: "No need to set the thread affinity" #elif defined ZEN_LINUX //gettimeofday() seems fine but is deprecated @@ -49,8 +49,8 @@ const struct FormatIsoDateTimeTag {} FORMAT_ISO_DATE_TIME = {}; //%Y-%m-%d %H:%M //---------------------------------------------------------------------------------------------------------------------------------- -template <class String> -bool parseTime(const String& format, const String& str, TimeComp& comp); //similar to ::strptime(), return true on success +template <class String, class String2> +bool parseTime(const String& format, const String2& str, TimeComp& comp); //similar to ::strptime(), return true on success //---------------------------------------------------------------------------------------------------------------------------------- @@ -272,10 +272,11 @@ String formatTime(const String2& format, const TimeComp& comp) } -template <class String> -bool parseTime(const String& format, const String& str, TimeComp& comp) //return true on success +template <class String, class String2> +bool parseTime(const String& format, const String2& str, TimeComp& comp) //return true on success { typedef typename GetCharType<String>::Type CharType; + static_assert(IsSameType<CharType, typename GetCharType<String2>::Type>::value, ""); const CharType* iterFmt = strBegin(format); const CharType* const fmtLast = iterFmt + strLength(format); @@ -285,7 +286,7 @@ bool parseTime(const String& format, const String& str, TimeComp& comp) //return auto extractNumber = [&](int& result, size_t digitCount) -> bool { - if (strLast - iterStr < digitCount) + if (strLast - iterStr < makeSigned(digitCount)) return false; if (std::any_of(iterStr, iterStr + digitCount, [](CharType c) { return !isDigit(c); })) @@ -104,7 +104,7 @@ size_t getUtf16Len(Char16 ch) //ch must be first code unit! returns 0 on error! template <class CharIterator, class Function> inline void utf16ToCodePoint(CharIterator first, CharIterator last, Function writeOutput) //"writeOutput" is a unary function taking a CodePoint { - assert_static(sizeof(typename std::iterator_traits<CharIterator>::value_type) == 2); + static_assert(sizeof(typename std::iterator_traits<CharIterator>::value_type) == 2, ""); for ( ; first != last; ++first) { @@ -201,7 +201,7 @@ bool decodeTrail(CharIterator& first, CharIterator last, CodePoint& cp) //decode template <class CharIterator, class Function> inline void utf8ToCodePoint(CharIterator first, CharIterator last, Function writeOutput) //"writeOutput" is a unary function taking a CodePoint { - assert_static(sizeof(typename std::iterator_traits<CharIterator>::value_type) == 1); + static_assert(sizeof(typename std::iterator_traits<CharIterator>::value_type) == 1, ""); for ( ; first != last; ++first) { @@ -337,12 +337,12 @@ size_t findUnicodePosWide(const WideString& str, size_t unicodePos, Int2Type<2>) if (utfPos >= strLen) return strLen; - size_t utf16len = getUtf16Len(strFirst[utfPos]); + size_t utf16len = getUtf16Len(strFirst[utfPos]); if (utf16len == 0) ++utf16len; //invalid utf16 character utfPos += utf16len; } - if (utfPos >= strLen) - return strLen; + if (utfPos >= strLen) + return strLen; return utfPos; } @@ -416,8 +416,8 @@ CharString wideToUtf8(const WideString& str, Int2Type<4>) //other OS: convert ut template <class WideString, class CharString> inline WideString utf8ToWide(const CharString& str) { - assert_static((IsSameType<typename GetCharType<CharString>::Type, char >::value)); - assert_static((IsSameType<typename GetCharType<WideString>::Type, wchar_t>::value)); + static_assert(IsSameType<typename GetCharType<CharString>::Type, char >::value, ""); + static_assert(IsSameType<typename GetCharType<WideString>::Type, wchar_t>::value, ""); return implementation::utf8ToWide<WideString>(str, Int2Type<sizeof(wchar_t)>()); } @@ -426,8 +426,8 @@ WideString utf8ToWide(const CharString& str) template <class CharString, class WideString> inline CharString wideToUtf8(const WideString& str) { - assert_static((IsSameType<typename GetCharType<CharString>::Type, char >::value)); - assert_static((IsSameType<typename GetCharType<WideString>::Type, wchar_t>::value)); + static_assert(IsSameType<typename GetCharType<CharString>::Type, char >::value, ""); + static_assert(IsSameType<typename GetCharType<WideString>::Type, wchar_t>::value, ""); return implementation::wideToUtf8<CharString>(str, Int2Type<sizeof(wchar_t)>()); } diff --git a/zen/win_ver.h b/zen/win_ver.h index 0d3f8d70..1d7ce7f0 100644 --- a/zen/win_ver.h +++ b/zen/win_ver.h @@ -7,24 +7,26 @@ #ifndef WINDOWS_VERSION_HEADER_238470348254325 #define WINDOWS_VERSION_HEADER_238470348254325 +#include <cassert> #include <utility> #include "win.h" //includes "windows.h" namespace zen { - struct OsVersion - { - OsVersion() : major(), minor() {} - OsVersion(DWORD high, DWORD low) : major(high), minor(low) {} +struct OsVersion +{ + OsVersion() : major(), minor() {} + OsVersion(DWORD high, DWORD low) : major(high), minor(low) {} - DWORD major; - DWORD minor; - }; - inline bool operator< (const OsVersion& lhs, const OsVersion& rhs) { return lhs.major != rhs.major ? lhs.major < rhs.major : lhs.minor < rhs.minor; } - inline bool operator==(const OsVersion& lhs, const OsVersion& rhs) { return lhs.major == rhs.major && lhs.minor == rhs.minor; } + DWORD major; + DWORD minor; +}; +inline bool operator< (const OsVersion& lhs, const OsVersion& rhs) { return lhs.major != rhs.major ? lhs.major < rhs.major : lhs.minor < rhs.minor; } +inline bool operator==(const OsVersion& lhs, const OsVersion& rhs) { return lhs.major == rhs.major && lhs.minor == rhs.minor; } //version overview: http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx +const OsVersion osVersionWin10 (6, 4); const OsVersion osVersionWin81 (6, 3); const OsVersion osVersionWin8 (6, 2); const OsVersion osVersionWin7 (6, 1); @@ -61,11 +63,18 @@ OsVersion getOsVersion() { OSVERSIONINFO osvi = {}; osvi.dwOSVersionInfoSize = sizeof(osvi); +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4996) //"'GetVersionExW': was declared deprecated" +#endif if (!::GetVersionEx(&osvi)) //38 ns per call! (yes, that's nano!) -> we do NOT miss C++11 thread-safe statics right now... - { - assert(false); - return OsVersion(); - } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + { + assert(false); + return OsVersion(); + } return OsVersion(osvi.dwMajorVersion, osvi.dwMinorVersion); } @@ -78,16 +87,16 @@ bool isRealOsVersion(const OsVersion& ver) verInfo.dwMajorVersion = ver.major; verInfo.dwMinorVersion = ver.minor; - //Syntax: http://msdn.microsoft.com/en-us/library/windows/desktop/ms725491%28v=vs.85%29.aspx + //Syntax: http://msdn.microsoft.com/en-us/library/windows/desktop/ms725491%28v=vs.85%29.aspx DWORDLONG conditionMask = 0; VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_EQUAL); VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_EQUAL); const bool rv = ::VerifyVersionInfo(&verInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask) - == TRUE; //silence VC "performance warnings" - assert(rv || GetLastError() == ERROR_OLD_WIN_VERSION); + == TRUE; //silence VC "performance warnings" + assert(rv || GetLastError() == ERROR_OLD_WIN_VERSION); - return rv; + return rv; } } diff --git a/zen/xml_io.cpp b/zen/xml_io.cpp index 485d78bb..9ac4b87f 100644 --- a/zen/xml_io.cpp +++ b/zen/xml_io.cpp @@ -5,7 +5,7 @@ // ************************************************************************** #include "xml_io.h" -#include "file_handling.h" +#include "file_access.h" #include "file_io.h" #include "serialize.h" @@ -66,7 +66,7 @@ void zen::saveXmlDocument(const XmlDoc& doc, const Zstring& filepath) //throw Fi try { if (getFilesize(filepath) == stream.size()) //throw FileError - if (loadBinStream<std::string>(filepath) == stream) //throw FileError + if (loadBinStream<std::string>(filepath, nullptr) == stream) //throw FileError return; } catch (FileError&) {} diff --git a/zen/zstring.cpp b/zen/zstring.cpp index f16af6a0..a2a26f83 100644 --- a/zen/zstring.cpp +++ b/zen/zstring.cpp @@ -6,6 +6,7 @@ #include "zstring.h" #include <stdexcept> +#include <unordered_map> #ifdef ZEN_WIN #include "dll.h" @@ -40,7 +41,7 @@ public: void insert(const void* ptr, size_t size) { boost::lock_guard<boost::mutex> dummy(lockActStrings); - if (!activeStrings.insert(std::make_pair(ptr, size)).second) + if (!activeStrings.emplace(ptr, size).second) reportProblem("Serious Error: New memory points into occupied space: " + rawMemToString(ptr, size)); } @@ -96,7 +97,7 @@ private: } boost::mutex lockActStrings; - zen::hash_map<const void*, size_t> activeStrings; + std::unordered_map<const void*, size_t> activeStrings; }; //caveat: function scope static initialization is not thread-safe in VS 2010! @@ -148,15 +149,15 @@ const SysDllFun<CompareStringOrdinalFunc> compareStringOrdinal = SysDllFun<Compa } -int z_impl::compareFilenamesNoCase(const wchar_t* lhs, const wchar_t* rhs, size_t sizeLhs, size_t sizeRhs) +int cmpFileName(const Zstring& lhs, const Zstring& rhs) { if (compareStringOrdinal) //this additional test has no noticeable performance impact { - const int rv = compareStringOrdinal(lhs, //__in LPCWSTR lpString1, - static_cast<int>(sizeLhs), //__in int cchCount1, - rhs, //__in LPCWSTR lpString2, - static_cast<int>(sizeRhs), //__in int cchCount2, - true); //__in BOOL bIgnoreCase + const int rv = compareStringOrdinal(lhs.c_str(), //__in LPCWSTR lpString1, + static_cast<int>(lhs.size()), //__in int cchCount1, + rhs.c_str(), //__in LPCWSTR lpString2, + static_cast<int>(rhs.size()), //__in int cchCount2, + true); //__in BOOL bIgnoreCase if (rv <= 0) throw std::runtime_error("Error comparing strings (CompareStringOrdinal)."); else @@ -167,31 +168,35 @@ int z_impl::compareFilenamesNoCase(const wchar_t* lhs, const wchar_t* rhs, size_ //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": - auto copyToUpperCase = [](const wchar_t* strIn, wchar_t* strOut, size_t len) + const size_t sizeLhs = lhs.size(); + const size_t sizeRhs = rhs.size(); + + const auto minSize = std::min(sizeLhs, sizeRhs); + + if (minSize == 0) //LCMapString does not allow input sizes of 0! + return static_cast<int>(sizeLhs) - static_cast<int>(sizeRhs); + + auto copyToUpperCase = [&](const wchar_t* strIn, wchar_t* strOut) { //faster than CharUpperBuff + wmemcpy or CharUpper + wmemcpy and same speed like ::CompareString() - if (::LCMapString(ZSTRING_INVARIANT_LOCALE, //__in LCID Locale, - LCMAP_UPPERCASE, //__in DWORD dwMapFlags, - strIn, //__in LPCTSTR lpSrcStr, - static_cast<int>(len), //__in int cchSrc, - strOut, //__out LPTSTR lpDestStr, - static_cast<int>(len)) == 0) //__in int cchDest + if (::LCMapString(ZSTRING_INVARIANT_LOCALE, //__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)."); }; - const auto minSize = std::min(sizeLhs, sizeRhs); - auto eval = [&](wchar_t* bufL, wchar_t* bufR) { - if (minSize > 0) //LCMapString does not allow input sizes of 0! - { - copyToUpperCase(lhs, bufL, minSize); - copyToUpperCase(rhs, bufR, minSize); - - const int rv = ::wmemcmp(bufL, bufR, minSize); - if (rv != 0) - return rv; - } + copyToUpperCase(lhs.c_str(), bufL); + copyToUpperCase(rhs.c_str(), bufR); + + const int rv = ::wmemcmp(bufL, bufR, minSize); + if (rv != 0) + return rv; + return static_cast<int>(sizeLhs) - static_cast<int>(sizeRhs); }; @@ -203,35 +208,55 @@ int z_impl::compareFilenamesNoCase(const wchar_t* lhs, const wchar_t* rhs, size_ } else //use freestore { - std::vector<wchar_t> bufferL(minSize); - std::vector<wchar_t> bufferR(minSize); - return eval(&bufferL[0], &bufferR[0]); + std::vector<wchar_t> buffer(2 * minSize); + return eval(&buffer[0], &buffer[minSize]); } } } -void z_impl::makeFilenameUpperCase(wchar_t* str, size_t size) +Zstring makeUpperCopy(const Zstring& str) { - if (size == 0) //LCMapString does not allow input sizes of 0! - return; + const int len = static_cast<int>(str.size()); + + if (len == 0) //LCMapString does not allow input sizes of 0! + return str; + + Zstring output; + output.resize(len); //use Windows' upper case conversion: faster than ::CharUpper() - if (::LCMapString(ZSTRING_INVARIANT_LOCALE, LCMAP_UPPERCASE, str, static_cast<int>(size), str, static_cast<int>(size)) == 0) - throw std::runtime_error("Error converting to upper case! (LCMapString)"); + if (::LCMapString(ZSTRING_INVARIANT_LOCALE, //__in LCID Locale, + LCMAP_UPPERCASE, //__in DWORD dwMapFlags, + str.c_str(), //__in LPCTSTR lpSrcStr, + len, //__in int cchSrc, + &*output.begin(), //__out LPTSTR lpDestStr, + len) == 0) //__in int cchDest + throw std::runtime_error("Error comparing strings (LCMapString)."); + + return output; } + #elif defined ZEN_MAC -int z_impl::compareFilenamesNoCase(const char* lhs, const char* rhs, size_t sizeLhs, size_t sizeRhs) +int cmpFileName(const Zstring& lhs, const Zstring& rhs) { - return ::strcasecmp(lhs, rhs); //locale-dependent! + return ::strcasecmp(lhs.c_str(), rhs.c_str()); //locale-dependent! } -void z_impl::makeFilenameUpperCase(char* str, size_t size) +Zstring makeUpperCopy(const Zstring& str) { - std::for_each(str, str + size, [](char& c) { c = static_cast<char>(::toupper(static_cast<unsigned char>(c))); }); //locale-dependent! + const size_t len = str.size(); + + Zstring output; + output.resize(len); + + std::transform(str.begin(), str.end(), output.begin(), [](char c) { return static_cast<char>(::toupper(static_cast<unsigned char>(c))); }); //locale-dependent! + //result of toupper() is an unsigned char mapped to int range, so the char representation is in the last 8 bits and we need not care about signedness! //this should work for UTF-8, too: all chars >= 128 are mapped upon themselves! + + return output; } #endif diff --git a/zen/zstring.h b/zen/zstring.h index 2152954d..94144386 100644 --- a/zen/zstring.h +++ b/zen/zstring.h @@ -4,8 +4,8 @@ // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** -#ifndef ZSTRING_H_INCLUDED -#define ZSTRING_H_INCLUDED +#ifndef ZSTRING_H_INCLUDED_73425873425789 +#define ZSTRING_H_INCLUDED_73425873425789 #include "string_base.h" @@ -66,30 +66,26 @@ typedef zen::Zbase<Zchar, zen::StorageRefCountThreadSafe, AllocatorFreeStoreChec //Compare filepaths: Windows does NOT distinguish between upper/lower-case, while Linux DOES -template <template <class, class> class SP, class AP> -int cmpFileName(const zen::Zbase<Zchar, SP, AP>& lhs, const zen::Zbase<Zchar, SP, AP>& rhs); +int cmpFileName(const Zstring& lhs, const Zstring& rhs); struct LessFilename //case-insensitive on Windows, case-sensitive on Linux { - template <template <class, class> class SP, class AP> - bool operator()(const zen::Zbase<Zchar, SP, AP>& lhs, const zen::Zbase<Zchar, SP, AP>& rhs) const { return cmpFileName(lhs, rhs) < 0; } + bool operator()(const Zstring& lhs, const Zstring& rhs) const { return cmpFileName(lhs, rhs) < 0; } }; struct EqualFilename //case-insensitive on Windows, case-sensitive on Linux { - template <template <class, class> class SP, class AP> - bool operator()(const zen::Zbase<Zchar, SP, AP>& lhs, const zen::Zbase<Zchar, SP, AP>& rhs) const { return cmpFileName(lhs, rhs) == 0; } + bool operator()(const Zstring& lhs, const Zstring& rhs) const { return cmpFileName(lhs, rhs) == 0; } }; #if defined ZEN_WIN || defined ZEN_MAC -template <template <class, class> class SP, class AP> -void makeUpper(zen::Zbase<Zchar, SP, AP>& str); +Zstring makeUpperCopy(const Zstring& str); #endif inline Zstring appendSeparator(Zstring path) //support rvalue references! { - return endsWith(path, FILE_NAME_SEPARATOR) ? path : (path += FILE_NAME_SEPARATOR); + return zen::endsWith(path, FILE_NAME_SEPARATOR) ? path : (path += FILE_NAME_SEPARATOR); } @@ -98,44 +94,13 @@ Zstring appendSeparator(Zstring path) //support rvalue references! //################################# inline implementation ######################################## -namespace z_impl -{ -#if defined ZEN_WIN || defined ZEN_MAC -int compareFilenamesNoCase(const Zchar* lhs, const Zchar* rhs, size_t sizeLhs, size_t sizeRhs); -void makeFilenameUpperCase(Zchar* str, size_t size); -#endif -} - -template <template <class, class> class SP, class AP> inline -int cmpFileName(const zen::Zbase<Zchar, SP, AP>& lhs, const zen::Zbase<Zchar, SP, AP>& rhs) +#ifdef ZEN_LINUX +inline +int cmpFileName(const Zstring& lhs, const Zstring& rhs) { -#if defined ZEN_WIN || defined ZEN_MAC - return z_impl::compareFilenamesNoCase(lhs.data(), rhs.data(), lhs.length(), rhs.length()); -#elif defined ZEN_LINUX return std::strcmp(lhs.c_str(), rhs.c_str()); //POSIX filepaths don't have embedded 0 - //#elif defined ZEN_MAC - // return ::strcasecmp(lhs.c_str(), rhs.c_str()); //locale-dependent! -#endif -} - - -#if defined ZEN_WIN || defined ZEN_MAC -template <template <class, class> class SP, class AP> inline -void makeUpper(zen::Zbase<Zchar, SP, AP>& str) -{ - z_impl::makeFilenameUpperCase(str.begin(), str.length()); } #endif - -namespace std -{ -template<> inline -void swap(Zstring& rhs, Zstring& lhs) -{ - rhs.swap(lhs); -} -} - -#endif //ZSTRING_H_INCLUDED +#endif //ZSTRING_H_INCLUDED_73425873425789 |