├── .gitignore ├── LICENSE ├── README.md ├── WpfDiff ├── WpfDiff.sln └── WpfDiff │ ├── App.config │ ├── App.xaml │ ├── App.xaml.cs │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── MainWindowModel.cs │ ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings │ ├── SideBySideDiffModelVisualizer.cs │ ├── ViewModel.cs │ └── WpfDiff.csproj └── screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Manuel Naujoks 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WpfDiff 2 | Highlight changes in text using DiffPlex (Apache 2.0) and WPF's RichTextBox. 3 | 4 | ![Screenshot](https://raw.githubusercontent.com/halllo/WpfDiff/master/screenshot.png) 5 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDiff", "WpfDiff\WpfDiff.csproj", "{141A6C3D-7631-4E5B-8D96-199955B50054}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {141A6C3D-7631-4E5B-8D96-199955B50054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {141A6C3D-7631-4E5B-8D96-199955B50054}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {141A6C3D-7631-4E5B-8D96-199955B50054}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {141A6C3D-7631-4E5B-8D96-199955B50054}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace WpfDiff 4 | { 5 | public partial class App : Application 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | 24 | 27 | 28 | 31 | 32 | 35 | 36 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using CommandContext; 2 | using System.Linq; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using System.Windows.Controls.Primitives; 6 | 7 | namespace WpfDiff 8 | { 9 | public partial class MainWindow : Window 10 | { 11 | public MainWindow() 12 | { 13 | InitializeComponent(); 14 | this.CommandContext(DataContext = new MainWindowModel()); 15 | } 16 | 17 | private void ScrollChanged(object sender, ScrollChangedEventArgs e) 18 | { 19 | var scrollViewerToUpdate = sender == this.beforeDiff ? new TextBoxBase[] { this.afterDiff, this.after, this.before } : 20 | sender == this.afterDiff ? new TextBoxBase[] { this.beforeDiff, this.after, this.before } : 21 | sender == this.before ? new TextBoxBase[] { this.beforeDiff, this.after, this.afterDiff } : 22 | sender == this.after ? new TextBoxBase[] { this.beforeDiff, this.afterDiff, this.before } : new TextBoxBase[0]; 23 | 24 | scrollViewerToUpdate.ToList().ForEach(textToSync => 25 | { 26 | textToSync.ScrollToVerticalOffset(e.VerticalOffset); 27 | textToSync.ScrollToHorizontalOffset(e.HorizontalOffset); 28 | }); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/MainWindowModel.cs: -------------------------------------------------------------------------------- 1 | using DiffPlex; 2 | using DiffPlex.DiffBuilder; 3 | using DiffPlex.DiffBuilder.Model; 4 | 5 | namespace WpfDiff 6 | { 7 | public class MainWindowModel : ViewModel 8 | { 9 | public MainWindowModel() 10 | { 11 | Vorher = Nachher = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed quis augue condimentum, pulvinar tellus vitae, tempor nisi. Donec id diam nec justo scelerisque pulvinar id ut orci. Curabitur a congue ligula. Proin orci ligula, facilisis vitae tempor ut, lobortis ac leo. Integer quis mollis enim, a suscipit justo. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse volutpat vestibulum venenatis. 12 | Proin euismod tortor ut pretium posuere. Sed ac orci eget leo pharetra mattis. Donec at augue turpis. Maecenas laoreet massa sit amet purus imperdiet accumsan. Proin quis ante aliquet, pretium turpis sit amet, luctus odio. Pellentesque ut tellus suscipit, interdum lacus cursus, fermentum dui. Nullam euismod molestie viverra. Aenean et luctus nibh, eget mollis risus. Vestibulum eu quam in neque dictum euismod. 13 | Vivamus ex turpis, aliquam sed porttitor volutpat, imperdiet nec tellus. Pellentesque a dolor eu dui dignissim vestibulum consectetur nec nisl. Donec a quam a leo mattis interdum. Mauris consectetur, turpis nec semper placerat, quam mi efficitur ligula, eget ornare turpis nisi vitae arcu. Fusce sit amet feugiat nisi. Mauris pharetra, libero a pulvinar egestas, diam lacus vestibulum sem, egestas sollicitudin nibh purus eu odio. Maecenas placerat, lacus sed pulvinar rhoncus, erat arcu eleifend mauris, sed fermentum ex massa ut orci. Nullam tempor vehicula orci, at cursus risus venenatis id. Nullam at est sed augue eleifend rutrum. In laoreet pretium est at rutrum. Aliquam elementum at justo consectetur elementum. Morbi sollicitudin eget ante sed viverra. Sed turpis ligula, sollicitudin sed tempus in, pulvinar vel orci. 14 | Vestibulum porttitor accumsan lacus, eu vehicula urna semper vitae. Quisque sed urna nunc. Maecenas ac pretium ipsum. Proin ornare magna a viverra cursus. Vivamus fringilla massa a justo auctor, eu sagittis enim imperdiet. Vestibulum egestas eros et efficitur posuere. Nam malesuada cursus sodales. Pellentesque aliquet metus odio, vitae cursus est aliquet eget. Vivamus in lectus at erat convallis condimentum at vitae diam. In hac habitasse platea dictumst. Proin viverra euismod elit, eu imperdiet augue vestibulum non. Morbi scelerisque aliquet erat, vitae sagittis mauris venenatis ac. Curabitur quis semper tortor. Proin massa lectus, viverra sed dui a, pharetra ullamcorper ex. Proin molestie diam ac lacus convallis vestibulum. 15 | Duis vel nunc quam. Donec aliquam, lorem in tempus placerat, ex est posuere mi, non scelerisque dui tortor molestie elit. Donec laoreet dolor ac mauris fermentum tincidunt. Nunc varius iaculis ligula, vel placerat arcu auctor eget. Sed vitae hendrerit felis. Suspendisse in lacus a massa tristique hendrerit. Aliquam non faucibus velit. Fusce in justo ac leo accumsan pretium et eget dui. Quisque a sapien ut massa vestibulum scelerisque. 16 | Duis dapibus eu odio pharetra consectetur. Donec facilisis purus nec posuere suscipit. Pellentesque vulputate elit ac nisi hendrerit eleifend. Morbi non rhoncus diam, nec tempus lacus. Cras vitae vestibulum quam. Nulla pretium enim sed velit fermentum, sit amet accumsan lectus porta. Duis auctor ultrices fringilla. Etiam eu tristique dolor, eget tristique odio. 17 | Nam convallis condimentum leo, nec elementum justo scelerisque et. In rhoncus tempor justo, id bibendum est. Proin lacinia luctus lectus et laoreet. Pellentesque nulla ipsum, porta non quam ut, porta semper metus. Pellentesque fringilla ante tellus, eget dictum quam luctus nec. Praesent consequat lacus nec libero congue, at condimentum metus efficitur. Proin a ligula molestie, sodales nunc at, vulputate elit. Duis nec blandit elit. 18 | Etiam vitae nisi semper, ullamcorper odio aliquam, facilisis leo. Vivamus at finibus lorem, quis vestibulum dolor. Suspendisse vitae erat vitae sem convallis consectetur. Cras sed massa bibendum sapien egestas viverra. Fusce gravida sed ipsum non lacinia. Curabitur ac urna lacus. Etiam eros nisl, finibus nec nibh sed, bibendum ultricies purus. Vivamus ac aliquam metus, lacinia mollis nunc. Sed eu mi sodales, condimentum ex non, vestibulum risus. Cras sed scelerisque dolor. Maecenas scelerisque sit amet lorem id placerat. Donec nec enim in ligula ullamcorper volutpat nec id mauris. Aenean vestibulum purus laoreet orci facilisis scelerisque. 19 | Maecenas facilisis dapibus ipsum sit amet porta. Maecenas nec dui sit amet dolor pretium luctus. Cras at mi eu purus laoreet pharetra eu in ligula. Nullam bibendum nisi nec nunc tincidunt faucibus. Aenean vulputate, nibh ac suscipit fringilla, velit ex consequat mi, at ornare leo orci eget nibh. Vivamus viverra, leo a lobortis mollis, felis magna sollicitudin lorem, eu interdum purus sem eu tellus. Proin ut sem laoreet, bibendum ex non, sagittis ligula. Ut convallis egestas turpis, quis tincidunt massa ultrices at. Ut ac ex mollis, tincidunt nulla vel, vehicula ipsum. Morbi et sagittis justo. Duis eget velit vel diam pharetra cursus vel non dui. Aliquam vel lorem ligula. Nam maximus, nisi eu sollicitudin consequat, diam purus condimentum tortor, nec egestas ex sem quis felis. Ut vulputate lorem odio, sed ultrices dolor iaculis at. 20 | Curabitur eleifend sapien sit amet rutrum facilisis. Fusce augue libero, egestas ac nisl in, sollicitudin rutrum magna. Maecenas feugiat ante ipsum, varius semper massa dapibus ac. Maecenas nec laoreet eros. Pellentesque sodales nisi sodales, lobortis magna ac, efficitur ligula. Quisque pellentesque sem id neque posuere tristique. Mauris id magna sit amet lacus molestie condimentum sit amet quis neque. Donec aliquet semper nisi, eu tempus ex faucibus ultrices. Nam id risus ex. Nam in aliquet eros. Quisque pellentesque mauris a ultrices cursus. Praesent nunc massa, tempor nec euismod quis, scelerisque vitae dolor. Ut luctus varius erat sit amet fermentum. Donec sagittis libero tortor, quis porttitor odio facilisis id. Curabitur enim ante, vehicula lacinia laoreet nec, vulputate id lectus. Proin tempus purus neque, at fermentum velit pulvinar sed. 21 | Vivamus ultricies ipsum a quam pretium, vel semper lacus consectetur. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis vitae erat in tellus elementum luctus. Mauris vel quam quis nisl aliquam pharetra a vel mauris. Fusce interdum lorem quis pellentesque condimentum. Sed iaculis justo id felis sodales, vitae euismod odio semper. Praesent malesuada luctus gravida. Praesent imperdiet libero sed velit tristique, sit amet aliquet leo egestas. Quisque vitae eleifend leo. Donec aliquam sagittis tellus, non tempus lacus tincidunt at. 22 | Phasellus tempus est maximus tristique posuere. Donec turpis lacus, lobortis nec egestas et, blandit eget nisl. Quisque iaculis nec lectus ac tempor. In hac habitasse platea dictumst. Phasellus et sollicitudin eros, sit amet tempor risus. Cras ut lectus pulvinar, mattis neque ac, vestibulum turpis. Integer porta ligula diam, in imperdiet diam molestie vitae. Nulla tristique tristique luctus. Quisque et mattis magna, sed maximus est. Donec nec ullamcorper tortor. Fusce vitae ornare augue. Donec lacinia sem justo, vestibulum volutpat metus ullamcorper nec. Vestibulum accumsan libero vel dictum porta. 23 | Sed aliquam vitae odio in imperdiet. Nullam sed scelerisque orci. Ut blandit, velit non maximus tincidunt, mauris odio interdum nisi, id semper nibh diam ut nisi. Donec pharetra hendrerit facilisis. Pellentesque lorem lectus, vestibulum vel rutrum porttitor, scelerisque vitae metus. Suspendisse vel lectus eleifend, viverra magna vitae, faucibus lectus. Ut nisl dui, iaculis eu quam non, rutrum euismod sapien. Duis nibh nunc, consectetur et orci eget, rutrum pretium arcu. Phasellus quam lorem, sollicitudin at lacus id, sollicitudin imperdiet massa. Nam nec magna dapibus, interdum erat quis, porta mi. Phasellus vestibulum nulla eget justo consequat, vel viverra tortor efficitur. Cras fringilla efficitur nunc vel faucibus. Curabitur elementum vel ligula et sagittis. 24 | Proin mollis nec tortor a blandit. Phasellus rutrum, mi vitae efficitur volutpat, quam orci tempus velit, ac ornare tellus augue eget elit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque a venenatis sem. Nullam et urna quis est vulputate convallis. Suspendisse id feugiat risus. Nunc viverra justo eget sodales gravida. Maecenas malesuada nec eros vitae feugiat. Mauris blandit diam erat, sit amet iaculis lectus tempor sed. In tortor felis, convallis laoreet dui a, consectetur fermentum nulla. Aliquam sed leo pharetra, vehicula lectus ut, tempor ex. Integer fermentum pellentesque nunc, eget mollis quam convallis vitae. Aliquam neque mi, condimentum sed metus sed, vulputate vulputate neque. Quisque efficitur est in ante efficitur tristique nec vitae neque. Nunc aliquam molestie nisl, eu gravida orci interdum quis. Nulla facilisi. 25 | Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum at pulvinar est. Aenean id odio ac mi pharetra fringilla non nec tellus. Aliquam erat volutpat. Sed vel diam dapibus, mollis purus a, rutrum urna. Fusce a turpis eu velit dignissim ullamcorper. Etiam aliquam sapien congue sapien venenatis finibus. In ultrices arcu velit, sed condimentum nibh sagittis eu. Integer quis fermentum enim. Mauris eu rutrum justo. Quisque congue egestas nibh id ullamcorper. Sed aliquam tellus fringilla, luctus nisi eu, dignissim sapien. 26 | Vestibulum sodales lectus nec dictum laoreet. Suspendisse ipsum ligula, feugiat in mauris cursus, rutrum sagittis nisl. In hac habitasse platea dictumst. Donec porta, lacus nec elementum consequat, lectus lectus vulputate dolor, in posuere quam eros a elit. Vestibulum mattis metus in leo ornare luctus vitae ut mauris. Curabitur arcu erat, tincidunt eget aliquam nec, ullamcorper a urna. Quisque a dolor in arcu cursus feugiat et non sapien. Cras lobortis egestas sollicitudin. Nunc feugiat sodales blandit. Phasellus fermentum tortor lacus, sit amet vestibulum neque sollicitudin at. Nam et dapibus nulla. Maecenas vel lacus est. Ut finibus tempor pellentesque. Nunc commodo a tellus elementum condimentum. In augue lectus, bibendum consectetur vulputate sit amet, interdum aliquet metus. 27 | Morbi mollis ipsum ac diam tempus vestibulum. Vivamus tristique tincidunt lacus, a bibendum nulla euismod ut. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla cursus euismod suscipit. Vestibulum et velit at velit dignissim sodales. Etiam posuere odio fringilla eleifend bibendum. Nullam facilisis nulla nunc, tristique suscipit eros mattis non. Morbi blandit sapien quis nisl facilisis scelerisque. Maecenas vel lorem at ipsum feugiat tempus vel eget arcu. 28 | Morbi varius facilisis turpis id iaculis. Nam vulputate egestas est pharetra vehicula. Praesent condimentum congue elit, in mattis odio tempor dictum. Ut dictum laoreet urna eget facilisis. Donec egestas dictum pellentesque. Curabitur et tellus metus. Aliquam nec neque aliquet risus luctus consequat. Sed tincidunt nec sapien eget auctor. Maecenas nibh sem, sodales a risus mollis, convallis tristique nibh. Nunc id orci vel urna tincidunt lacinia. Etiam vitae libero eros. 29 | Aenean semper bibendum ex, ut lacinia quam pulvinar nec. Etiam laoreet dui rutrum erat fringilla, ut consequat dolor elementum. Phasellus ut ipsum id mauris congue pulvinar. Nullam in ipsum sit amet dolor pulvinar hendrerit quis at dui. Etiam ut tellus sit amet velit suscipit pellentesque. Mauris placerat lobortis quam, efficitur sodales enim cursus id. Maecenas ac leo augue. Vestibulum nec justo mattis, cursus tortor eget, sagittis nulla. In at mattis nisi. Suspendisse potenti. Praesent at justo accumsan elit gravida ultricies id ut mi. In varius velit eu tempor laoreet. Suspendisse arcu neque, finibus ac nulla eget, ultrices ultricies est. Proin imperdiet porta orci, vitae eleifend sem facilisis facilisis. 30 | Suspendisse potenti. Aliquam sollicitudin eros quis porta tempor. Curabitur a nisl et orci tristique vulputate. Vestibulum ipsum nisl, maximus vitae nisi a, posuere rutrum magna. Etiam vel accumsan lectus. In justo felis, feugiat at magna in, condimentum volutpat nisl. Cras vel sem tristique, fringilla velit sit amet, sagittis leo. Morbi libero nisi, vulputate nec velit id, placerat dapibus sapien. Praesent rhoncus, eros et efficitur convallis, turpis risus feugiat orci, at auctor massa nunc vitae lorem. Mauris vel nunc condimentum risus condimentum interdum. 31 | In imperdiet felis nisl, in luctus est luctus ut. Vestibulum feugiat est eget lectus tincidunt cursus. Donec ac mauris in arcu mollis varius nec id nibh. Duis vel libero scelerisque, interdum nulla non, suscipit libero. Praesent facilisis ultricies suscipit. Curabitur posuere facilisis magna. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla egestas augue convallis lacinia sodales. 32 | Suspendisse commodo diam non leo egestas dapibus. Curabitur maximus sapien et sapien sodales, ut interdum nisl fermentum. Nam pretium neque vel laoreet interdum. Sed consectetur dui nec ex cursus, sed pulvinar felis viverra. Vestibulum fringilla, justo sed semper mattis, dolor odio convallis eros, sit amet semper quam massa vitae metus. Curabitur sed pretium ligula. Curabitur dictum aliquet facilisis. 33 | Nulla mattis ante sed nibh lacinia, eu pellentesque dui gravida. Mauris turpis metus, venenatis vel orci in, varius vehicula massa. Sed pellentesque magna sit amet leo ultricies, eu rhoncus lacus laoreet. Fusce tempus mi id aliquam mollis. Aliquam ornare lectus diam, vel congue sem tempor at. Nulla facilisi. Cras tincidunt, urna in blandit molestie, neque lorem ullamcorper orci, a cursus erat justo ut eros. Morbi gravida neque et scelerisque semper. Cras nec enim nec felis blandit malesuada. Proin eget egestas ante. 34 | Suspendisse lobortis lobortis lectus, a ornare lorem auctor a. In vel consequat ipsum. Mauris aliquam diam ac ullamcorper fermentum. Ut nec lorem vel nibh mollis porttitor. Aenean sed purus dolor. Proin ut rutrum justo, eu sagittis sem. Nulla ac ex ac mauris ultrices pretium. Aenean eget eros at arcu aliquet molestie et quis mi. Sed gravida eu enim vitae suscipit. Donec ac ornare leo. Praesent non lacinia dolor. Cras luctus dapibus libero, vel bibendum purus maximus sed. 35 | Praesent molestie nibh ac massa posuere sagittis. Quisque metus tellus, dapibus a ante eget, ultricies fringilla velit. Nunc interdum velit at enim fringilla, eget placerat nulla tincidunt. Aliquam id velit purus. Nunc ac vulputate lorem, vitae maximus massa. Curabitur sit amet mattis mi. Vivamus eu erat eget dolor viverra tincidunt. 36 | Sed aliquet libero nisl, ut molestie nisl sodales sit amet. Praesent tincidunt semper dictum. Maecenas consequat sapien eros, auctor sollicitudin magna auctor nec. Nullam nec urna id risus ullamcorper eleifend sed efficitur urna. Mauris nec ligula sodales, rutrum odio eu, semper metus. In vulputate hendrerit nulla eget malesuada. Nunc suscipit laoreet risus ac aliquet. Praesent porttitor est sit amet lectus mattis fermentum eget id nunc. 37 | Mauris blandit venenatis risus. Suspendisse potenti. Aenean vel tincidunt libero. Cras nec urna fermentum, faucibus dolor at, cursus turpis. Donec non tellus sit amet nisi auctor aliquam maximus eu sapien. Ut quis dignissim massa, interdum aliquet felis. Nullam iaculis sapien ac justo tristique malesuada. 38 | Aenean malesuada tristique mi quis placerat. Aenean condimentum velit at urna mattis tempor. Mauris consequat urna massa, eget bibendum turpis interdum at. Sed mattis dignissim urna sed congue. Donec sit amet est odio. Praesent ut sem ac odio aliquam fringilla. Vestibulum vehicula sem vel ex molestie, in scelerisque dui vestibulum. Aenean rutrum nulla a risus condimentum vulputate. Donec nec leo vitae nisl viverra facilisis eu eu mi. Suspendisse justo nibh, blandit at nulla et, ultricies congue dolor. 39 | Duis libero metus, pellentesque sit amet pellentesque lacinia, rutrum ut ante. Etiam sagittis nibh at lobortis congue. Aenean placerat turpis vel sapien sagittis, in elementum eros hendrerit. Proin interdum, nibh vitae placerat dictum, risus purus molestie diam, id gravida ligula purus ut risus. Pellentesque tristique ligula a lectus venenatis faucibus. Sed ac nisl purus. Aliquam in ipsum id enim tincidunt vestibulum. Praesent lectus dolor, aliquet ut risus et, facilisis accumsan nulla. Morbi ultrices tellus quis lectus mattis, id imperdiet nulla malesuada. Donec pharetra mauris ac turpis iaculis, at feugiat felis tincidunt. Suspendisse ex dolor, consectetur at lectus quis, eleifend tincidunt magna. Nullam blandit cursus est, vitae euismod enim tempor in. 40 | Vivamus non sapien aliquam, accumsan eros eu, placerat lacus. Ut varius a felis vitae tempor. Duis posuere turpis et neque laoreet, ut semper diam hendrerit. Etiam eleifend tortor in est ornare consequat. Ut hendrerit lacus non felis efficitur, non congue dui porttitor. In porttitor enim eu massa molestie, sed tempor libero lacinia. Aenean fringilla elementum gravida. Fusce nisi nisl, semper nec tortor sed, porttitor scelerisque quam. 41 | In hac habitasse platea dictumst. Etiam lacinia convallis elementum. Etiam a augue ex. Suspendisse vitae tortor lacus. Quisque aliquam ut quam sed vulputate. Nulla facilisi. Cras eleifend libero vel nisl viverra, vel aliquet nulla convallis. Proin nec quam eu magna consectetur consequat id nec neque. Nam libero mi, lobortis at maximus in, congue vestibulum odio. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras ac quam quis justo tincidunt aliquet. Suspendisse posuere, leo ac vehicula venenatis, purus lorem eleifend odio, vel facilisis justo urna a nisl. Aliquam sollicitudin rutrum ante. Integer blandit ipsum eu elit tincidunt, sed maximus lorem vulputate. 42 | Donec diam neque, volutpat vitae tortor eget, hendrerit consequat metus. Aliquam interdum vel leo vel pellentesque. Quisque auctor facilisis magna. Etiam ac auctor arcu. Nam scelerisque enim quis quam maximus, sollicitudin pretium nisi blandit. Proin dignissim sem sit amet ornare fringilla. Suspendisse potenti. Sed nec pharetra ex, sed pharetra metus. Donec commodo vestibulum purus ac volutpat. Duis condimentum ut nunc quis varius. Nulla mattis porta nulla, sed fringilla arcu rhoncus a. Suspendisse ornare sapien ac fringilla ultrices. Quisque tempus mi non nisl aliquam, sodales commodo nisl tempor. Etiam scelerisque viverra ex sed malesuada. Praesent nec urna vel metus feugiat iaculis a quis leo. Fusce egestas dui eget velit varius euismod. 43 | Sed ultricies blandit diam nec venenatis. Aliquam non risus vel dui tristique condimentum. Duis id elit non sem pulvinar laoreet. Nam ac eros volutpat neque efficitur vestibulum eget ut metus. Mauris eleifend mattis arcu, eget maximus nibh tempus at. Donec bibendum purus a lorem pulvinar, dapibus tristique turpis malesuada. Suspendisse dapibus diam eu lectus hendrerit mollis. Praesent sed nisl porttitor, venenatis odio vitae, finibus lorem. Morbi gravida vitae sapien eu mattis. In dictum eros dolor, non sagittis felis accumsan at. Nulla vulputate pulvinar facilisis. Donec euismod ultricies lorem. Curabitur maximus ipsum vel enim fermentum, vel posuere ex congue. Etiam sollicitudin quam ut lorem pharetra, sit amet tincidunt justo luctus. Vivamus ornare tellus eu enim gravida, a pulvinar justo ullamcorper. 44 | Praesent vitae molestie enim. Maecenas molestie sapien at cursus rhoncus. Vestibulum sollicitudin ullamcorper tellus. Nunc at quam vel erat aliquet luctus at quis turpis. Quisque fermentum laoreet tempor. In ut nibh ac orci vulputate malesuada. Curabitur faucibus lacus dolor, ut tempor arcu tempor nec. Mauris est nulla, blandit at malesuada sed, pellentesque ac sem. Curabitur nec nunc vel est eleifend sagittis. Maecenas vestibulum magna consequat odio malesuada, ut fringilla magna venenatis. Sed ut ligula non eros sagittis dignissim nec ac neque. 45 | Cras gravida sapien at erat aliquet, id laoreet ante porttitor. Donec sit amet massa at odio vulputate congue. Sed nisi dolor, egestas eget tortor sit amet, fermentum gravida tortor. Vivamus nec elit turpis. Sed sit amet purus non risus tincidunt pulvinar. Vivamus posuere metus et est sollicitudin, eu lacinia sem luctus. Sed sed mauris convallis, pellentesque eros nec, lobortis purus. Suspendisse placerat elit sit amet sagittis maximus. Proin ac aliquam nisi, ullamcorper pretium libero. Suspendisse tincidunt, massa facilisis aliquam elementum, dui neque volutpat lorem, in interdum arcu erat eu orci. Aliquam sed lectus tincidunt sapien sagittis elementum ac in turpis. Morbi vulputate metus tellus, a laoreet arcu volutpat sed. Nullam eu congue tortor. Morbi semper id lorem nec sodales. 46 | Donec finibus dui non neque molestie semper. Nulla quis sapien sapien. Vivamus in feugiat nisi. Duis et leo sollicitudin, aliquet erat dignissim, blandit velit. Praesent varius dignissim tellus, nec pretium risus eleifend non. Maecenas sagittis nisi vitae magna scelerisque, eu consectetur urna sagittis. Proin at aliquam nunc, id iaculis quam. Integer sit amet lectus et lacus hendrerit ultrices a non sem. Quisque semper dolor ac felis vulputate porta. Proin quis rhoncus nibh. Suspendisse varius sodales sagittis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aliquam molestie sit amet risus sit amet pulvinar. Cras sagittis metus ac semper maximus. 47 | Quisque et ornare mi. Integer vel nulla nunc. Vivamus ornare nulla eu lectus auctor feugiat. Vestibulum in auctor purus. Maecenas quis arcu sit amet eros consequat semper. Suspendisse lobortis, nisl ut pellentesque sollicitudin, metus ipsum tincidunt leo, et gravida ipsum nisi eu orci. Phasellus at fringilla leo, eu feugiat nulla. Quisque lacus nisl, hendrerit a blandit quis, dictum non nisi. Cras venenatis, massa eu viverra lacinia, odio sapien sagittis nibh, et eleifend erat risus at velit. Quisque malesuada, erat nec porttitor consequat, justo tellus porta lacus, at facilisis leo ante vel enim. Cras viverra, urna non mollis placerat, odio tellus scelerisque urna, sollicitudin feugiat purus quam sit amet justo. Suspendisse rutrum pulvinar ipsum vel pulvinar. 48 | Proin mollis at augue quis cursus. Maecenas a hendrerit dolor, imperdiet varius diam. Praesent nec lectus ac erat sodales interdum eu nec dui. Maecenas scelerisque tortor cursus feugiat gravida. Nulla dictum accumsan augue et ultrices. Cras elementum metus vitae semper imperdiet. Fusce non nulla lectus. Aliquam ut tellus id orci consectetur commodo vel quis dolor. Fusce consectetur laoreet efficitur. Vestibulum vitae augue vel lectus congue accumsan at a risus. Cras nulla odio, aliquam at massa quis, egestas sollicitudin felis. Praesent porta pellentesque justo a egestas. Etiam nec tellus luctus, vestibulum eros in, suscipit neque. 49 | Praesent vulputate vitae leo non feugiat. Sed vestibulum nisl sit amet augue auctor tempor. Donec accumsan neque eget libero consequat porta. Donec congue lorem vel mauris imperdiet dapibus. Sed ornare ipsum nibh, sit amet lobortis massa vestibulum et. In tempus, nibh imperdiet gravida laoreet, ligula mi pretium nibh, non consequat risus est eget eros. Pellentesque non leo nulla. Morbi tincidunt elementum nulla id tincidunt. Sed sed lorem sodales, commodo lectus in, malesuada dui. Cras non ultrices libero, id pellentesque erat. 50 | Nullam eu nibh nec ligula pharetra interdum viverra sit amet nibh. In sit amet mi dignissim, vulputate risus rutrum, mattis dui. Aenean fringilla tristique elit, sed sodales lectus consectetur non. Maecenas fringilla sed eros sit amet efficitur. Aliquam tincidunt mauris tempus dui pretium, vel dapibus lacus faucibus. Mauris lobortis egestas magna vel iaculis. Donec convallis hendrerit metus et sodales. Cras id elementum ex, a semper enim. Sed placerat arcu nisl, nec congue neque mattis non. Aenean in magna tortor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis condimentum urna imperdiet leo euismod, laoreet consectetur orci lacinia. Curabitur vehicula consectetur nisi ut dictum. Aenean malesuada, massa id tempor facilisis, orci sapien pulvinar nulla, sed bibendum erat arcu congue urna. 51 | Proin ullamcorper felis a magna gravida auctor. Mauris sagittis dignissim commodo. Donec blandit est augue, et accumsan ex ultricies a. Vivamus aliquam quam ac nunc accumsan pretium. In sed tortor tincidunt metus congue maximus. Donec ut nisl erat. Integer accumsan ante ullamcorper tincidunt ultricies. Aenean sollicitudin convallis arcu ut auctor. Ut rutrum, tortor vel egestas fermentum, ligula eros posuere mauris, vel vulputate lorem massa a erat. Suspendisse potenti. 52 | Aenean condimentum elit non ultricies elementum. Fusce placerat pharetra lacinia. Maecenas orci nibh, rhoncus vitae neque eleifend, ornare ornare erat. Mauris elementum, purus in efficitur vehicula, nibh ligula ullamcorper eros, eu mattis magna tortor in nisi. Aliquam eget sapien ipsum. Quisque vitae enim ac metus eleifend placerat. Pellentesque faucibus fringilla velit id pulvinar. Sed interdum elit mi. Phasellus eros lacus, eleifend eu pulvinar quis, auctor in metus. Suspendisse vehicula augue id finibus vehicula. 53 | Curabitur tortor lorem, bibendum condimentum lorem eget, cursus dictum sem. Aenean laoreet nisi quis ante dignissim commodo. Suspendisse eget congue arcu, eu vestibulum sapien. Donec massa lorem, suscipit ac arcu eget, accumsan malesuada risus. Aliquam suscipit eros in maximus faucibus. Maecenas sodales pellentesque risus in varius. Morbi ut enim at felis consequat cursus eget vel neque. Nam sit amet vehicula tortor. Maecenas auctor imperdiet eros, vel maximus justo vehicula a. Aenean enim tellus, vehicula et metus at, eleifend gravida elit. Duis pellentesque scelerisque libero, eu imperdiet nunc facilisis in. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. 54 | Etiam sapien leo, ullamcorper consequat malesuada quis, lobortis vel erat. Ut et arcu eu nisl ultrices lobortis et ac nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vitae ante id elit feugiat bibendum nec vel nisi. Suspendisse metus augue, mattis ut lorem non, aliquet interdum lacus. Curabitur id neque sit amet orci varius pretium. Donec massa libero, viverra vel erat sed, aliquam volutpat enim. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum consectetur massa et dui accumsan, ut sodales purus tincidunt. Quisque tempor facilisis mollis. Etiam vel suscipit justo. Vestibulum faucibus imperdiet ante, sit amet vestibulum sapien laoreet in. Etiam a bibendum erat. Aenean faucibus arcu a odio tincidunt, ut ultrices urna porta. Quisque tempor, ante sed viverra vestibulum, neque erat interdum erat, eu volutpat felis nibh eu massa. 55 | Suspendisse a arcu sit amet nisl semper fermentum in id mauris. Etiam commodo auctor quam ut placerat. Maecenas gravida turpis vitae urna rhoncus, at mollis nulla ultrices. Sed urna nibh, porttitor nec dui nec, consequat pharetra risus. Phasellus vehicula quam eget ex molestie condimentum. Pellentesque pulvinar elit sed urna consequat mollis. Ut ac lacinia augue. Morbi vel ligula iaculis massa commodo dapibus. Nulla ut sagittis diam, vitae accumsan tortor. Cras in risus laoreet, faucibus velit ut, bibendum justo. Vivamus sed interdum felis. Nullam enim sem, tincidunt sed odio in, vestibulum malesuada arcu. Duis lacinia malesuada euismod. 56 | Donec quis felis sit amet nunc tincidunt volutpat sed vel nisi. Nam maximus dolor quis molestie tristique. Morbi tincidunt eros nunc, eu imperdiet leo egestas a. Sed in enim arcu. Maecenas malesuada volutpat ante nec sodales. Aenean ac purus sem. Pellentesque nibh justo, ultricies molestie sem ac, ultrices blandit arcu. Phasellus non feugiat odio, ut malesuada augue. Morbi vel congue ipsum, ac luctus ipsum. Donec id mauris volutpat, sodales ligula eget, pulvinar lectus. Phasellus vitae lacus quam. Sed quis nunc ut elit ornare elementum. Nulla molestie felis non neque pretium, sed lacinia elit euismod. Nulla egestas non dolor viverra facilisis. 57 | Ut mollis risus lorem. Quisque commodo sem arcu, eu ultrices orci lobortis a. Integer dui tellus, tempor eu enim vitae, cursus efficitur enim. Donec euismod, ante et aliquet gravida, ipsum est maximus dui, ut tincidunt diam lorem eu lacus. Aenean lacus sem, tincidunt eu commodo gravida, elementum sit amet nisl. Duis tincidunt elit at tempus mattis. Nullam viverra in ligula eget scelerisque. Duis pretium auctor molestie. Quisque malesuada elementum purus. Maecenas quis tellus dapibus, auctor lectus at, vestibulum ligula. Ut vehicula condimentum eleifend. 58 | Donec posuere placerat nulla, eu ultricies orci. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam turpis nisi, rhoncus vel varius vitae, mattis at augue. Nam risus metus, scelerisque quis tempus et, accumsan sed erat. Curabitur facilisis at massa in tincidunt. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Mauris facilisis scelerisque erat a molestie. Mauris lacinia diam at diam tristique tincidunt. Aenean imperdiet malesuada consequat. Phasellus maximus eu odio eu bibendum. 59 | Pellentesque sit amet accumsan ipsum, et laoreet ante. Sed volutpat nunc id ante ultrices, in suscipit lectus mollis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nullam tincidunt ullamcorper sem non imperdiet. Sed faucibus commodo augue egestas tincidunt. Vivamus semper, magna sit amet lacinia malesuada, mauris ex cursus tellus, in aliquet turpis turpis ut leo. Mauris sollicitudin a eros sit amet convallis. 60 | Morbi tempor sem ac nisl lacinia imperdiet. Quisque ligula neque, tempor id tristique quis, vulputate at justo. Phasellus vel mi sit amet orci mattis luctus et eget nisl. Sed non dolor elit. Fusce nec tortor sit amet purus vestibulum tempor. Praesent tellus libero, egestas quis urna nec, molestie posuere odio. Suspendisse euismod dictum dolor quis porttitor"; 61 | } 62 | 63 | string vorher; 64 | public string Vorher 65 | { 66 | get { return vorher; } 67 | set { vorher = value; Compare(); } 68 | } 69 | 70 | string nachher; 71 | public string Nachher 72 | { 73 | get { return nachher; } 74 | set { nachher = value; Compare(); } 75 | } 76 | 77 | public SideBySideDiffModel Diff { get; private set; } 78 | 79 | private void Compare() 80 | { 81 | var diffBuilder = new SideBySideDiffBuilder(new Differ()); 82 | Diff = diffBuilder.BuildDiffModel(Vorher ?? string.Empty, Nachher ?? string.Empty); 83 | NotifyChanged(nameof(Diff)); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("WpfDiff")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("WpfDiff")] 15 | [assembly: AssemblyCopyright("Copyright © 2017")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WpfDiff.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WpfDiff.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WpfDiff.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/SideBySideDiffModelVisualizer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using System.Windows.Documents; 6 | using System.Windows.Media; 7 | using DiffPlex.DiffBuilder.Model; 8 | 9 | namespace WpfDiff 10 | { 11 | public class SideBySideDiffModelVisualizer 12 | { 13 | public static SideBySideDiffModel GetVorher(DependencyObject obj) { return (SideBySideDiffModel)obj.GetValue(VorherProperty); } 14 | public static void SetVorher(DependencyObject obj, SideBySideDiffModel value) { obj.SetValue(VorherProperty, value); } 15 | public static readonly DependencyProperty VorherProperty = DependencyProperty.RegisterAttached("Vorher", typeof(SideBySideDiffModel), typeof(SideBySideDiffModelVisualizer), new PropertyMetadata(null, new PropertyChangedCallback(VorherChanged))); 16 | private static void VorherChanged(DependencyObject dep, DependencyPropertyChangedEventArgs e) 17 | { 18 | var richTextBox = (RichTextBox)dep; 19 | var diff = (SideBySideDiffModel)e.NewValue; 20 | 21 | var zippedDiffs = Enumerable.Zip(diff.OldText.Lines, diff.NewText.Lines, (oldLine, newLine) => new OldNew { Old = oldLine, New = newLine }).ToList(); 22 | ShowDiffs(richTextBox, zippedDiffs, line => line.Old, piece => piece.Old); 23 | } 24 | 25 | public static SideBySideDiffModel GetNachher(DependencyObject obj) { return (SideBySideDiffModel)obj.GetValue(NachherProperty); } 26 | public static void SetNachher(DependencyObject obj, SideBySideDiffModel value) { obj.SetValue(NachherProperty, value); } 27 | public static readonly DependencyProperty NachherProperty = DependencyProperty.RegisterAttached("Nachher", typeof(SideBySideDiffModel), typeof(SideBySideDiffModelVisualizer), new PropertyMetadata(null, new PropertyChangedCallback(NachherChanged))); 28 | private static void NachherChanged(DependencyObject dep, DependencyPropertyChangedEventArgs e) 29 | { 30 | var richTextBox = (RichTextBox)dep; 31 | var diff = (SideBySideDiffModel)e.NewValue; 32 | 33 | var zippedDiffs = Enumerable.Zip(diff.OldText.Lines, diff.NewText.Lines, (oldLine, newLine) => new OldNew { Old = oldLine, New = newLine }).ToList(); 34 | ShowDiffs(richTextBox, zippedDiffs, line => line.New, piece => piece.New); 35 | } 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | private static void ShowDiffs(RichTextBox diffBox, System.Collections.Generic.List> lines, Func, DiffPiece> lineSelector, Func, DiffPiece> pieceSelector) 48 | { 49 | diffBox.Document.Blocks.Clear(); 50 | foreach (var line in lines) 51 | { 52 | var synchroLineLength = Math.Max(line.Old.Text?.Length ?? 0, line.New.Text?.Length ?? 0); 53 | var lineSubPieces = Enumerable.Zip(line.Old.SubPieces, line.New.SubPieces, (oldPiece, newPiece) => new OldNew { Old = oldPiece, New = newPiece, Length = Math.Max(oldPiece.Text?.Length ?? 0, newPiece.Text?.Length ?? 0) }); 54 | 55 | var oldNewLine = lineSelector(line); 56 | switch (oldNewLine.Type) 57 | { 58 | case ChangeType.Unchanged: AppendParagraph(diffBox, oldNewLine.Text ?? string.Empty); break; 59 | case ChangeType.Imaginary: AppendParagraph(diffBox, new string(BreakingSpace, synchroLineLength), Brushes.Gray, Brushes.LightCyan); break; 60 | case ChangeType.Inserted: AppendParagraph(diffBox, oldNewLine.Text ?? string.Empty, Brushes.LightGreen); break; 61 | case ChangeType.Deleted: AppendParagraph(diffBox, oldNewLine.Text ?? string.Empty, Brushes.OrangeRed); break; 62 | case ChangeType.Modified: 63 | var paragraph = AppendParagraph(diffBox, string.Empty); 64 | foreach (var subPiece in lineSubPieces) 65 | { 66 | var oldNewPiece = pieceSelector(subPiece); 67 | switch (oldNewPiece.Type) 68 | { 69 | case ChangeType.Unchanged: paragraph.Inlines.Add(NewRun(oldNewPiece.Text ?? string.Empty, Brushes.Yellow)); break; 70 | case ChangeType.Imaginary: paragraph.Inlines.Add(NewRun(oldNewPiece.Text ?? string.Empty)); break; 71 | case ChangeType.Inserted: paragraph.Inlines.Add(NewRun(oldNewPiece.Text ?? string.Empty, Brushes.LightGreen)); break; 72 | case ChangeType.Deleted: paragraph.Inlines.Add(NewRun(oldNewPiece.Text ?? string.Empty, Brushes.OrangeRed)); break; 73 | case ChangeType.Modified: paragraph.Inlines.Add(NewRun(oldNewPiece.Text ?? string.Empty, Brushes.Yellow)); break; 74 | default: throw new ArgumentException(); 75 | } 76 | paragraph.Inlines.Add(NewRun(new string(BreakingSpace, subPiece.Length - (oldNewPiece.Text ?? string.Empty).Length), Brushes.Gray, Brushes.LightCyan)); 77 | } 78 | break; 79 | default: throw new ArgumentException(); 80 | } 81 | } 82 | } 83 | 84 | 85 | private class OldNew 86 | { 87 | public T Old { get; set; } 88 | public T New { get; set; } 89 | public int Length { get; set; } 90 | } 91 | 92 | 93 | 94 | private static char BreakingSpace = '-'; 95 | 96 | private static Paragraph AppendParagraph(RichTextBox textBox, string text, Brush background = null, Brush foreground = null) 97 | { 98 | var paragraph = new Paragraph(new Run(text)) 99 | { 100 | LineHeight = 0.5, 101 | Background = background ?? Brushes.Transparent, 102 | Foreground = foreground ?? Brushes.Black, 103 | BorderBrush = Brushes.DarkGray, 104 | BorderThickness = new Thickness(0, 0, 0, 1), 105 | }; 106 | 107 | textBox.Document.Blocks.Add(paragraph); 108 | return paragraph; 109 | } 110 | 111 | private static Run NewRun(string text, Brush background = null, Brush foreground = null) => new Run(text) 112 | { 113 | Background = background ?? Brushes.Transparent, 114 | Foreground = foreground ?? Brushes.Black, 115 | }; 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/ViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace WpfDiff 4 | { 5 | public abstract class ViewModel : INotifyPropertyChanged 6 | { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | 9 | protected void NotifyChanged(string name) 10 | { 11 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WpfDiff/WpfDiff/WpfDiff.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {141A6C3D-7631-4E5B-8D96-199955B50054} 8 | WinExe 9 | WpfDiff 10 | WpfDiff 11 | v4.8 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | 17 | 18 | 19 | 20 | 21 | AnyCPU 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | 30 | 31 | AnyCPU 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE 36 | prompt 37 | 4 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 4.0 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | MSBuild:Compile 60 | Designer 61 | 62 | 63 | 64 | 65 | 66 | MSBuild:Compile 67 | Designer 68 | 69 | 70 | App.xaml 71 | Code 72 | 73 | 74 | MainWindow.xaml 75 | Code 76 | 77 | 78 | 79 | 80 | Code 81 | 82 | 83 | True 84 | True 85 | Resources.resx 86 | 87 | 88 | True 89 | Settings.settings 90 | True 91 | 92 | 93 | ResXFileCodeGenerator 94 | Resources.Designer.cs 95 | 96 | 97 | SettingsSingleFileGenerator 98 | Settings.Designer.cs 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 1.0.28 107 | 108 | 109 | 1.6.3 110 | 111 | 112 | 5.0.1 113 | 114 | 115 | 4.3.0 116 | 117 | 118 | 2.0.3 119 | 120 | 121 | 4.3.0 122 | 123 | 124 | 4.3.0 125 | 126 | 127 | 4.3.0 128 | 129 | 130 | 4.3.1 131 | 132 | 133 | 4.3.0 134 | 135 | 136 | 4.3.0 137 | 138 | 139 | 4.3.0 140 | 141 | 142 | 4.3.0 143 | 144 | 145 | 4.3.0 146 | 147 | 148 | 4.3.0 149 | 150 | 151 | 4.3.0 152 | 153 | 154 | 4.3.0 155 | 156 | 157 | 4.3.0 158 | 159 | 160 | 4.3.0 161 | 162 | 163 | 4.3.0 164 | 165 | 166 | 4.3.4 167 | 168 | 169 | 4.3.0 170 | 171 | 172 | 4.3.0 173 | 174 | 175 | 4.3.0 176 | 177 | 178 | 4.3.0 179 | 180 | 181 | 4.3.0 182 | 183 | 184 | 4.3.0 185 | 186 | 187 | 4.3.0 188 | 189 | 190 | 4.3.0 191 | 192 | 193 | 4.3.0 194 | 195 | 196 | 4.3.0 197 | 198 | 199 | 4.3.0 200 | 201 | 202 | 4.3.0 203 | 204 | 205 | 4.3.0 206 | 207 | 208 | 4.3.0 209 | 210 | 211 | 4.3.0 212 | 213 | 214 | 4.3.0 215 | 216 | 217 | 4.3.0 218 | 219 | 220 | 4.3.0 221 | 222 | 223 | 4.3.0 224 | 225 | 226 | 4.3.0 227 | 228 | 229 | 230 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/halllo/WpfDiff/bf24ce2c810c38044d43958a3c5201277d34bd5b/screenshot.png --------------------------------------------------------------------------------