diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/AutoTypeSearch/SearchResults.cs b/AutoTypeSearch/SearchResults.cs
new file mode 100755
index 0000000..b2b0529
--- /dev/null
+++ b/AutoTypeSearch/SearchResults.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePass.Util.Spr;
+using KeePassLib;
+using KeePassLib.Utility;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResults
+	{
+		private readonly string mTerm;
+		private readonly SearchResult[] mResults;
+
+		private readonly object mLock = new object();
+		private volatile int mCount;
+		private volatile bool mComplete;
+
+		private readonly AutoResetEvent mResultsUpdated = new AutoResetEvent(false);
+
+		private readonly CompareOptions mStringComparison;
+		private readonly bool mSearchTitle;
+		private readonly bool mSearchUserName;
+		private readonly bool mSearchUrl;
+		private readonly bool mSearchNotes;
+		private readonly bool mSearchCustomFields;
+		private readonly bool mResolveReferences;
+		private readonly bool mSearchTags;
+
+		public SearchResults(int capacity, string term)
+		{
+			mTerm = term;
+			mResults = new SearchResult[capacity];
+
+			mStringComparison = Settings.Default.CaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase;
+			mStringComparison |= CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace;
+			mSearchTitle = Settings.Default.SearchTitle;
+			mSearchUserName = Settings.Default.SearchUserName;
+			mSearchUrl = Settings.Default.SearchUrl;
+			mSearchNotes = Settings.Default.SearchNotes;
+			mSearchCustomFields = Settings.Default.SearchCustomFields;
+			mSearchTags = Settings.Default.SearchTags;
+			mResolveReferences = Settings.Default.ResolveReferences;
+		}
+
+		/// 
+		/// Gets an ordered list of fields to search for the term
+		/// 
+		/// 
+		/// 
+		private IEnumerable GetFieldsToSearch(PwEntry entry)
+		{
+			var fieldsToSearch = new List((int)entry.Strings.UCount);
+			if (mSearchTitle) fieldsToSearch.Add(PwDefs.TitleField);
+			if (mSearchUserName) fieldsToSearch.Add(PwDefs.UserNameField);
+			if (mSearchUrl) fieldsToSearch.Add(PwDefs.UrlField);
+			if (mSearchNotes) fieldsToSearch.Add(PwDefs.NotesField);
+			if (mSearchCustomFields)
+			{
+				foreach (var stringEntry in entry.Strings)
+				{
+					if (!stringEntry.Value.IsProtected && !PwDefs.IsStandardField(stringEntry.Key))
+					{
+						fieldsToSearch.Add(stringEntry.Key);
+					}
+				}
+			}
+			if (mSearchTags) fieldsToSearch.Add(AutoTypeSearchExt.TagsVirtualFieldName);
+
+			return fieldsToSearch;
+		}
+
+		public void AddResultIfMatchesTerm(PwDatabase context, PwEntry entry)
+		{
+			// First try without resolving
+			var addedResult = AddResultIfMatchesTerm(context, entry, false);
+
+			if (!addedResult && mResolveReferences)
+			{
+				// Not found without resolving, so try resolving
+				AddResultIfMatchesTerm(context, entry, true);
+			}
+		}
+
+		private bool AddResultIfMatchesTerm(PwDatabase context, PwEntry entry, bool resolveReferences)
+		{
+			foreach (var fieldName in GetFieldsToSearch(entry))
+			{
+				string fieldValue;
+				if (fieldName == AutoTypeSearchExt.TagsVirtualFieldName)
+				{
+					fieldValue = StrUtil.TagsToString(entry.Tags, true);
+				}
+				else
+				{
+					fieldValue = entry.Strings.ReadSafeEx(fieldName);
+
+					if (resolveReferences)
+					{
+						fieldValue = ResolveReferences(context, entry, fieldValue);
+					}
+				}
+
+				if (!String.IsNullOrEmpty(fieldValue))
+				{
+					var foundIndex = CultureInfo.CurrentCulture.CompareInfo.IndexOf(fieldValue, mTerm, mStringComparison);
+					if (foundIndex >= 0)
+					{
+						// Found a match, create a search result and add it
+						AddResult(new SearchResult(context, entry, entry.Strings.ReadSafe(PwDefs.TitleField), fieldName, fieldValue, foundIndex, mTerm.Length));
+						return true;
+					}
+				}
+			}
+			return false;
+		}
+
+		/// 
+		/// Resolves any references in the field value and returns it. If there were no references,
+		/// returns null (to avoid duplicate searching - it is assumed that the unresolved value has already been searched)
+		/// 
+		private string ResolveReferences(PwDatabase context, PwEntry entry, string fieldValue)
+		{
+			if (fieldValue.IndexOf('{') < 0)
+			{
+				// Can't contain any references
+				return null;
+			}
+			
+			var sprContext = new SprContext(entry, context, SprCompileFlags.Deref) { ForcePlainTextPasswords = false };
+
+			var result = SprEngine.Compile(fieldValue, sprContext);
+			if (CultureInfo.CurrentCulture.CompareInfo.Compare(result,fieldValue, mStringComparison) == 0)
+			{
+				return null;
+			}
+			
+			return result;
+		}
+
+		public void AddResultIfMatchesTerm(SearchResult candidate)
+		{
+			// First see whether the existing candidate is a further match in the same place
+			var fieldValue = candidate.FieldValue;
+			if (fieldValue.Length > candidate.Start + mTerm.Length && CultureInfo.CurrentCulture.CompareInfo.Compare(fieldValue.Substring(candidate.Start, mTerm.Length), mTerm, mStringComparison) == 0)
+			{
+				// Yep, match continues, so add it.
+				AddResult(new SearchResult(candidate.Database, candidate.Entry, candidate.Title, candidate.FieldName, fieldValue, candidate.Start, mTerm.Length));
+			}
+			else
+			{
+				// Existing candidate match couldn't be extended, so search from scratch again
+				AddResultIfMatchesTerm(candidate.Database, candidate.Entry);
+			}
+		}
+
+		private void AddResult(SearchResult result)
+		{
+			lock (mLock)
+			{
+				if (mComplete)
+				{
+					throw new InvalidOperationException("Search results have been completed");
+				}
+				result.SetResultIndex(mCount);
+				mResults[mCount++] = result;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Indicates that the results are complete, and no more will be added.
+		/// 
+		public void SetComplete()
+		{
+			lock (mLock)
+			{
+				mComplete = true;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Gets all the available results so far.
+		/// 
+		/// Index to start returning from. Modified to be the first index not available yet on return.
+		/// Set to true if the results are complete, false if more results are pending but have not been returned.
+		/// 
+		public SearchResult[] GetAvailableResults(ref int index, out bool complete)
+		{
+			int count;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			if (count <= index)
+			{
+				return new SearchResult[0];
+			}
+
+			var availableResults = new SearchResult[count - index];
+			Array.Copy(mResults, index, availableResults, 0, availableResults.Length);
+			index = count;
+
+			return availableResults;
+		}
+
+		/// 
+		/// Gets all the results. Will block until complete.
+		/// 
+		/// 
+		public IEnumerable GetAllResults()
+		{
+			int count = -1;
+
+			for (var i = 0; i < mResults.Length; i++)
+			{
+				if (i > count)
+				{
+					// Reached the limit of availability so far, so see if more is available
+					do
+					{
+						bool moreAvailable, complete;
+
+						lock (mLock)
+						{
+							moreAvailable = mCount > count;
+							count = mCount;
+							complete = mComplete;
+						}
+
+						if (!moreAvailable)
+						{
+							if (complete)
+							{
+								// No more available, but the results are now complete anyway
+								yield break;
+							}
+
+							// No more available yet, not yet complete, wait until more becomes available
+							mResultsUpdated.WaitOne();
+						}
+						else
+						{
+							// More available now, so stop checking for more, continue with the loop to return them
+							break;
+						}
+					} while (true);
+
+					Debug.Assert(i <= count, "More should be available now");
+				}
+
+				yield return mResults[i];
+			}
+		}
+
+		public SearchResults CreateChildResults(string term)
+		{
+			Debug.Assert(term.StartsWith(mTerm));
+
+			int count;
+			bool complete;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			// If complete, then we know we don't need more than count. Otherwise, it can't be more than this capacity anyway
+			var childCapacity = complete ? count : mResults.Length;
+
+			return new SearchResults(childCapacity, term);
+		}
+	}
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/AutoTypeSearch/SearchResults.cs b/AutoTypeSearch/SearchResults.cs
new file mode 100755
index 0000000..b2b0529
--- /dev/null
+++ b/AutoTypeSearch/SearchResults.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePass.Util.Spr;
+using KeePassLib;
+using KeePassLib.Utility;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResults
+	{
+		private readonly string mTerm;
+		private readonly SearchResult[] mResults;
+
+		private readonly object mLock = new object();
+		private volatile int mCount;
+		private volatile bool mComplete;
+
+		private readonly AutoResetEvent mResultsUpdated = new AutoResetEvent(false);
+
+		private readonly CompareOptions mStringComparison;
+		private readonly bool mSearchTitle;
+		private readonly bool mSearchUserName;
+		private readonly bool mSearchUrl;
+		private readonly bool mSearchNotes;
+		private readonly bool mSearchCustomFields;
+		private readonly bool mResolveReferences;
+		private readonly bool mSearchTags;
+
+		public SearchResults(int capacity, string term)
+		{
+			mTerm = term;
+			mResults = new SearchResult[capacity];
+
+			mStringComparison = Settings.Default.CaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase;
+			mStringComparison |= CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace;
+			mSearchTitle = Settings.Default.SearchTitle;
+			mSearchUserName = Settings.Default.SearchUserName;
+			mSearchUrl = Settings.Default.SearchUrl;
+			mSearchNotes = Settings.Default.SearchNotes;
+			mSearchCustomFields = Settings.Default.SearchCustomFields;
+			mSearchTags = Settings.Default.SearchTags;
+			mResolveReferences = Settings.Default.ResolveReferences;
+		}
+
+		/// 
+		/// Gets an ordered list of fields to search for the term
+		/// 
+		/// 
+		/// 
+		private IEnumerable GetFieldsToSearch(PwEntry entry)
+		{
+			var fieldsToSearch = new List((int)entry.Strings.UCount);
+			if (mSearchTitle) fieldsToSearch.Add(PwDefs.TitleField);
+			if (mSearchUserName) fieldsToSearch.Add(PwDefs.UserNameField);
+			if (mSearchUrl) fieldsToSearch.Add(PwDefs.UrlField);
+			if (mSearchNotes) fieldsToSearch.Add(PwDefs.NotesField);
+			if (mSearchCustomFields)
+			{
+				foreach (var stringEntry in entry.Strings)
+				{
+					if (!stringEntry.Value.IsProtected && !PwDefs.IsStandardField(stringEntry.Key))
+					{
+						fieldsToSearch.Add(stringEntry.Key);
+					}
+				}
+			}
+			if (mSearchTags) fieldsToSearch.Add(AutoTypeSearchExt.TagsVirtualFieldName);
+
+			return fieldsToSearch;
+		}
+
+		public void AddResultIfMatchesTerm(PwDatabase context, PwEntry entry)
+		{
+			// First try without resolving
+			var addedResult = AddResultIfMatchesTerm(context, entry, false);
+
+			if (!addedResult && mResolveReferences)
+			{
+				// Not found without resolving, so try resolving
+				AddResultIfMatchesTerm(context, entry, true);
+			}
+		}
+
+		private bool AddResultIfMatchesTerm(PwDatabase context, PwEntry entry, bool resolveReferences)
+		{
+			foreach (var fieldName in GetFieldsToSearch(entry))
+			{
+				string fieldValue;
+				if (fieldName == AutoTypeSearchExt.TagsVirtualFieldName)
+				{
+					fieldValue = StrUtil.TagsToString(entry.Tags, true);
+				}
+				else
+				{
+					fieldValue = entry.Strings.ReadSafeEx(fieldName);
+
+					if (resolveReferences)
+					{
+						fieldValue = ResolveReferences(context, entry, fieldValue);
+					}
+				}
+
+				if (!String.IsNullOrEmpty(fieldValue))
+				{
+					var foundIndex = CultureInfo.CurrentCulture.CompareInfo.IndexOf(fieldValue, mTerm, mStringComparison);
+					if (foundIndex >= 0)
+					{
+						// Found a match, create a search result and add it
+						AddResult(new SearchResult(context, entry, entry.Strings.ReadSafe(PwDefs.TitleField), fieldName, fieldValue, foundIndex, mTerm.Length));
+						return true;
+					}
+				}
+			}
+			return false;
+		}
+
+		/// 
+		/// Resolves any references in the field value and returns it. If there were no references,
+		/// returns null (to avoid duplicate searching - it is assumed that the unresolved value has already been searched)
+		/// 
+		private string ResolveReferences(PwDatabase context, PwEntry entry, string fieldValue)
+		{
+			if (fieldValue.IndexOf('{') < 0)
+			{
+				// Can't contain any references
+				return null;
+			}
+			
+			var sprContext = new SprContext(entry, context, SprCompileFlags.Deref) { ForcePlainTextPasswords = false };
+
+			var result = SprEngine.Compile(fieldValue, sprContext);
+			if (CultureInfo.CurrentCulture.CompareInfo.Compare(result,fieldValue, mStringComparison) == 0)
+			{
+				return null;
+			}
+			
+			return result;
+		}
+
+		public void AddResultIfMatchesTerm(SearchResult candidate)
+		{
+			// First see whether the existing candidate is a further match in the same place
+			var fieldValue = candidate.FieldValue;
+			if (fieldValue.Length > candidate.Start + mTerm.Length && CultureInfo.CurrentCulture.CompareInfo.Compare(fieldValue.Substring(candidate.Start, mTerm.Length), mTerm, mStringComparison) == 0)
+			{
+				// Yep, match continues, so add it.
+				AddResult(new SearchResult(candidate.Database, candidate.Entry, candidate.Title, candidate.FieldName, fieldValue, candidate.Start, mTerm.Length));
+			}
+			else
+			{
+				// Existing candidate match couldn't be extended, so search from scratch again
+				AddResultIfMatchesTerm(candidate.Database, candidate.Entry);
+			}
+		}
+
+		private void AddResult(SearchResult result)
+		{
+			lock (mLock)
+			{
+				if (mComplete)
+				{
+					throw new InvalidOperationException("Search results have been completed");
+				}
+				result.SetResultIndex(mCount);
+				mResults[mCount++] = result;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Indicates that the results are complete, and no more will be added.
+		/// 
+		public void SetComplete()
+		{
+			lock (mLock)
+			{
+				mComplete = true;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Gets all the available results so far.
+		/// 
+		/// Index to start returning from. Modified to be the first index not available yet on return.
+		/// Set to true if the results are complete, false if more results are pending but have not been returned.
+		/// 
+		public SearchResult[] GetAvailableResults(ref int index, out bool complete)
+		{
+			int count;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			if (count <= index)
+			{
+				return new SearchResult[0];
+			}
+
+			var availableResults = new SearchResult[count - index];
+			Array.Copy(mResults, index, availableResults, 0, availableResults.Length);
+			index = count;
+
+			return availableResults;
+		}
+
+		/// 
+		/// Gets all the results. Will block until complete.
+		/// 
+		/// 
+		public IEnumerable GetAllResults()
+		{
+			int count = -1;
+
+			for (var i = 0; i < mResults.Length; i++)
+			{
+				if (i > count)
+				{
+					// Reached the limit of availability so far, so see if more is available
+					do
+					{
+						bool moreAvailable, complete;
+
+						lock (mLock)
+						{
+							moreAvailable = mCount > count;
+							count = mCount;
+							complete = mComplete;
+						}
+
+						if (!moreAvailable)
+						{
+							if (complete)
+							{
+								// No more available, but the results are now complete anyway
+								yield break;
+							}
+
+							// No more available yet, not yet complete, wait until more becomes available
+							mResultsUpdated.WaitOne();
+						}
+						else
+						{
+							// More available now, so stop checking for more, continue with the loop to return them
+							break;
+						}
+					} while (true);
+
+					Debug.Assert(i <= count, "More should be available now");
+				}
+
+				yield return mResults[i];
+			}
+		}
+
+		public SearchResults CreateChildResults(string term)
+		{
+			Debug.Assert(term.StartsWith(mTerm));
+
+			int count;
+			bool complete;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			// If complete, then we know we don't need more than count. Otherwise, it can't be more than this capacity anyway
+			var childCapacity = complete ? count : mResults.Length;
+
+			return new SearchResults(childCapacity, term);
+		}
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.Designer.cs b/AutoTypeSearch/SearchWindow.Designer.cs
new file mode 100755
index 0000000..18b37d1
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.Designer.cs
@@ -0,0 +1,201 @@
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	partial class SearchWindow
+	{
+		/// 
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		#region Windows Form Designer generated code
+
+		/// 
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			this.components = new System.ComponentModel.Container();
+			this.mSearch = new System.Windows.Forms.TextBox();
+			this.mResults = new System.Windows.Forms.ListBox();
+			this.mLayout = new System.Windows.Forms.TableLayoutPanel();
+			this.mBanner = new System.Windows.Forms.PictureBox();
+			this.mInfoBanner = new System.Windows.Forms.Panel();
+			this.mInfoLabel = new System.Windows.Forms.Label();
+			this.mInfoBannerImage = new System.Windows.Forms.PictureBox();
+			this.mThrobber = new System.Windows.Forms.PictureBox();
+			this.mResultsUpdater = new System.Windows.Forms.Timer(this.components);
+			this.mNoResultsLabel = new System.Windows.Forms.Label();
+			this.mLayout.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).BeginInit();
+			this.mInfoBanner.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).BeginInit();
+			this.SuspendLayout();
+			// 
+			// mSearch
+			// 
+			this.mSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mSearch.Location = new System.Drawing.Point(1, 78);
+			this.mSearch.Margin = new System.Windows.Forms.Padding(1, 0, 1, 0);
+			this.mSearch.Name = "mSearch";
+			this.mSearch.Size = new System.Drawing.Size(521, 20);
+			this.mSearch.TabIndex = 0;
+			this.mSearch.LocationChanged += new System.EventHandler(this.mSearch_LocationChanged);
+			this.mSearch.TextChanged += new System.EventHandler(this.mSearch_TextChanged);
+			// 
+			// mResults
+			// 
+			this.mResults.BorderStyle = System.Windows.Forms.BorderStyle.None;
+			this.mResults.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mResults.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
+			this.mResults.FormattingEnabled = true;
+			this.mResults.IntegralHeight = false;
+			this.mResults.Location = new System.Drawing.Point(0, 98);
+			this.mResults.Margin = new System.Windows.Forms.Padding(0);
+			this.mResults.Name = "mResults";
+			this.mResults.Size = new System.Drawing.Size(523, 176);
+			this.mResults.TabIndex = 1;
+			this.mResults.TabStop = false;
+			this.mResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseClick);
+			this.mResults.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.mResults_DrawItem);
+			this.mResults.LocationChanged += new System.EventHandler(this.mResults_LocationChanged);
+			this.mResults.MouseEnter += new System.EventHandler(this.mResults_MouseEnter);
+			this.mResults.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseMove);
+			// 
+			// mLayout
+			// 
+			this.mLayout.ColumnCount = 1;
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+			this.mLayout.Controls.Add(this.mSearch, 0, 2);
+			this.mLayout.Controls.Add(this.mResults, 0, 3);
+			this.mLayout.Controls.Add(this.mBanner, 0, 0);
+			this.mLayout.Controls.Add(this.mInfoBanner, 0, 1);
+			this.mLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mLayout.Location = new System.Drawing.Point(0, 0);
+			this.mLayout.Name = "mLayout";
+			this.mLayout.RowCount = 4;
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.Size = new System.Drawing.Size(523, 274);
+			this.mLayout.TabIndex = 2;
+			// 
+			// mBanner
+			// 
+			this.mBanner.Dock = System.Windows.Forms.DockStyle.Top;
+			this.mBanner.Location = new System.Drawing.Point(0, 0);
+			this.mBanner.Margin = new System.Windows.Forms.Padding(0);
+			this.mBanner.Name = "mBanner";
+			this.mBanner.Size = new System.Drawing.Size(523, 60);
+			this.mBanner.TabIndex = 3;
+			this.mBanner.TabStop = false;
+			this.mBanner.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mBannerImage_MouseDown);
+			// 
+			// mInfoBanner
+			// 
+			this.mInfoBanner.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+			this.mInfoBanner.BackColor = System.Drawing.SystemColors.Info;
+			this.mInfoBanner.Controls.Add(this.mInfoLabel);
+			this.mInfoBanner.Controls.Add(this.mInfoBannerImage);
+			this.mInfoBanner.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoBanner.Location = new System.Drawing.Point(2, 61);
+			this.mInfoBanner.Margin = new System.Windows.Forms.Padding(2, 1, 1, 1);
+			this.mInfoBanner.Name = "mInfoBanner";
+			this.mInfoBanner.Size = new System.Drawing.Size(520, 16);
+			this.mInfoBanner.TabIndex = 8;
+			// 
+			// mInfoLabel
+			// 
+			this.mInfoLabel.AutoEllipsis = true;
+			this.mInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoLabel.ForeColor = System.Drawing.SystemColors.InfoText;
+			this.mInfoLabel.Location = new System.Drawing.Point(16, 0);
+			this.mInfoLabel.Name = "mInfoLabel";
+			this.mInfoLabel.Size = new System.Drawing.Size(504, 16);
+			this.mInfoLabel.TabIndex = 6;
+			this.mInfoLabel.Text = "AutoType failed to find";
+			// 
+			// mInfoBannerImage
+			// 
+			this.mInfoBannerImage.Dock = System.Windows.Forms.DockStyle.Left;
+			this.mInfoBannerImage.Image = global::AutoTypeSearch.Properties.Resources.Info;
+			this.mInfoBannerImage.Location = new System.Drawing.Point(0, 0);
+			this.mInfoBannerImage.Margin = new System.Windows.Forms.Padding(0);
+			this.mInfoBannerImage.Name = "mInfoBannerImage";
+			this.mInfoBannerImage.Size = new System.Drawing.Size(16, 16);
+			this.mInfoBannerImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mInfoBannerImage.TabIndex = 7;
+			this.mInfoBannerImage.TabStop = false;
+			// 
+			// mThrobber
+			// 
+			this.mThrobber.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.mThrobber.BackColor = System.Drawing.SystemColors.Window;
+			this.mThrobber.Location = new System.Drawing.Point(503, 81);
+			this.mThrobber.Name = "mThrobber";
+			this.mThrobber.Size = new System.Drawing.Size(16, 16);
+			this.mThrobber.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mThrobber.TabIndex = 4;
+			this.mThrobber.TabStop = false;
+			this.mThrobber.Visible = false;
+			// 
+			// mResultsUpdater
+			// 
+			this.mResultsUpdater.Interval = 250;
+			this.mResultsUpdater.Tick += new System.EventHandler(this.mResultsUpdater_Tick);
+			// 
+			// mNoResultsLabel
+			// 
+			this.mNoResultsLabel.AutoSize = true;
+			this.mNoResultsLabel.Location = new System.Drawing.Point(5, 103);
+			this.mNoResultsLabel.Name = "mNoResultsLabel";
+			this.mNoResultsLabel.Size = new System.Drawing.Size(84, 13);
+			this.mNoResultsLabel.TabIndex = 5;
+			this.mNoResultsLabel.Text = "No results found";
+			// 
+			// SearchWindow
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.BackColor = System.Drawing.SystemColors.Window;
+			this.ClientSize = new System.Drawing.Size(523, 274);
+			this.ControlBox = false;
+			this.Controls.Add(this.mNoResultsLabel);
+			this.Controls.Add(this.mThrobber);
+			this.Controls.Add(this.mLayout);
+			this.MinimumSize = new System.Drawing.Size(160, 96);
+			this.Name = "SearchWindow";
+			this.ShowInTaskbar = false;
+			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+			this.TopMost = true;
+			this.mLayout.ResumeLayout(false);
+			this.mLayout.PerformLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).EndInit();
+			this.mInfoBanner.ResumeLayout(false);
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).EndInit();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.TextBox mSearch;
+		private System.Windows.Forms.ListBox mResults;
+		private System.Windows.Forms.TableLayoutPanel mLayout;
+		private System.Windows.Forms.PictureBox mBanner;
+		private PictureBox mThrobber;
+		private Timer mResultsUpdater;
+		private Label mNoResultsLabel;
+		private Label mInfoLabel;
+		private Panel mInfoBanner;
+		private PictureBox mInfoBannerImage;
+	}
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/AutoTypeSearch/SearchResults.cs b/AutoTypeSearch/SearchResults.cs
new file mode 100755
index 0000000..b2b0529
--- /dev/null
+++ b/AutoTypeSearch/SearchResults.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePass.Util.Spr;
+using KeePassLib;
+using KeePassLib.Utility;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResults
+	{
+		private readonly string mTerm;
+		private readonly SearchResult[] mResults;
+
+		private readonly object mLock = new object();
+		private volatile int mCount;
+		private volatile bool mComplete;
+
+		private readonly AutoResetEvent mResultsUpdated = new AutoResetEvent(false);
+
+		private readonly CompareOptions mStringComparison;
+		private readonly bool mSearchTitle;
+		private readonly bool mSearchUserName;
+		private readonly bool mSearchUrl;
+		private readonly bool mSearchNotes;
+		private readonly bool mSearchCustomFields;
+		private readonly bool mResolveReferences;
+		private readonly bool mSearchTags;
+
+		public SearchResults(int capacity, string term)
+		{
+			mTerm = term;
+			mResults = new SearchResult[capacity];
+
+			mStringComparison = Settings.Default.CaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase;
+			mStringComparison |= CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace;
+			mSearchTitle = Settings.Default.SearchTitle;
+			mSearchUserName = Settings.Default.SearchUserName;
+			mSearchUrl = Settings.Default.SearchUrl;
+			mSearchNotes = Settings.Default.SearchNotes;
+			mSearchCustomFields = Settings.Default.SearchCustomFields;
+			mSearchTags = Settings.Default.SearchTags;
+			mResolveReferences = Settings.Default.ResolveReferences;
+		}
+
+		/// 
+		/// Gets an ordered list of fields to search for the term
+		/// 
+		/// 
+		/// 
+		private IEnumerable GetFieldsToSearch(PwEntry entry)
+		{
+			var fieldsToSearch = new List((int)entry.Strings.UCount);
+			if (mSearchTitle) fieldsToSearch.Add(PwDefs.TitleField);
+			if (mSearchUserName) fieldsToSearch.Add(PwDefs.UserNameField);
+			if (mSearchUrl) fieldsToSearch.Add(PwDefs.UrlField);
+			if (mSearchNotes) fieldsToSearch.Add(PwDefs.NotesField);
+			if (mSearchCustomFields)
+			{
+				foreach (var stringEntry in entry.Strings)
+				{
+					if (!stringEntry.Value.IsProtected && !PwDefs.IsStandardField(stringEntry.Key))
+					{
+						fieldsToSearch.Add(stringEntry.Key);
+					}
+				}
+			}
+			if (mSearchTags) fieldsToSearch.Add(AutoTypeSearchExt.TagsVirtualFieldName);
+
+			return fieldsToSearch;
+		}
+
+		public void AddResultIfMatchesTerm(PwDatabase context, PwEntry entry)
+		{
+			// First try without resolving
+			var addedResult = AddResultIfMatchesTerm(context, entry, false);
+
+			if (!addedResult && mResolveReferences)
+			{
+				// Not found without resolving, so try resolving
+				AddResultIfMatchesTerm(context, entry, true);
+			}
+		}
+
+		private bool AddResultIfMatchesTerm(PwDatabase context, PwEntry entry, bool resolveReferences)
+		{
+			foreach (var fieldName in GetFieldsToSearch(entry))
+			{
+				string fieldValue;
+				if (fieldName == AutoTypeSearchExt.TagsVirtualFieldName)
+				{
+					fieldValue = StrUtil.TagsToString(entry.Tags, true);
+				}
+				else
+				{
+					fieldValue = entry.Strings.ReadSafeEx(fieldName);
+
+					if (resolveReferences)
+					{
+						fieldValue = ResolveReferences(context, entry, fieldValue);
+					}
+				}
+
+				if (!String.IsNullOrEmpty(fieldValue))
+				{
+					var foundIndex = CultureInfo.CurrentCulture.CompareInfo.IndexOf(fieldValue, mTerm, mStringComparison);
+					if (foundIndex >= 0)
+					{
+						// Found a match, create a search result and add it
+						AddResult(new SearchResult(context, entry, entry.Strings.ReadSafe(PwDefs.TitleField), fieldName, fieldValue, foundIndex, mTerm.Length));
+						return true;
+					}
+				}
+			}
+			return false;
+		}
+
+		/// 
+		/// Resolves any references in the field value and returns it. If there were no references,
+		/// returns null (to avoid duplicate searching - it is assumed that the unresolved value has already been searched)
+		/// 
+		private string ResolveReferences(PwDatabase context, PwEntry entry, string fieldValue)
+		{
+			if (fieldValue.IndexOf('{') < 0)
+			{
+				// Can't contain any references
+				return null;
+			}
+			
+			var sprContext = new SprContext(entry, context, SprCompileFlags.Deref) { ForcePlainTextPasswords = false };
+
+			var result = SprEngine.Compile(fieldValue, sprContext);
+			if (CultureInfo.CurrentCulture.CompareInfo.Compare(result,fieldValue, mStringComparison) == 0)
+			{
+				return null;
+			}
+			
+			return result;
+		}
+
+		public void AddResultIfMatchesTerm(SearchResult candidate)
+		{
+			// First see whether the existing candidate is a further match in the same place
+			var fieldValue = candidate.FieldValue;
+			if (fieldValue.Length > candidate.Start + mTerm.Length && CultureInfo.CurrentCulture.CompareInfo.Compare(fieldValue.Substring(candidate.Start, mTerm.Length), mTerm, mStringComparison) == 0)
+			{
+				// Yep, match continues, so add it.
+				AddResult(new SearchResult(candidate.Database, candidate.Entry, candidate.Title, candidate.FieldName, fieldValue, candidate.Start, mTerm.Length));
+			}
+			else
+			{
+				// Existing candidate match couldn't be extended, so search from scratch again
+				AddResultIfMatchesTerm(candidate.Database, candidate.Entry);
+			}
+		}
+
+		private void AddResult(SearchResult result)
+		{
+			lock (mLock)
+			{
+				if (mComplete)
+				{
+					throw new InvalidOperationException("Search results have been completed");
+				}
+				result.SetResultIndex(mCount);
+				mResults[mCount++] = result;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Indicates that the results are complete, and no more will be added.
+		/// 
+		public void SetComplete()
+		{
+			lock (mLock)
+			{
+				mComplete = true;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Gets all the available results so far.
+		/// 
+		/// Index to start returning from. Modified to be the first index not available yet on return.
+		/// Set to true if the results are complete, false if more results are pending but have not been returned.
+		/// 
+		public SearchResult[] GetAvailableResults(ref int index, out bool complete)
+		{
+			int count;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			if (count <= index)
+			{
+				return new SearchResult[0];
+			}
+
+			var availableResults = new SearchResult[count - index];
+			Array.Copy(mResults, index, availableResults, 0, availableResults.Length);
+			index = count;
+
+			return availableResults;
+		}
+
+		/// 
+		/// Gets all the results. Will block until complete.
+		/// 
+		/// 
+		public IEnumerable GetAllResults()
+		{
+			int count = -1;
+
+			for (var i = 0; i < mResults.Length; i++)
+			{
+				if (i > count)
+				{
+					// Reached the limit of availability so far, so see if more is available
+					do
+					{
+						bool moreAvailable, complete;
+
+						lock (mLock)
+						{
+							moreAvailable = mCount > count;
+							count = mCount;
+							complete = mComplete;
+						}
+
+						if (!moreAvailable)
+						{
+							if (complete)
+							{
+								// No more available, but the results are now complete anyway
+								yield break;
+							}
+
+							// No more available yet, not yet complete, wait until more becomes available
+							mResultsUpdated.WaitOne();
+						}
+						else
+						{
+							// More available now, so stop checking for more, continue with the loop to return them
+							break;
+						}
+					} while (true);
+
+					Debug.Assert(i <= count, "More should be available now");
+				}
+
+				yield return mResults[i];
+			}
+		}
+
+		public SearchResults CreateChildResults(string term)
+		{
+			Debug.Assert(term.StartsWith(mTerm));
+
+			int count;
+			bool complete;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			// If complete, then we know we don't need more than count. Otherwise, it can't be more than this capacity anyway
+			var childCapacity = complete ? count : mResults.Length;
+
+			return new SearchResults(childCapacity, term);
+		}
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.Designer.cs b/AutoTypeSearch/SearchWindow.Designer.cs
new file mode 100755
index 0000000..18b37d1
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.Designer.cs
@@ -0,0 +1,201 @@
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	partial class SearchWindow
+	{
+		/// 
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		#region Windows Form Designer generated code
+
+		/// 
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			this.components = new System.ComponentModel.Container();
+			this.mSearch = new System.Windows.Forms.TextBox();
+			this.mResults = new System.Windows.Forms.ListBox();
+			this.mLayout = new System.Windows.Forms.TableLayoutPanel();
+			this.mBanner = new System.Windows.Forms.PictureBox();
+			this.mInfoBanner = new System.Windows.Forms.Panel();
+			this.mInfoLabel = new System.Windows.Forms.Label();
+			this.mInfoBannerImage = new System.Windows.Forms.PictureBox();
+			this.mThrobber = new System.Windows.Forms.PictureBox();
+			this.mResultsUpdater = new System.Windows.Forms.Timer(this.components);
+			this.mNoResultsLabel = new System.Windows.Forms.Label();
+			this.mLayout.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).BeginInit();
+			this.mInfoBanner.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).BeginInit();
+			this.SuspendLayout();
+			// 
+			// mSearch
+			// 
+			this.mSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mSearch.Location = new System.Drawing.Point(1, 78);
+			this.mSearch.Margin = new System.Windows.Forms.Padding(1, 0, 1, 0);
+			this.mSearch.Name = "mSearch";
+			this.mSearch.Size = new System.Drawing.Size(521, 20);
+			this.mSearch.TabIndex = 0;
+			this.mSearch.LocationChanged += new System.EventHandler(this.mSearch_LocationChanged);
+			this.mSearch.TextChanged += new System.EventHandler(this.mSearch_TextChanged);
+			// 
+			// mResults
+			// 
+			this.mResults.BorderStyle = System.Windows.Forms.BorderStyle.None;
+			this.mResults.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mResults.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
+			this.mResults.FormattingEnabled = true;
+			this.mResults.IntegralHeight = false;
+			this.mResults.Location = new System.Drawing.Point(0, 98);
+			this.mResults.Margin = new System.Windows.Forms.Padding(0);
+			this.mResults.Name = "mResults";
+			this.mResults.Size = new System.Drawing.Size(523, 176);
+			this.mResults.TabIndex = 1;
+			this.mResults.TabStop = false;
+			this.mResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseClick);
+			this.mResults.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.mResults_DrawItem);
+			this.mResults.LocationChanged += new System.EventHandler(this.mResults_LocationChanged);
+			this.mResults.MouseEnter += new System.EventHandler(this.mResults_MouseEnter);
+			this.mResults.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseMove);
+			// 
+			// mLayout
+			// 
+			this.mLayout.ColumnCount = 1;
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+			this.mLayout.Controls.Add(this.mSearch, 0, 2);
+			this.mLayout.Controls.Add(this.mResults, 0, 3);
+			this.mLayout.Controls.Add(this.mBanner, 0, 0);
+			this.mLayout.Controls.Add(this.mInfoBanner, 0, 1);
+			this.mLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mLayout.Location = new System.Drawing.Point(0, 0);
+			this.mLayout.Name = "mLayout";
+			this.mLayout.RowCount = 4;
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.Size = new System.Drawing.Size(523, 274);
+			this.mLayout.TabIndex = 2;
+			// 
+			// mBanner
+			// 
+			this.mBanner.Dock = System.Windows.Forms.DockStyle.Top;
+			this.mBanner.Location = new System.Drawing.Point(0, 0);
+			this.mBanner.Margin = new System.Windows.Forms.Padding(0);
+			this.mBanner.Name = "mBanner";
+			this.mBanner.Size = new System.Drawing.Size(523, 60);
+			this.mBanner.TabIndex = 3;
+			this.mBanner.TabStop = false;
+			this.mBanner.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mBannerImage_MouseDown);
+			// 
+			// mInfoBanner
+			// 
+			this.mInfoBanner.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+			this.mInfoBanner.BackColor = System.Drawing.SystemColors.Info;
+			this.mInfoBanner.Controls.Add(this.mInfoLabel);
+			this.mInfoBanner.Controls.Add(this.mInfoBannerImage);
+			this.mInfoBanner.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoBanner.Location = new System.Drawing.Point(2, 61);
+			this.mInfoBanner.Margin = new System.Windows.Forms.Padding(2, 1, 1, 1);
+			this.mInfoBanner.Name = "mInfoBanner";
+			this.mInfoBanner.Size = new System.Drawing.Size(520, 16);
+			this.mInfoBanner.TabIndex = 8;
+			// 
+			// mInfoLabel
+			// 
+			this.mInfoLabel.AutoEllipsis = true;
+			this.mInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoLabel.ForeColor = System.Drawing.SystemColors.InfoText;
+			this.mInfoLabel.Location = new System.Drawing.Point(16, 0);
+			this.mInfoLabel.Name = "mInfoLabel";
+			this.mInfoLabel.Size = new System.Drawing.Size(504, 16);
+			this.mInfoLabel.TabIndex = 6;
+			this.mInfoLabel.Text = "AutoType failed to find";
+			// 
+			// mInfoBannerImage
+			// 
+			this.mInfoBannerImage.Dock = System.Windows.Forms.DockStyle.Left;
+			this.mInfoBannerImage.Image = global::AutoTypeSearch.Properties.Resources.Info;
+			this.mInfoBannerImage.Location = new System.Drawing.Point(0, 0);
+			this.mInfoBannerImage.Margin = new System.Windows.Forms.Padding(0);
+			this.mInfoBannerImage.Name = "mInfoBannerImage";
+			this.mInfoBannerImage.Size = new System.Drawing.Size(16, 16);
+			this.mInfoBannerImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mInfoBannerImage.TabIndex = 7;
+			this.mInfoBannerImage.TabStop = false;
+			// 
+			// mThrobber
+			// 
+			this.mThrobber.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.mThrobber.BackColor = System.Drawing.SystemColors.Window;
+			this.mThrobber.Location = new System.Drawing.Point(503, 81);
+			this.mThrobber.Name = "mThrobber";
+			this.mThrobber.Size = new System.Drawing.Size(16, 16);
+			this.mThrobber.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mThrobber.TabIndex = 4;
+			this.mThrobber.TabStop = false;
+			this.mThrobber.Visible = false;
+			// 
+			// mResultsUpdater
+			// 
+			this.mResultsUpdater.Interval = 250;
+			this.mResultsUpdater.Tick += new System.EventHandler(this.mResultsUpdater_Tick);
+			// 
+			// mNoResultsLabel
+			// 
+			this.mNoResultsLabel.AutoSize = true;
+			this.mNoResultsLabel.Location = new System.Drawing.Point(5, 103);
+			this.mNoResultsLabel.Name = "mNoResultsLabel";
+			this.mNoResultsLabel.Size = new System.Drawing.Size(84, 13);
+			this.mNoResultsLabel.TabIndex = 5;
+			this.mNoResultsLabel.Text = "No results found";
+			// 
+			// SearchWindow
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.BackColor = System.Drawing.SystemColors.Window;
+			this.ClientSize = new System.Drawing.Size(523, 274);
+			this.ControlBox = false;
+			this.Controls.Add(this.mNoResultsLabel);
+			this.Controls.Add(this.mThrobber);
+			this.Controls.Add(this.mLayout);
+			this.MinimumSize = new System.Drawing.Size(160, 96);
+			this.Name = "SearchWindow";
+			this.ShowInTaskbar = false;
+			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+			this.TopMost = true;
+			this.mLayout.ResumeLayout(false);
+			this.mLayout.PerformLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).EndInit();
+			this.mInfoBanner.ResumeLayout(false);
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).EndInit();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.TextBox mSearch;
+		private System.Windows.Forms.ListBox mResults;
+		private System.Windows.Forms.TableLayoutPanel mLayout;
+		private System.Windows.Forms.PictureBox mBanner;
+		private PictureBox mThrobber;
+		private Timer mResultsUpdater;
+		private Label mNoResultsLabel;
+		private Label mInfoLabel;
+		private Panel mInfoBanner;
+		private PictureBox mInfoBannerImage;
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchWindow.cs b/AutoTypeSearch/SearchWindow.cs
new file mode 100755
index 0000000..363b898
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.cs
@@ -0,0 +1,925 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Media;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Resources;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Collections;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	public partial class SearchWindow : Form
+	{
+		private const int SecondLineInset = 10;
+
+		// HACK to work around mono bug
+		private static readonly FieldInfo sMonoListBoxTopIndex = typeof(ListBox).GetField("top_index", BindingFlags.Instance | BindingFlags.NonPublic);
+
+		private readonly MainForm mMainForm;
+		private readonly Bitmap mBannerImage;
+		private readonly Searcher mSearcher;
+
+		private readonly Stream mThrobberImageStream;
+
+		private int? mWindowTopBorderHeight;
+		private int mBannerWidth = -1;
+		private int mMaximumExpandHeight;
+		private bool mManualSizeApplied;
+		private SearchResults mCurrentSearch;
+		private SearchResults mLastResultsUpdated;
+		private int mLastResultsUpdatedNextAvailableIndex;
+
+		#region Opening
+		public SearchWindow()
+		{
+			InitializeComponent();
+
+			// Mono can't load animated gifs from resx without crashing, so load it from an embedded resource instead
+			try
+			{
+				mThrobberImageStream = GetType().Assembly.GetManifestResourceStream("AutoTypeSearch.Throbber.gif");
+				if (mThrobberImageStream != null)
+				{
+					mThrobber.Image = Image.FromStream(mThrobberImageStream);
+				}
+			}
+			catch (Exception ex)
+			{
+				Debug.Fail("Failed to load Throbber.gif from embedded resource: " + ex.Message);
+			}
+
+			GlobalWindowManager.CustomizeControl(this);
+			UIUtil.SetExplorerTheme(mResults, true);
+			SetItemHeight();
+		}
+
+		public SearchWindow(MainForm mainForm, string infoBanner) : this()
+		{
+			mMainForm = mainForm;
+
+			mInfoBanner.Height = Math.Max(mInfoBannerImage.Height, mInfoLabel.Font.Height) + mInfoBanner.Margin.Vertical;
+			mInfoLabel.Padding = new Padding(0, (mInfoBanner.Height - mInfoLabel.Font.Height) / 2, 0, 0);
+			mInfoLabel.Text = infoBanner;
+
+			if (infoBanner == null)
+			{
+				mInfoBanner.Visible = false;
+				mInfoBanner.Height = 0;
+			}
+			
+			mSearcher = new Searcher(mMainForm.DocumentManager.GetOpenDatabases().ToArray());
+
+			Icon = mMainForm.Icon;
+			using (var bannerIcon = new Icon(Icon, 48, 48))
+			{
+				mBannerImage = bannerIcon.ToBitmap();
+			}
+			UpdateBanner();
+
+			ShowThrobber = false;
+
+			FontUtil.AssignDefaultItalic(mNoResultsLabel);
+		}
+
+
+		protected override void OnCreateControl()
+		{
+			base.OnCreateControl();
+
+			if (NativeMethods.IsWindows10())
+			{
+				mWindowTopBorderHeight = PointToScreen(Point.Empty).Y - this.Top;
+				NativeMethods.RefreshWindowFrame(Handle);
+			}
+
+			var windowRect = Settings.Default.WindowPosition;
+			var collapsedWindowRect = windowRect;
+			
+			collapsedWindowRect.Height = mSearch.Bottom + (Height - ClientSize.Height);
+
+			MinimumSize = new Size(MinimumSize.Width, collapsedWindowRect.Height);
+
+			if (windowRect.IsEmpty || !IsOnScreen(collapsedWindowRect))
+			{
+				windowRect = new Rectangle(0, 0, Width, Height);
+				Height = collapsedWindowRect.Height;
+
+				CenterToScreen();
+			}
+			else
+			{
+				Location = windowRect.Location;
+				Size = collapsedWindowRect.Size;
+			}
+
+			mMaximumExpandHeight = Math.Max(windowRect.Height, MinimumSize.Height + mResults.ItemHeight);
+		}
+		
+
+		private static bool IsOnScreen(Rectangle rectangle)
+		{
+			return Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(rectangle));
+		}
+
+		private void SetItemHeight()
+		{
+			mResults.ItemHeight = mResults.Font.Height * 2 + 2;
+		}
+
+		protected override void WndProc(ref Message m)
+		{
+			if (mWindowTopBorderHeight.HasValue)
+			{
+				NativeMethods.RemoveWindowFrameTopBorder(ref m, mWindowTopBorderHeight.Value);
+			}
+			base.WndProc(ref m);
+		}
+
+		#endregion
+
+		#region Closing
+		protected override void OnActivated(EventArgs e)
+		{
+			base.OnActivated(e);
+			Deactivate += OnDeactivate;
+		}
+
+		private void OnDeactivate(object sender, EventArgs eventArgs)
+		{
+			Close();
+		}
+
+		protected override void OnClosed(EventArgs e)
+		{
+			Deactivate -= OnDeactivate;
+			base.OnClosed(e);
+		}
+
+		/// 
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				if (mBannerImage != null)
+				{
+					mBannerImage.Dispose();
+				}
+				if (mThrobber.Image != null)
+				{
+					mThrobber.Image.Dispose();
+					mThrobber.Image = null;
+					mThrobberImageStream.Dispose();
+				}
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+		#endregion
+
+		#region Item Drawing
+		private void mResults_DrawItem(object sender, DrawItemEventArgs e)
+		{
+			var searchResult = mResults.Items[e.Index] as SearchResult;
+			if (searchResult == null)
+			{
+				Debug.Fail("Unexpected item in mResults");
+// ReSharper disable once HeuristicUnreachableCode - Not unreachable
+				return;
+			}
+			var drawingArea = e.Bounds;
+			drawingArea.Height--; // Leave room for a dividing line at the bottom
+			
+			if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
+			{
+				DrawBorderedRectangle(e.Graphics, drawingArea, SystemColors.Highlight);
+			}
+			else
+			{
+				e.Graphics.FillRectangle(SystemBrushes.Window, drawingArea);
+			}
+
+			var image = GetImage(searchResult.Database, searchResult.Entry.CustomIconUuid, searchResult.Entry.IconId);
+			var imageMargin = (drawingArea.Height - image.Height) / 2;
+			e.Graphics.DrawImage(image, drawingArea.Left + imageMargin, drawingArea.Top + imageMargin, image.Width, image.Height);
+
+			var textLeftMargin = drawingArea.Left + imageMargin * 2 + image.Width;
+			var textBounds = new Rectangle(textLeftMargin, drawingArea.Top + 1, drawingArea.Width - textLeftMargin - 1, drawingArea.Height - 2);
+
+			var line1Bounds = textBounds;
+			line1Bounds.Height = e.Font.Height;
+			var line2Bounds = line1Bounds;
+			line2Bounds.Y += line2Bounds.Height - 1;
+			line2Bounds.X += SecondLineInset;
+			line2Bounds.Width -= SecondLineInset;
+
+			var resultInTitleField = searchResult.FieldName == PwDefs.TitleField;
+
+			var title = (resultInTitleField ? searchResult.FieldValue : searchResult.Title).Replace('\n', ' '); // The FieldValue may have references resolved, whereas the title is always read directly.
+
+			var uniqueTitlePartWidth = 0;
+			if (!String.IsNullOrEmpty(searchResult.UniqueTitlePart))
+			{
+				var uniqueTitlePart = searchResult.UniqueTitlePart.Replace('\n', ' ');
+
+				var titleWidth = TextRenderer.MeasureText(e.Graphics, title, e.Font, line1Bounds.Size, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+
+				var availableWidthForUniqueTitlePart = line1Bounds.Width - titleWidth;
+				if (availableWidthForUniqueTitlePart > 20) // Don't bother including a unique part if there's no room for it
+				{
+					var uniqueTitlePartReversed = ReverseString(uniqueTitlePart);
+
+					uniqueTitlePartWidth = TextRenderer.MeasureText(e.Graphics, uniqueTitlePartReversed, e.Font, new Size(availableWidthForUniqueTitlePart, line1Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+					uniqueTitlePart = ReverseString(uniqueTitlePartReversed);
+
+					TextRenderer.DrawText(e.Graphics, uniqueTitlePart, e.Font, new Rectangle(line1Bounds.X, line1Bounds.Y, uniqueTitlePartWidth, line1Bounds.Height), SystemColors.GrayText, TextFormatFlags.NoPadding);
+				}
+			}
+
+			var titleBounds = new Rectangle(line1Bounds.X + uniqueTitlePartWidth, line1Bounds.Y, line1Bounds.Width - uniqueTitlePartWidth, line1Bounds.Height);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Highlight title in first line.
+				DrawHighlight(e, titleBounds, title, searchResult.Start, searchResult.Length);
+			}
+
+			TextRenderer.DrawText(e.Graphics, searchResult.Title, e.Font, titleBounds, SystemColors.WindowText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Use Username for second line.
+				TextRenderer.DrawText(e.Graphics, KPRes.UserName + ": " + searchResult.Entry.Strings.ReadSafeEx(PwDefs.UserNameField), e.Font, line2Bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+			}
+			else
+			{
+				// Found the result in not title field. Show the matching result on second line
+				
+				var fieldValue = searchResult.FieldValue.Replace('\n',' ');
+				var fieldNamePrefix = GetDisplayFieldName(searchResult.FieldName) + ": ";
+
+				var remainingSpace = line2Bounds.Width;
+				var fieldNamePrefixWidth = TextRenderer.MeasureText(e.Graphics, fieldNamePrefix, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+				remainingSpace -= fieldNamePrefixWidth;
+
+				int fieldValueHighlightWidth = 0, fieldValueLeftContextWidth = 0, fieldValueRightContextWidth = 0;
+
+				var leftContext = fieldValue.Substring(0, searchResult.Start);
+				var highlight = fieldValue.Substring(searchResult.Start, searchResult.Length);
+				var rightContext = fieldValue.Substring(searchResult.Start + searchResult.Length);
+
+				if (searchResult.Length == 0)
+				{
+					fieldValueHighlightWidth = remainingSpace;
+				}
+				else
+				{
+					if (remainingSpace > 0)
+					{
+						var availableSpace = remainingSpace;
+						fieldValueHighlightWidth = TextRenderer.MeasureText(e.Graphics, highlight, e.Font, new Size(availableSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						remainingSpace -= fieldValueHighlightWidth;
+					}
+
+					// Of the space remaining, divide it equally between that which comes before, and that which comes after
+					if (!String.IsNullOrEmpty(leftContext))
+					{
+						var leftContextReversed = ReverseString(leftContext);
+						fieldValueLeftContextWidth = TextRenderer.MeasureText(e.Graphics, leftContextReversed, e.Font, new Size(remainingSpace / 2, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+						if (fieldValueLeftContextWidth > remainingSpace)
+						{
+							// Always allow space for the minimal left context
+							fieldValueHighlightWidth -= (fieldValueLeftContextWidth - remainingSpace);
+							remainingSpace = 0;
+						}
+						else
+						{
+							remainingSpace -= fieldValueLeftContextWidth;							
+						}
+						
+						// Replace left context with the truncated reversed left context.
+						leftContext = ReverseString(leftContextReversed);
+					}
+
+					if (remainingSpace > 0 && !String.IsNullOrEmpty(rightContext))
+					{
+						fieldValueRightContextWidth = TextRenderer.MeasureText(e.Graphics, rightContext, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						if (fieldValueRightContextWidth > remainingSpace)
+						{
+							fieldValueRightContextWidth = 0;
+						}
+					}
+				}
+
+				// Now draw it all
+				var bounds = line2Bounds;
+				bounds.Width = fieldNamePrefixWidth;
+				TextRenderer.DrawText(e.Graphics, fieldNamePrefix, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				if (fieldValueLeftContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueLeftContextWidth;
+					TextRenderer.DrawText(e.Graphics, leftContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding); // No ellipsis as the leftContext string has already been truncated appropriately
+				}
+				if (fieldValueHighlightWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueHighlightWidth;
+
+					if (searchResult.Length > 0)
+					{
+						DrawHighlightRectangle(e, bounds);
+					}
+					TextRenderer.DrawText(e.Graphics, highlight, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+				if (fieldValueRightContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueRightContextWidth;
+					TextRenderer.DrawText(e.Graphics, rightContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+			}
+
+			e.Graphics.DrawLine(SystemPens.ButtonFace, drawingArea.Left, drawingArea.Bottom, drawingArea.Right, drawingArea.Bottom);
+		}
+
+		private static string ReverseString(string value)
+		{
+			return new String(value.ToCharArray().TakeWhile(c => c != '\0').Reverse().ToArray());
+		}
+
+		private static void DrawHighlight(DrawItemEventArgs e, Rectangle lineBounds, string text, int highlightFrom, int highlightLength)
+		{
+			var highlightX = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width;
+			var highlightWidth = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom + highlightLength), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width - highlightX;
+
+			DrawHighlightRectangle(e, new Rectangle(lineBounds.Left + highlightX, lineBounds.Top, highlightWidth, lineBounds.Height));
+		}
+
+		private static void DrawHighlightRectangle(DrawItemEventArgs e, Rectangle rectangle)
+		{
+			DrawBorderedRectangle(e.Graphics, rectangle, Color.PaleTurquoise);
+		}
+
+		private static void DrawBorderedRectangle(Graphics graphics, Rectangle rectangle, Color colour)
+		{
+			var border = rectangle;
+			border.Width--;
+			border.Height--;
+
+			using (var brush = new SolidBrush(MergeColors(colour, SystemColors.Window, 0.2)))
+			{
+				graphics.FillRectangle(brush, rectangle);
+			}
+			using (var pen = new Pen(colour, 1f))
+			{
+				graphics.DrawRectangle(pen, border);
+			}
+		}
+
+		private Image GetImage(PwDatabase database, PwUuid customIconId, PwIcon iconId)
+		{
+			Image image = null;
+			if (!customIconId.Equals(PwUuid.Zero))
+			{
+				image = database.GetCustomIcon(customIconId, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16));
+			}
+			if (image == null)
+			{
+				try { image = mMainForm.ClientIcons.Images[(int)iconId]; }
+				catch (Exception) { Debug.Assert(false); }
+			}
+
+			return image;
+		}
+
+		private static string GetDisplayFieldName(string fieldName)
+		{
+			switch (fieldName)
+			{
+				case PwDefs.TitleField:
+					return KPRes.Title;
+				case PwDefs.UserNameField:
+					return KPRes.UserName;
+				case PwDefs.PasswordField:
+					return KPRes.Password;
+				case PwDefs.UrlField:
+					return KPRes.Url;
+				case PwDefs.NotesField:
+					return KPRes.Notes;
+				case AutoTypeSearchExt.TagsVirtualFieldName:
+					return KPRes.Tags;
+				default:
+					return fieldName;
+			}
+		}
+
+		public static Color MergeColors(Color from, Color to, double amount)
+		{
+			var r = (byte)((from.R * amount) + to.R * (1 - amount));
+			var g = (byte)((from.G * amount) + to.G * (1 - amount));
+			var b = (byte)((from.B * amount) + to.B * (1 - amount));
+			return Color.FromArgb(r, g, b);
+		}
+		#endregion
+
+		#region Mouse tracking
+		private Point mMouseEntryPosition;
+		
+		private void mResults_MouseEnter(object sender, EventArgs e)
+		{
+			mMouseEntryPosition = MousePosition;
+		}
+
+		private void mResults_MouseMove(object sender, MouseEventArgs e)
+		{
+			// Discard the location the mouse has on entering the control (as it may be that the control has just moved under the mouse, not the other way around)
+			if (MousePosition == mMouseEntryPosition)
+			{
+				return;
+			}
+
+			// Hot tracking
+			var hoverIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (hoverIndex >= 0 && mResults.SelectedIndex != hoverIndex)
+			{
+				if (mResults.GetItemRectangle(hoverIndex).Bottom <= mResults.ClientRectangle.Bottom)
+				{
+					mResults.SelectedIndex = hoverIndex;
+				}
+				else
+				{
+					// Avoid the control scrolling
+					mResults.BeginUpdate();
+					var topIndex = mResults.TopIndex;
+					mResults.SelectedIndex = hoverIndex;
+					mResults.TopIndex = topIndex;
+					mResults.EndUpdate();
+				}
+			}
+		}
+		#endregion
+
+		#region Resizing
+		protected override void OnResizeBegin(EventArgs e)
+		{
+			// Stop automatically sizing - the user is picking a size they want.
+			mManualSizeApplied = true;
+			base.OnResizeBegin(e);
+		}
+
+		protected override void OnResize(EventArgs e)
+		{
+			base.OnResize(e);
+
+			UpdateBanner();
+
+			mResults.Invalidate();
+		}
+
+		protected override void OnResizeEnd(EventArgs e)
+		{
+			base.OnResizeEnd(e);
+
+			if (Height > MinimumSize.Height && Height != mMaximumExpandHeight)
+			{
+				mMaximumExpandHeight = Math.Max(Height, MinimumSize.Height + mResults.ItemHeight);
+			}
+			else
+			{
+				mManualSizeApplied = false;
+			}
+
+			Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+		}
+
+		private void UpdateBanner()
+		{
+			if (mBannerImage != null)
+			{
+				BannerFactory.UpdateBanner(this, mBanner, mBannerImage, PwDefs.ProductName, Resources.BannerText, ref mBannerWidth);
+			}
+		}
+
+		private void mSearch_LocationChanged(object sender, EventArgs e)
+		{
+			mThrobber.Location = new Point(mSearch.Right - mThrobber.Width - mThrobber.Margin.Right, mSearch.Top + (mSearch.Height - mThrobber.Height) / 2);
+		}
+
+		private void mResults_LocationChanged(object sender, EventArgs e)
+		{
+			mNoResultsLabel.Top = mResults.Top + (mResults.ItemHeight - mNoResultsLabel.Height) / 2;
+		}
+		#endregion
+
+		#region Searching
+		private static readonly SearchResultPrecedence SearchResultPrecedenceComparer = new SearchResultPrecedence();
+		private void mSearch_TextChanged(object sender, EventArgs e)
+		{
+			if (mSearch.Text.Length < 2)
+			{
+				// Stop searching
+				mResultsUpdater.Enabled = false;
+				ShowThrobber = false;
+				Height = MinimumSize.Height;
+				mManualSizeApplied = false;
+				mResults.Items.Clear();
+				mLastResultsUpdated = null;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			else
+			{
+				// Start searching
+				mNoResultsLabel.Visible = false;
+				mCurrentSearch = mSearcher.Search(mSearch.Text);
+				mResultsUpdater.Enabled = true;
+				ShowThrobber = true;
+				mResultsUpdater_Tick(null, EventArgs.Empty); // Quick poke just in case the results are already done.
+			}
+		}
+
+		[SuppressMessage("ReSharper", "CoVariantArrayConversion", Justification = "Object arrays for Listbox.Items, known to be of correct type")]
+		private void mResultsUpdater_Tick(object sender, EventArgs e)
+		{
+			if (mLastResultsUpdated != mCurrentSearch)
+			{
+				// Clear out old results and replace with new ones
+				mResults.Items.Clear();
+				mLastResultsUpdated = mCurrentSearch;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			var existingResultsCount = mResults.Items.Count;
+			
+			bool complete;
+			var newResults = mLastResultsUpdated.GetAvailableResults(ref mLastResultsUpdatedNextAvailableIndex, out complete);
+			if (newResults.Length > 0)
+			{
+				mResults.BeginUpdate();
+				
+				SearchResult[] allResults;
+				if (existingResultsCount > 0)
+				{
+					allResults = new SearchResult[existingResultsCount + newResults.Length];
+					mResults.Items.CopyTo(allResults, 0);
+					newResults.CopyTo(allResults, existingResultsCount);
+
+					mResults.Items.Clear();
+				}
+				else
+				{
+					allResults = newResults;
+				}
+
+				CalculateUniqueTitles(allResults);
+
+				Array.Sort(allResults, SearchResultPrecedenceComparer);
+				mResults.Items.AddRange(allResults);
+				
+				mResults.EndUpdate();
+
+				if (allResults.Length > 0)
+				{
+					if (mResults.SelectedIndex == -1)
+					{
+						try
+						{
+							// HACK to work around mono bug
+							if (sMonoListBoxTopIndex != null)
+							{
+								sMonoListBoxTopIndex.SetValue(mResults, 1); // Set the top_index to 1 so that when selected index is set to 0, and calls EnsureVisible(0), it follows the index < top_index pass and not the broken index >= top_index + rows path. 
+							}
+
+							mResults.SelectedIndex = 0;
+							mResults.TopIndex = 0;
+						}
+						catch (Exception ex)
+						{
+							Debug.Fail("Failed to set selection on count of " + allResults.Length + ": " + ex.Message);
+						}
+					}
+
+					if (!mManualSizeApplied)
+					{
+						Height = Math.Min(mMaximumExpandHeight, MinimumSize.Height + (allResults.Length * mResults.ItemHeight));
+					}
+				}
+			}
+
+			if (complete)
+			{
+				ShowThrobber = false;
+				mResultsUpdater.Enabled = false;
+
+				if (mResults.Items.Count == 0)
+				{
+					mNoResultsLabel.Visible = true;
+					Height = MinimumSize.Height + mResults.ItemHeight;
+					mManualSizeApplied = false;
+				}
+			}
+		}
+
+		private void CalculateUniqueTitles(IEnumerable results, int depth = 0)
+		{
+			// Where results have identical titles, include group titles to make them unique
+			depth += 1;
+
+			// First create a lookup by title
+			var titles = new Dictionary>();
+			foreach (var searchResult in results)
+			{
+				List resultsWithSameTitle;
+				if (titles.TryGetValue(searchResult.UniqueTitle, out resultsWithSameTitle))
+				{
+					resultsWithSameTitle.Add(searchResult);
+				}
+				else
+				{
+					titles.Add(searchResult.UniqueTitle, new List { searchResult });
+				}
+			}
+
+			// Attempt to unique-ify any non-unique titles
+			foreach (var resultsSharingTitle in titles.Values)
+			{
+				if (resultsSharingTitle.Count > 1)
+				{
+					var titlesModified = false;
+					foreach (var searchResult in resultsSharingTitle)
+					{
+						titlesModified |= searchResult.SetUniqueTitleDepth(depth);
+					}
+
+					if (titlesModified)
+					{
+						// Recurse in case of continuing non-uniqueness
+						CalculateUniqueTitles(resultsSharingTitle, depth);
+					}
+				}
+			}
+		}
+
+		private class SearchResultPrecedence : IComparer
+		{
+			public int Compare(SearchResult x, SearchResult y)
+			{
+				// First precedence is that if the result is the start of the field value, it's higher precedence than if it doesn't.
+				var result = -(x.Start == 0).CompareTo(y.Start == 0);
+
+				// Second precedence is that the start of the title field is higher precedence than the start of any other field
+				if (result == 0)
+				{
+					result = -(x.FieldName == PwDefs.TitleField).CompareTo(y.FieldName == PwDefs.TitleField);
+				}
+
+				// Both start the title field, so both equal. Have to have consistent ordering, so return final precedence based search index
+				if (result == 0)
+				{
+					result = x.ResultIndex.CompareTo(y.ResultIndex);
+				}
+				
+				return result;
+			}
+		}
+
+		private bool ShowThrobber
+		{
+			get { return mThrobber.Visible; }
+			set
+			{
+				if (value != ShowThrobber)
+				{
+					if (value)
+					{
+						mThrobber.Visible = true;
+
+						// Set the margin on the textbox to allow room for the throbber
+						NativeMethods.SetTextBoxRightMargin(mSearch, mThrobber.Width + mThrobber.Margin.Right);
+					}
+					else
+					{
+						mThrobber.Visible = false;
+
+						NativeMethods.SetTextBoxRightMargin(mSearch, 0);
+					}
+				}
+			}
+		}
+		#endregion
+
+		private void mBannerImage_MouseDown(object sender, MouseEventArgs e)
+		{
+			// Allow drag by banner image
+			if (e.Button == MouseButtons.Left)
+			{
+				if (e.Clicks == 2)
+				{
+					// Re-center the form on double-click
+					CenterToScreen();
+
+					Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+				}
+				else if (!NativeLib.IsUnix())
+				{
+					NativeMethods.StartFormDrag(this);
+				}
+			}
+		}
+
+		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+		{
+			switch (keyData)
+			{
+				case Keys.Escape:
+					Close();
+					return true;
+				case Keys.Up:
+					TryChangeSelection(-1);
+					return true;
+				case Keys.Down:
+					TryChangeSelection(1);
+					return true;
+				case Keys.PageUp:
+					TryChangeSelection(-mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.PageDown:
+					TryChangeSelection(mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.Home | Keys.Control:
+					mResults.SelectedIndex = 0;
+					return true;
+				case Keys.End | Keys.Control:
+					mResults.SelectedIndex = mResults.Items.Count - 1;
+					return true;
+				case Keys.Enter:
+					PerformAction(Settings.Default.DefaultAction, mResults.SelectedItem as SearchResult);
+					break;
+				case Keys.Enter | Keys.Shift:
+					PerformAction(Settings.Default.AlternativeAction, mResults.SelectedItem as SearchResult);
+					break;
+			}
+			
+			return base.ProcessCmdKey(ref msg, keyData);
+		}
+
+		#region Selection Changing
+
+		protected override void OnMouseWheel(MouseEventArgs e)
+		{
+			mResults.TopIndex -= (e.Delta / Math.Abs(e.Delta));
+		}
+
+		private void TryChangeSelection(int delta)
+		{
+			if (mResults.Items.Count > 0)
+			{
+				mResults.SelectedIndex = Math.Max(Math.Min(mResults.Items.Count - 1, mResults.SelectedIndex + delta), 0);
+			}
+		}
+		#endregion
+
+		#region Actions
+
+		private void mResults_MouseClick(object sender, MouseEventArgs e)
+		{
+			var clickIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (clickIndex >= 0)
+			{
+				var clickedResult = mResults.Items[clickIndex] as SearchResult;
+				if (clickedResult != null)
+				{
+					PerformAction((ModifierKeys & Keys.Shift) == Keys.Shift ? Settings.Default.AlternativeAction : Settings.Default.DefaultAction, clickedResult);
+				}
+			}
+		}
+
+		private void PerformAction(Actions action, SearchResult searchResult)
+		{
+			Close();
+
+			if (searchResult != null)
+			{
+				switch (action)
+				{
+					case Actions.PerformAutoType:
+						AutoTypeEntry(searchResult);
+						break;
+					case Actions.EditEntry:
+						EditEntry(searchResult);
+						break;
+					case Actions.ShowEntry:
+						ShowEntry(searchResult);
+						break;
+					case Actions.OpenEntryUrl:
+						OpenEntryUrl(searchResult);
+						break;
+					case Actions.CopyPassword:
+						CopyPassword(searchResult);
+						break;
+					default:
+						throw new ArgumentOutOfRangeException("action");
+				}
+			}
+		}
+
+		private void AutoTypeEntry(SearchResult searchResult)
+		{
+			bool result;
+			if (ActiveForm != null)
+			{
+				result = AutoType.PerformIntoPreviousWindow(mMainForm, searchResult.Entry, searchResult.Database);
+			}
+			else
+			{
+				result = AutoType.PerformIntoCurrentWindow(searchResult.Entry, searchResult.Database);
+			}
+			if (!result)
+			{
+				SystemSounds.Beep.Play();
+
+				if (Settings.Default.AlternativeAction != Actions.PerformAutoType)
+				{
+					PerformAction(Settings.Default.AlternativeAction, searchResult);
+				}
+			}
+		}
+
+		private void EditEntry(SearchResult searchResult)
+		{
+			using (var entryForm = new PwEntryForm())
+			{
+				mMainForm.MakeDocumentActive(mMainForm.DocumentManager.FindDocument(searchResult.Database));
+				
+				entryForm.InitEx(searchResult.Entry, PwEditMode.EditExistingEntry, searchResult.Database, mMainForm.ClientIcons, false, false);
+
+				ShowForegroundDialog(entryForm);
+
+				mMainForm.UpdateUI(false, null, searchResult.Database.UINeedsIconUpdate, null, true, null, entryForm.HasModifiedEntry);
+			}
+		}
+
+// ReSharper disable once UnusedMethodReturnValue.Local - Generic helper, result may be used in future
+		private DialogResult ShowForegroundDialog(Form form)
+		{
+			mMainForm.EnsureVisibleForegroundWindow(false, false);
+			form.StartPosition = FormStartPosition.CenterScreen;
+			if (mMainForm.IsTrayed())
+			{
+				form.ShowInTaskbar = true;
+			}
+
+			form.Shown += ActivateFormOnShown;
+			return form.ShowDialog(mMainForm);
+		}
+
+		private static void ActivateFormOnShown(object sender, EventArgs eventArgs)
+		{
+			var form = (Form)sender;
+			form.Shown -= ActivateFormOnShown;
+			form.Activate();
+		}
+
+		private void ShowEntry(SearchResult searchResult)
+		{
+			// Show this entry
+			mMainForm.UpdateUI(false, mMainForm.DocumentManager.FindDocument(searchResult.Database), true, searchResult.Entry.ParentGroup, true, null, false, null);
+			mMainForm.SelectEntries(new PwObjectList { searchResult.Entry }, true, true);
+			mMainForm.EnsureVisibleEntry(searchResult.Entry.Uuid);
+			mMainForm.UpdateUI(false, null, false, null, false, null, false);
+			mMainForm.EnsureVisibleForegroundWindow(true, true);
+		}
+
+		private void OpenEntryUrl(SearchResult searchResult)
+		{
+			WinUtil.OpenEntryUrl(searchResult.Entry);
+		}
+
+		private void CopyPassword(SearchResult searchResult)
+		{
+			if (ClipboardUtil.Copy(searchResult.Entry.Strings.ReadSafe(PwDefs.PasswordField), true, true, searchResult.Entry,
+									mMainForm.DocumentManager.SafeFindContainerOf(searchResult.Entry),
+									IntPtr.Zero))
+			{
+				mMainForm.StartClipboardCountdown();
+			}
+		}
+		
+		#endregion
+	}
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/AutoTypeSearch/SearchResults.cs b/AutoTypeSearch/SearchResults.cs
new file mode 100755
index 0000000..b2b0529
--- /dev/null
+++ b/AutoTypeSearch/SearchResults.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePass.Util.Spr;
+using KeePassLib;
+using KeePassLib.Utility;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResults
+	{
+		private readonly string mTerm;
+		private readonly SearchResult[] mResults;
+
+		private readonly object mLock = new object();
+		private volatile int mCount;
+		private volatile bool mComplete;
+
+		private readonly AutoResetEvent mResultsUpdated = new AutoResetEvent(false);
+
+		private readonly CompareOptions mStringComparison;
+		private readonly bool mSearchTitle;
+		private readonly bool mSearchUserName;
+		private readonly bool mSearchUrl;
+		private readonly bool mSearchNotes;
+		private readonly bool mSearchCustomFields;
+		private readonly bool mResolveReferences;
+		private readonly bool mSearchTags;
+
+		public SearchResults(int capacity, string term)
+		{
+			mTerm = term;
+			mResults = new SearchResult[capacity];
+
+			mStringComparison = Settings.Default.CaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase;
+			mStringComparison |= CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace;
+			mSearchTitle = Settings.Default.SearchTitle;
+			mSearchUserName = Settings.Default.SearchUserName;
+			mSearchUrl = Settings.Default.SearchUrl;
+			mSearchNotes = Settings.Default.SearchNotes;
+			mSearchCustomFields = Settings.Default.SearchCustomFields;
+			mSearchTags = Settings.Default.SearchTags;
+			mResolveReferences = Settings.Default.ResolveReferences;
+		}
+
+		/// 
+		/// Gets an ordered list of fields to search for the term
+		/// 
+		/// 
+		/// 
+		private IEnumerable GetFieldsToSearch(PwEntry entry)
+		{
+			var fieldsToSearch = new List((int)entry.Strings.UCount);
+			if (mSearchTitle) fieldsToSearch.Add(PwDefs.TitleField);
+			if (mSearchUserName) fieldsToSearch.Add(PwDefs.UserNameField);
+			if (mSearchUrl) fieldsToSearch.Add(PwDefs.UrlField);
+			if (mSearchNotes) fieldsToSearch.Add(PwDefs.NotesField);
+			if (mSearchCustomFields)
+			{
+				foreach (var stringEntry in entry.Strings)
+				{
+					if (!stringEntry.Value.IsProtected && !PwDefs.IsStandardField(stringEntry.Key))
+					{
+						fieldsToSearch.Add(stringEntry.Key);
+					}
+				}
+			}
+			if (mSearchTags) fieldsToSearch.Add(AutoTypeSearchExt.TagsVirtualFieldName);
+
+			return fieldsToSearch;
+		}
+
+		public void AddResultIfMatchesTerm(PwDatabase context, PwEntry entry)
+		{
+			// First try without resolving
+			var addedResult = AddResultIfMatchesTerm(context, entry, false);
+
+			if (!addedResult && mResolveReferences)
+			{
+				// Not found without resolving, so try resolving
+				AddResultIfMatchesTerm(context, entry, true);
+			}
+		}
+
+		private bool AddResultIfMatchesTerm(PwDatabase context, PwEntry entry, bool resolveReferences)
+		{
+			foreach (var fieldName in GetFieldsToSearch(entry))
+			{
+				string fieldValue;
+				if (fieldName == AutoTypeSearchExt.TagsVirtualFieldName)
+				{
+					fieldValue = StrUtil.TagsToString(entry.Tags, true);
+				}
+				else
+				{
+					fieldValue = entry.Strings.ReadSafeEx(fieldName);
+
+					if (resolveReferences)
+					{
+						fieldValue = ResolveReferences(context, entry, fieldValue);
+					}
+				}
+
+				if (!String.IsNullOrEmpty(fieldValue))
+				{
+					var foundIndex = CultureInfo.CurrentCulture.CompareInfo.IndexOf(fieldValue, mTerm, mStringComparison);
+					if (foundIndex >= 0)
+					{
+						// Found a match, create a search result and add it
+						AddResult(new SearchResult(context, entry, entry.Strings.ReadSafe(PwDefs.TitleField), fieldName, fieldValue, foundIndex, mTerm.Length));
+						return true;
+					}
+				}
+			}
+			return false;
+		}
+
+		/// 
+		/// Resolves any references in the field value and returns it. If there were no references,
+		/// returns null (to avoid duplicate searching - it is assumed that the unresolved value has already been searched)
+		/// 
+		private string ResolveReferences(PwDatabase context, PwEntry entry, string fieldValue)
+		{
+			if (fieldValue.IndexOf('{') < 0)
+			{
+				// Can't contain any references
+				return null;
+			}
+			
+			var sprContext = new SprContext(entry, context, SprCompileFlags.Deref) { ForcePlainTextPasswords = false };
+
+			var result = SprEngine.Compile(fieldValue, sprContext);
+			if (CultureInfo.CurrentCulture.CompareInfo.Compare(result,fieldValue, mStringComparison) == 0)
+			{
+				return null;
+			}
+			
+			return result;
+		}
+
+		public void AddResultIfMatchesTerm(SearchResult candidate)
+		{
+			// First see whether the existing candidate is a further match in the same place
+			var fieldValue = candidate.FieldValue;
+			if (fieldValue.Length > candidate.Start + mTerm.Length && CultureInfo.CurrentCulture.CompareInfo.Compare(fieldValue.Substring(candidate.Start, mTerm.Length), mTerm, mStringComparison) == 0)
+			{
+				// Yep, match continues, so add it.
+				AddResult(new SearchResult(candidate.Database, candidate.Entry, candidate.Title, candidate.FieldName, fieldValue, candidate.Start, mTerm.Length));
+			}
+			else
+			{
+				// Existing candidate match couldn't be extended, so search from scratch again
+				AddResultIfMatchesTerm(candidate.Database, candidate.Entry);
+			}
+		}
+
+		private void AddResult(SearchResult result)
+		{
+			lock (mLock)
+			{
+				if (mComplete)
+				{
+					throw new InvalidOperationException("Search results have been completed");
+				}
+				result.SetResultIndex(mCount);
+				mResults[mCount++] = result;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Indicates that the results are complete, and no more will be added.
+		/// 
+		public void SetComplete()
+		{
+			lock (mLock)
+			{
+				mComplete = true;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Gets all the available results so far.
+		/// 
+		/// Index to start returning from. Modified to be the first index not available yet on return.
+		/// Set to true if the results are complete, false if more results are pending but have not been returned.
+		/// 
+		public SearchResult[] GetAvailableResults(ref int index, out bool complete)
+		{
+			int count;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			if (count <= index)
+			{
+				return new SearchResult[0];
+			}
+
+			var availableResults = new SearchResult[count - index];
+			Array.Copy(mResults, index, availableResults, 0, availableResults.Length);
+			index = count;
+
+			return availableResults;
+		}
+
+		/// 
+		/// Gets all the results. Will block until complete.
+		/// 
+		/// 
+		public IEnumerable GetAllResults()
+		{
+			int count = -1;
+
+			for (var i = 0; i < mResults.Length; i++)
+			{
+				if (i > count)
+				{
+					// Reached the limit of availability so far, so see if more is available
+					do
+					{
+						bool moreAvailable, complete;
+
+						lock (mLock)
+						{
+							moreAvailable = mCount > count;
+							count = mCount;
+							complete = mComplete;
+						}
+
+						if (!moreAvailable)
+						{
+							if (complete)
+							{
+								// No more available, but the results are now complete anyway
+								yield break;
+							}
+
+							// No more available yet, not yet complete, wait until more becomes available
+							mResultsUpdated.WaitOne();
+						}
+						else
+						{
+							// More available now, so stop checking for more, continue with the loop to return them
+							break;
+						}
+					} while (true);
+
+					Debug.Assert(i <= count, "More should be available now");
+				}
+
+				yield return mResults[i];
+			}
+		}
+
+		public SearchResults CreateChildResults(string term)
+		{
+			Debug.Assert(term.StartsWith(mTerm));
+
+			int count;
+			bool complete;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			// If complete, then we know we don't need more than count. Otherwise, it can't be more than this capacity anyway
+			var childCapacity = complete ? count : mResults.Length;
+
+			return new SearchResults(childCapacity, term);
+		}
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.Designer.cs b/AutoTypeSearch/SearchWindow.Designer.cs
new file mode 100755
index 0000000..18b37d1
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.Designer.cs
@@ -0,0 +1,201 @@
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	partial class SearchWindow
+	{
+		/// 
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		#region Windows Form Designer generated code
+
+		/// 
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			this.components = new System.ComponentModel.Container();
+			this.mSearch = new System.Windows.Forms.TextBox();
+			this.mResults = new System.Windows.Forms.ListBox();
+			this.mLayout = new System.Windows.Forms.TableLayoutPanel();
+			this.mBanner = new System.Windows.Forms.PictureBox();
+			this.mInfoBanner = new System.Windows.Forms.Panel();
+			this.mInfoLabel = new System.Windows.Forms.Label();
+			this.mInfoBannerImage = new System.Windows.Forms.PictureBox();
+			this.mThrobber = new System.Windows.Forms.PictureBox();
+			this.mResultsUpdater = new System.Windows.Forms.Timer(this.components);
+			this.mNoResultsLabel = new System.Windows.Forms.Label();
+			this.mLayout.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).BeginInit();
+			this.mInfoBanner.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).BeginInit();
+			this.SuspendLayout();
+			// 
+			// mSearch
+			// 
+			this.mSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mSearch.Location = new System.Drawing.Point(1, 78);
+			this.mSearch.Margin = new System.Windows.Forms.Padding(1, 0, 1, 0);
+			this.mSearch.Name = "mSearch";
+			this.mSearch.Size = new System.Drawing.Size(521, 20);
+			this.mSearch.TabIndex = 0;
+			this.mSearch.LocationChanged += new System.EventHandler(this.mSearch_LocationChanged);
+			this.mSearch.TextChanged += new System.EventHandler(this.mSearch_TextChanged);
+			// 
+			// mResults
+			// 
+			this.mResults.BorderStyle = System.Windows.Forms.BorderStyle.None;
+			this.mResults.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mResults.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
+			this.mResults.FormattingEnabled = true;
+			this.mResults.IntegralHeight = false;
+			this.mResults.Location = new System.Drawing.Point(0, 98);
+			this.mResults.Margin = new System.Windows.Forms.Padding(0);
+			this.mResults.Name = "mResults";
+			this.mResults.Size = new System.Drawing.Size(523, 176);
+			this.mResults.TabIndex = 1;
+			this.mResults.TabStop = false;
+			this.mResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseClick);
+			this.mResults.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.mResults_DrawItem);
+			this.mResults.LocationChanged += new System.EventHandler(this.mResults_LocationChanged);
+			this.mResults.MouseEnter += new System.EventHandler(this.mResults_MouseEnter);
+			this.mResults.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseMove);
+			// 
+			// mLayout
+			// 
+			this.mLayout.ColumnCount = 1;
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+			this.mLayout.Controls.Add(this.mSearch, 0, 2);
+			this.mLayout.Controls.Add(this.mResults, 0, 3);
+			this.mLayout.Controls.Add(this.mBanner, 0, 0);
+			this.mLayout.Controls.Add(this.mInfoBanner, 0, 1);
+			this.mLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mLayout.Location = new System.Drawing.Point(0, 0);
+			this.mLayout.Name = "mLayout";
+			this.mLayout.RowCount = 4;
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.Size = new System.Drawing.Size(523, 274);
+			this.mLayout.TabIndex = 2;
+			// 
+			// mBanner
+			// 
+			this.mBanner.Dock = System.Windows.Forms.DockStyle.Top;
+			this.mBanner.Location = new System.Drawing.Point(0, 0);
+			this.mBanner.Margin = new System.Windows.Forms.Padding(0);
+			this.mBanner.Name = "mBanner";
+			this.mBanner.Size = new System.Drawing.Size(523, 60);
+			this.mBanner.TabIndex = 3;
+			this.mBanner.TabStop = false;
+			this.mBanner.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mBannerImage_MouseDown);
+			// 
+			// mInfoBanner
+			// 
+			this.mInfoBanner.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+			this.mInfoBanner.BackColor = System.Drawing.SystemColors.Info;
+			this.mInfoBanner.Controls.Add(this.mInfoLabel);
+			this.mInfoBanner.Controls.Add(this.mInfoBannerImage);
+			this.mInfoBanner.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoBanner.Location = new System.Drawing.Point(2, 61);
+			this.mInfoBanner.Margin = new System.Windows.Forms.Padding(2, 1, 1, 1);
+			this.mInfoBanner.Name = "mInfoBanner";
+			this.mInfoBanner.Size = new System.Drawing.Size(520, 16);
+			this.mInfoBanner.TabIndex = 8;
+			// 
+			// mInfoLabel
+			// 
+			this.mInfoLabel.AutoEllipsis = true;
+			this.mInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoLabel.ForeColor = System.Drawing.SystemColors.InfoText;
+			this.mInfoLabel.Location = new System.Drawing.Point(16, 0);
+			this.mInfoLabel.Name = "mInfoLabel";
+			this.mInfoLabel.Size = new System.Drawing.Size(504, 16);
+			this.mInfoLabel.TabIndex = 6;
+			this.mInfoLabel.Text = "AutoType failed to find";
+			// 
+			// mInfoBannerImage
+			// 
+			this.mInfoBannerImage.Dock = System.Windows.Forms.DockStyle.Left;
+			this.mInfoBannerImage.Image = global::AutoTypeSearch.Properties.Resources.Info;
+			this.mInfoBannerImage.Location = new System.Drawing.Point(0, 0);
+			this.mInfoBannerImage.Margin = new System.Windows.Forms.Padding(0);
+			this.mInfoBannerImage.Name = "mInfoBannerImage";
+			this.mInfoBannerImage.Size = new System.Drawing.Size(16, 16);
+			this.mInfoBannerImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mInfoBannerImage.TabIndex = 7;
+			this.mInfoBannerImage.TabStop = false;
+			// 
+			// mThrobber
+			// 
+			this.mThrobber.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.mThrobber.BackColor = System.Drawing.SystemColors.Window;
+			this.mThrobber.Location = new System.Drawing.Point(503, 81);
+			this.mThrobber.Name = "mThrobber";
+			this.mThrobber.Size = new System.Drawing.Size(16, 16);
+			this.mThrobber.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mThrobber.TabIndex = 4;
+			this.mThrobber.TabStop = false;
+			this.mThrobber.Visible = false;
+			// 
+			// mResultsUpdater
+			// 
+			this.mResultsUpdater.Interval = 250;
+			this.mResultsUpdater.Tick += new System.EventHandler(this.mResultsUpdater_Tick);
+			// 
+			// mNoResultsLabel
+			// 
+			this.mNoResultsLabel.AutoSize = true;
+			this.mNoResultsLabel.Location = new System.Drawing.Point(5, 103);
+			this.mNoResultsLabel.Name = "mNoResultsLabel";
+			this.mNoResultsLabel.Size = new System.Drawing.Size(84, 13);
+			this.mNoResultsLabel.TabIndex = 5;
+			this.mNoResultsLabel.Text = "No results found";
+			// 
+			// SearchWindow
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.BackColor = System.Drawing.SystemColors.Window;
+			this.ClientSize = new System.Drawing.Size(523, 274);
+			this.ControlBox = false;
+			this.Controls.Add(this.mNoResultsLabel);
+			this.Controls.Add(this.mThrobber);
+			this.Controls.Add(this.mLayout);
+			this.MinimumSize = new System.Drawing.Size(160, 96);
+			this.Name = "SearchWindow";
+			this.ShowInTaskbar = false;
+			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+			this.TopMost = true;
+			this.mLayout.ResumeLayout(false);
+			this.mLayout.PerformLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).EndInit();
+			this.mInfoBanner.ResumeLayout(false);
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).EndInit();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.TextBox mSearch;
+		private System.Windows.Forms.ListBox mResults;
+		private System.Windows.Forms.TableLayoutPanel mLayout;
+		private System.Windows.Forms.PictureBox mBanner;
+		private PictureBox mThrobber;
+		private Timer mResultsUpdater;
+		private Label mNoResultsLabel;
+		private Label mInfoLabel;
+		private Panel mInfoBanner;
+		private PictureBox mInfoBannerImage;
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchWindow.cs b/AutoTypeSearch/SearchWindow.cs
new file mode 100755
index 0000000..363b898
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.cs
@@ -0,0 +1,925 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Media;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Resources;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Collections;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	public partial class SearchWindow : Form
+	{
+		private const int SecondLineInset = 10;
+
+		// HACK to work around mono bug
+		private static readonly FieldInfo sMonoListBoxTopIndex = typeof(ListBox).GetField("top_index", BindingFlags.Instance | BindingFlags.NonPublic);
+
+		private readonly MainForm mMainForm;
+		private readonly Bitmap mBannerImage;
+		private readonly Searcher mSearcher;
+
+		private readonly Stream mThrobberImageStream;
+
+		private int? mWindowTopBorderHeight;
+		private int mBannerWidth = -1;
+		private int mMaximumExpandHeight;
+		private bool mManualSizeApplied;
+		private SearchResults mCurrentSearch;
+		private SearchResults mLastResultsUpdated;
+		private int mLastResultsUpdatedNextAvailableIndex;
+
+		#region Opening
+		public SearchWindow()
+		{
+			InitializeComponent();
+
+			// Mono can't load animated gifs from resx without crashing, so load it from an embedded resource instead
+			try
+			{
+				mThrobberImageStream = GetType().Assembly.GetManifestResourceStream("AutoTypeSearch.Throbber.gif");
+				if (mThrobberImageStream != null)
+				{
+					mThrobber.Image = Image.FromStream(mThrobberImageStream);
+				}
+			}
+			catch (Exception ex)
+			{
+				Debug.Fail("Failed to load Throbber.gif from embedded resource: " + ex.Message);
+			}
+
+			GlobalWindowManager.CustomizeControl(this);
+			UIUtil.SetExplorerTheme(mResults, true);
+			SetItemHeight();
+		}
+
+		public SearchWindow(MainForm mainForm, string infoBanner) : this()
+		{
+			mMainForm = mainForm;
+
+			mInfoBanner.Height = Math.Max(mInfoBannerImage.Height, mInfoLabel.Font.Height) + mInfoBanner.Margin.Vertical;
+			mInfoLabel.Padding = new Padding(0, (mInfoBanner.Height - mInfoLabel.Font.Height) / 2, 0, 0);
+			mInfoLabel.Text = infoBanner;
+
+			if (infoBanner == null)
+			{
+				mInfoBanner.Visible = false;
+				mInfoBanner.Height = 0;
+			}
+			
+			mSearcher = new Searcher(mMainForm.DocumentManager.GetOpenDatabases().ToArray());
+
+			Icon = mMainForm.Icon;
+			using (var bannerIcon = new Icon(Icon, 48, 48))
+			{
+				mBannerImage = bannerIcon.ToBitmap();
+			}
+			UpdateBanner();
+
+			ShowThrobber = false;
+
+			FontUtil.AssignDefaultItalic(mNoResultsLabel);
+		}
+
+
+		protected override void OnCreateControl()
+		{
+			base.OnCreateControl();
+
+			if (NativeMethods.IsWindows10())
+			{
+				mWindowTopBorderHeight = PointToScreen(Point.Empty).Y - this.Top;
+				NativeMethods.RefreshWindowFrame(Handle);
+			}
+
+			var windowRect = Settings.Default.WindowPosition;
+			var collapsedWindowRect = windowRect;
+			
+			collapsedWindowRect.Height = mSearch.Bottom + (Height - ClientSize.Height);
+
+			MinimumSize = new Size(MinimumSize.Width, collapsedWindowRect.Height);
+
+			if (windowRect.IsEmpty || !IsOnScreen(collapsedWindowRect))
+			{
+				windowRect = new Rectangle(0, 0, Width, Height);
+				Height = collapsedWindowRect.Height;
+
+				CenterToScreen();
+			}
+			else
+			{
+				Location = windowRect.Location;
+				Size = collapsedWindowRect.Size;
+			}
+
+			mMaximumExpandHeight = Math.Max(windowRect.Height, MinimumSize.Height + mResults.ItemHeight);
+		}
+		
+
+		private static bool IsOnScreen(Rectangle rectangle)
+		{
+			return Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(rectangle));
+		}
+
+		private void SetItemHeight()
+		{
+			mResults.ItemHeight = mResults.Font.Height * 2 + 2;
+		}
+
+		protected override void WndProc(ref Message m)
+		{
+			if (mWindowTopBorderHeight.HasValue)
+			{
+				NativeMethods.RemoveWindowFrameTopBorder(ref m, mWindowTopBorderHeight.Value);
+			}
+			base.WndProc(ref m);
+		}
+
+		#endregion
+
+		#region Closing
+		protected override void OnActivated(EventArgs e)
+		{
+			base.OnActivated(e);
+			Deactivate += OnDeactivate;
+		}
+
+		private void OnDeactivate(object sender, EventArgs eventArgs)
+		{
+			Close();
+		}
+
+		protected override void OnClosed(EventArgs e)
+		{
+			Deactivate -= OnDeactivate;
+			base.OnClosed(e);
+		}
+
+		/// 
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				if (mBannerImage != null)
+				{
+					mBannerImage.Dispose();
+				}
+				if (mThrobber.Image != null)
+				{
+					mThrobber.Image.Dispose();
+					mThrobber.Image = null;
+					mThrobberImageStream.Dispose();
+				}
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+		#endregion
+
+		#region Item Drawing
+		private void mResults_DrawItem(object sender, DrawItemEventArgs e)
+		{
+			var searchResult = mResults.Items[e.Index] as SearchResult;
+			if (searchResult == null)
+			{
+				Debug.Fail("Unexpected item in mResults");
+// ReSharper disable once HeuristicUnreachableCode - Not unreachable
+				return;
+			}
+			var drawingArea = e.Bounds;
+			drawingArea.Height--; // Leave room for a dividing line at the bottom
+			
+			if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
+			{
+				DrawBorderedRectangle(e.Graphics, drawingArea, SystemColors.Highlight);
+			}
+			else
+			{
+				e.Graphics.FillRectangle(SystemBrushes.Window, drawingArea);
+			}
+
+			var image = GetImage(searchResult.Database, searchResult.Entry.CustomIconUuid, searchResult.Entry.IconId);
+			var imageMargin = (drawingArea.Height - image.Height) / 2;
+			e.Graphics.DrawImage(image, drawingArea.Left + imageMargin, drawingArea.Top + imageMargin, image.Width, image.Height);
+
+			var textLeftMargin = drawingArea.Left + imageMargin * 2 + image.Width;
+			var textBounds = new Rectangle(textLeftMargin, drawingArea.Top + 1, drawingArea.Width - textLeftMargin - 1, drawingArea.Height - 2);
+
+			var line1Bounds = textBounds;
+			line1Bounds.Height = e.Font.Height;
+			var line2Bounds = line1Bounds;
+			line2Bounds.Y += line2Bounds.Height - 1;
+			line2Bounds.X += SecondLineInset;
+			line2Bounds.Width -= SecondLineInset;
+
+			var resultInTitleField = searchResult.FieldName == PwDefs.TitleField;
+
+			var title = (resultInTitleField ? searchResult.FieldValue : searchResult.Title).Replace('\n', ' '); // The FieldValue may have references resolved, whereas the title is always read directly.
+
+			var uniqueTitlePartWidth = 0;
+			if (!String.IsNullOrEmpty(searchResult.UniqueTitlePart))
+			{
+				var uniqueTitlePart = searchResult.UniqueTitlePart.Replace('\n', ' ');
+
+				var titleWidth = TextRenderer.MeasureText(e.Graphics, title, e.Font, line1Bounds.Size, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+
+				var availableWidthForUniqueTitlePart = line1Bounds.Width - titleWidth;
+				if (availableWidthForUniqueTitlePart > 20) // Don't bother including a unique part if there's no room for it
+				{
+					var uniqueTitlePartReversed = ReverseString(uniqueTitlePart);
+
+					uniqueTitlePartWidth = TextRenderer.MeasureText(e.Graphics, uniqueTitlePartReversed, e.Font, new Size(availableWidthForUniqueTitlePart, line1Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+					uniqueTitlePart = ReverseString(uniqueTitlePartReversed);
+
+					TextRenderer.DrawText(e.Graphics, uniqueTitlePart, e.Font, new Rectangle(line1Bounds.X, line1Bounds.Y, uniqueTitlePartWidth, line1Bounds.Height), SystemColors.GrayText, TextFormatFlags.NoPadding);
+				}
+			}
+
+			var titleBounds = new Rectangle(line1Bounds.X + uniqueTitlePartWidth, line1Bounds.Y, line1Bounds.Width - uniqueTitlePartWidth, line1Bounds.Height);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Highlight title in first line.
+				DrawHighlight(e, titleBounds, title, searchResult.Start, searchResult.Length);
+			}
+
+			TextRenderer.DrawText(e.Graphics, searchResult.Title, e.Font, titleBounds, SystemColors.WindowText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Use Username for second line.
+				TextRenderer.DrawText(e.Graphics, KPRes.UserName + ": " + searchResult.Entry.Strings.ReadSafeEx(PwDefs.UserNameField), e.Font, line2Bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+			}
+			else
+			{
+				// Found the result in not title field. Show the matching result on second line
+				
+				var fieldValue = searchResult.FieldValue.Replace('\n',' ');
+				var fieldNamePrefix = GetDisplayFieldName(searchResult.FieldName) + ": ";
+
+				var remainingSpace = line2Bounds.Width;
+				var fieldNamePrefixWidth = TextRenderer.MeasureText(e.Graphics, fieldNamePrefix, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+				remainingSpace -= fieldNamePrefixWidth;
+
+				int fieldValueHighlightWidth = 0, fieldValueLeftContextWidth = 0, fieldValueRightContextWidth = 0;
+
+				var leftContext = fieldValue.Substring(0, searchResult.Start);
+				var highlight = fieldValue.Substring(searchResult.Start, searchResult.Length);
+				var rightContext = fieldValue.Substring(searchResult.Start + searchResult.Length);
+
+				if (searchResult.Length == 0)
+				{
+					fieldValueHighlightWidth = remainingSpace;
+				}
+				else
+				{
+					if (remainingSpace > 0)
+					{
+						var availableSpace = remainingSpace;
+						fieldValueHighlightWidth = TextRenderer.MeasureText(e.Graphics, highlight, e.Font, new Size(availableSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						remainingSpace -= fieldValueHighlightWidth;
+					}
+
+					// Of the space remaining, divide it equally between that which comes before, and that which comes after
+					if (!String.IsNullOrEmpty(leftContext))
+					{
+						var leftContextReversed = ReverseString(leftContext);
+						fieldValueLeftContextWidth = TextRenderer.MeasureText(e.Graphics, leftContextReversed, e.Font, new Size(remainingSpace / 2, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+						if (fieldValueLeftContextWidth > remainingSpace)
+						{
+							// Always allow space for the minimal left context
+							fieldValueHighlightWidth -= (fieldValueLeftContextWidth - remainingSpace);
+							remainingSpace = 0;
+						}
+						else
+						{
+							remainingSpace -= fieldValueLeftContextWidth;							
+						}
+						
+						// Replace left context with the truncated reversed left context.
+						leftContext = ReverseString(leftContextReversed);
+					}
+
+					if (remainingSpace > 0 && !String.IsNullOrEmpty(rightContext))
+					{
+						fieldValueRightContextWidth = TextRenderer.MeasureText(e.Graphics, rightContext, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						if (fieldValueRightContextWidth > remainingSpace)
+						{
+							fieldValueRightContextWidth = 0;
+						}
+					}
+				}
+
+				// Now draw it all
+				var bounds = line2Bounds;
+				bounds.Width = fieldNamePrefixWidth;
+				TextRenderer.DrawText(e.Graphics, fieldNamePrefix, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				if (fieldValueLeftContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueLeftContextWidth;
+					TextRenderer.DrawText(e.Graphics, leftContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding); // No ellipsis as the leftContext string has already been truncated appropriately
+				}
+				if (fieldValueHighlightWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueHighlightWidth;
+
+					if (searchResult.Length > 0)
+					{
+						DrawHighlightRectangle(e, bounds);
+					}
+					TextRenderer.DrawText(e.Graphics, highlight, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+				if (fieldValueRightContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueRightContextWidth;
+					TextRenderer.DrawText(e.Graphics, rightContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+			}
+
+			e.Graphics.DrawLine(SystemPens.ButtonFace, drawingArea.Left, drawingArea.Bottom, drawingArea.Right, drawingArea.Bottom);
+		}
+
+		private static string ReverseString(string value)
+		{
+			return new String(value.ToCharArray().TakeWhile(c => c != '\0').Reverse().ToArray());
+		}
+
+		private static void DrawHighlight(DrawItemEventArgs e, Rectangle lineBounds, string text, int highlightFrom, int highlightLength)
+		{
+			var highlightX = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width;
+			var highlightWidth = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom + highlightLength), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width - highlightX;
+
+			DrawHighlightRectangle(e, new Rectangle(lineBounds.Left + highlightX, lineBounds.Top, highlightWidth, lineBounds.Height));
+		}
+
+		private static void DrawHighlightRectangle(DrawItemEventArgs e, Rectangle rectangle)
+		{
+			DrawBorderedRectangle(e.Graphics, rectangle, Color.PaleTurquoise);
+		}
+
+		private static void DrawBorderedRectangle(Graphics graphics, Rectangle rectangle, Color colour)
+		{
+			var border = rectangle;
+			border.Width--;
+			border.Height--;
+
+			using (var brush = new SolidBrush(MergeColors(colour, SystemColors.Window, 0.2)))
+			{
+				graphics.FillRectangle(brush, rectangle);
+			}
+			using (var pen = new Pen(colour, 1f))
+			{
+				graphics.DrawRectangle(pen, border);
+			}
+		}
+
+		private Image GetImage(PwDatabase database, PwUuid customIconId, PwIcon iconId)
+		{
+			Image image = null;
+			if (!customIconId.Equals(PwUuid.Zero))
+			{
+				image = database.GetCustomIcon(customIconId, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16));
+			}
+			if (image == null)
+			{
+				try { image = mMainForm.ClientIcons.Images[(int)iconId]; }
+				catch (Exception) { Debug.Assert(false); }
+			}
+
+			return image;
+		}
+
+		private static string GetDisplayFieldName(string fieldName)
+		{
+			switch (fieldName)
+			{
+				case PwDefs.TitleField:
+					return KPRes.Title;
+				case PwDefs.UserNameField:
+					return KPRes.UserName;
+				case PwDefs.PasswordField:
+					return KPRes.Password;
+				case PwDefs.UrlField:
+					return KPRes.Url;
+				case PwDefs.NotesField:
+					return KPRes.Notes;
+				case AutoTypeSearchExt.TagsVirtualFieldName:
+					return KPRes.Tags;
+				default:
+					return fieldName;
+			}
+		}
+
+		public static Color MergeColors(Color from, Color to, double amount)
+		{
+			var r = (byte)((from.R * amount) + to.R * (1 - amount));
+			var g = (byte)((from.G * amount) + to.G * (1 - amount));
+			var b = (byte)((from.B * amount) + to.B * (1 - amount));
+			return Color.FromArgb(r, g, b);
+		}
+		#endregion
+
+		#region Mouse tracking
+		private Point mMouseEntryPosition;
+		
+		private void mResults_MouseEnter(object sender, EventArgs e)
+		{
+			mMouseEntryPosition = MousePosition;
+		}
+
+		private void mResults_MouseMove(object sender, MouseEventArgs e)
+		{
+			// Discard the location the mouse has on entering the control (as it may be that the control has just moved under the mouse, not the other way around)
+			if (MousePosition == mMouseEntryPosition)
+			{
+				return;
+			}
+
+			// Hot tracking
+			var hoverIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (hoverIndex >= 0 && mResults.SelectedIndex != hoverIndex)
+			{
+				if (mResults.GetItemRectangle(hoverIndex).Bottom <= mResults.ClientRectangle.Bottom)
+				{
+					mResults.SelectedIndex = hoverIndex;
+				}
+				else
+				{
+					// Avoid the control scrolling
+					mResults.BeginUpdate();
+					var topIndex = mResults.TopIndex;
+					mResults.SelectedIndex = hoverIndex;
+					mResults.TopIndex = topIndex;
+					mResults.EndUpdate();
+				}
+			}
+		}
+		#endregion
+
+		#region Resizing
+		protected override void OnResizeBegin(EventArgs e)
+		{
+			// Stop automatically sizing - the user is picking a size they want.
+			mManualSizeApplied = true;
+			base.OnResizeBegin(e);
+		}
+
+		protected override void OnResize(EventArgs e)
+		{
+			base.OnResize(e);
+
+			UpdateBanner();
+
+			mResults.Invalidate();
+		}
+
+		protected override void OnResizeEnd(EventArgs e)
+		{
+			base.OnResizeEnd(e);
+
+			if (Height > MinimumSize.Height && Height != mMaximumExpandHeight)
+			{
+				mMaximumExpandHeight = Math.Max(Height, MinimumSize.Height + mResults.ItemHeight);
+			}
+			else
+			{
+				mManualSizeApplied = false;
+			}
+
+			Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+		}
+
+		private void UpdateBanner()
+		{
+			if (mBannerImage != null)
+			{
+				BannerFactory.UpdateBanner(this, mBanner, mBannerImage, PwDefs.ProductName, Resources.BannerText, ref mBannerWidth);
+			}
+		}
+
+		private void mSearch_LocationChanged(object sender, EventArgs e)
+		{
+			mThrobber.Location = new Point(mSearch.Right - mThrobber.Width - mThrobber.Margin.Right, mSearch.Top + (mSearch.Height - mThrobber.Height) / 2);
+		}
+
+		private void mResults_LocationChanged(object sender, EventArgs e)
+		{
+			mNoResultsLabel.Top = mResults.Top + (mResults.ItemHeight - mNoResultsLabel.Height) / 2;
+		}
+		#endregion
+
+		#region Searching
+		private static readonly SearchResultPrecedence SearchResultPrecedenceComparer = new SearchResultPrecedence();
+		private void mSearch_TextChanged(object sender, EventArgs e)
+		{
+			if (mSearch.Text.Length < 2)
+			{
+				// Stop searching
+				mResultsUpdater.Enabled = false;
+				ShowThrobber = false;
+				Height = MinimumSize.Height;
+				mManualSizeApplied = false;
+				mResults.Items.Clear();
+				mLastResultsUpdated = null;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			else
+			{
+				// Start searching
+				mNoResultsLabel.Visible = false;
+				mCurrentSearch = mSearcher.Search(mSearch.Text);
+				mResultsUpdater.Enabled = true;
+				ShowThrobber = true;
+				mResultsUpdater_Tick(null, EventArgs.Empty); // Quick poke just in case the results are already done.
+			}
+		}
+
+		[SuppressMessage("ReSharper", "CoVariantArrayConversion", Justification = "Object arrays for Listbox.Items, known to be of correct type")]
+		private void mResultsUpdater_Tick(object sender, EventArgs e)
+		{
+			if (mLastResultsUpdated != mCurrentSearch)
+			{
+				// Clear out old results and replace with new ones
+				mResults.Items.Clear();
+				mLastResultsUpdated = mCurrentSearch;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			var existingResultsCount = mResults.Items.Count;
+			
+			bool complete;
+			var newResults = mLastResultsUpdated.GetAvailableResults(ref mLastResultsUpdatedNextAvailableIndex, out complete);
+			if (newResults.Length > 0)
+			{
+				mResults.BeginUpdate();
+				
+				SearchResult[] allResults;
+				if (existingResultsCount > 0)
+				{
+					allResults = new SearchResult[existingResultsCount + newResults.Length];
+					mResults.Items.CopyTo(allResults, 0);
+					newResults.CopyTo(allResults, existingResultsCount);
+
+					mResults.Items.Clear();
+				}
+				else
+				{
+					allResults = newResults;
+				}
+
+				CalculateUniqueTitles(allResults);
+
+				Array.Sort(allResults, SearchResultPrecedenceComparer);
+				mResults.Items.AddRange(allResults);
+				
+				mResults.EndUpdate();
+
+				if (allResults.Length > 0)
+				{
+					if (mResults.SelectedIndex == -1)
+					{
+						try
+						{
+							// HACK to work around mono bug
+							if (sMonoListBoxTopIndex != null)
+							{
+								sMonoListBoxTopIndex.SetValue(mResults, 1); // Set the top_index to 1 so that when selected index is set to 0, and calls EnsureVisible(0), it follows the index < top_index pass and not the broken index >= top_index + rows path. 
+							}
+
+							mResults.SelectedIndex = 0;
+							mResults.TopIndex = 0;
+						}
+						catch (Exception ex)
+						{
+							Debug.Fail("Failed to set selection on count of " + allResults.Length + ": " + ex.Message);
+						}
+					}
+
+					if (!mManualSizeApplied)
+					{
+						Height = Math.Min(mMaximumExpandHeight, MinimumSize.Height + (allResults.Length * mResults.ItemHeight));
+					}
+				}
+			}
+
+			if (complete)
+			{
+				ShowThrobber = false;
+				mResultsUpdater.Enabled = false;
+
+				if (mResults.Items.Count == 0)
+				{
+					mNoResultsLabel.Visible = true;
+					Height = MinimumSize.Height + mResults.ItemHeight;
+					mManualSizeApplied = false;
+				}
+			}
+		}
+
+		private void CalculateUniqueTitles(IEnumerable results, int depth = 0)
+		{
+			// Where results have identical titles, include group titles to make them unique
+			depth += 1;
+
+			// First create a lookup by title
+			var titles = new Dictionary>();
+			foreach (var searchResult in results)
+			{
+				List resultsWithSameTitle;
+				if (titles.TryGetValue(searchResult.UniqueTitle, out resultsWithSameTitle))
+				{
+					resultsWithSameTitle.Add(searchResult);
+				}
+				else
+				{
+					titles.Add(searchResult.UniqueTitle, new List { searchResult });
+				}
+			}
+
+			// Attempt to unique-ify any non-unique titles
+			foreach (var resultsSharingTitle in titles.Values)
+			{
+				if (resultsSharingTitle.Count > 1)
+				{
+					var titlesModified = false;
+					foreach (var searchResult in resultsSharingTitle)
+					{
+						titlesModified |= searchResult.SetUniqueTitleDepth(depth);
+					}
+
+					if (titlesModified)
+					{
+						// Recurse in case of continuing non-uniqueness
+						CalculateUniqueTitles(resultsSharingTitle, depth);
+					}
+				}
+			}
+		}
+
+		private class SearchResultPrecedence : IComparer
+		{
+			public int Compare(SearchResult x, SearchResult y)
+			{
+				// First precedence is that if the result is the start of the field value, it's higher precedence than if it doesn't.
+				var result = -(x.Start == 0).CompareTo(y.Start == 0);
+
+				// Second precedence is that the start of the title field is higher precedence than the start of any other field
+				if (result == 0)
+				{
+					result = -(x.FieldName == PwDefs.TitleField).CompareTo(y.FieldName == PwDefs.TitleField);
+				}
+
+				// Both start the title field, so both equal. Have to have consistent ordering, so return final precedence based search index
+				if (result == 0)
+				{
+					result = x.ResultIndex.CompareTo(y.ResultIndex);
+				}
+				
+				return result;
+			}
+		}
+
+		private bool ShowThrobber
+		{
+			get { return mThrobber.Visible; }
+			set
+			{
+				if (value != ShowThrobber)
+				{
+					if (value)
+					{
+						mThrobber.Visible = true;
+
+						// Set the margin on the textbox to allow room for the throbber
+						NativeMethods.SetTextBoxRightMargin(mSearch, mThrobber.Width + mThrobber.Margin.Right);
+					}
+					else
+					{
+						mThrobber.Visible = false;
+
+						NativeMethods.SetTextBoxRightMargin(mSearch, 0);
+					}
+				}
+			}
+		}
+		#endregion
+
+		private void mBannerImage_MouseDown(object sender, MouseEventArgs e)
+		{
+			// Allow drag by banner image
+			if (e.Button == MouseButtons.Left)
+			{
+				if (e.Clicks == 2)
+				{
+					// Re-center the form on double-click
+					CenterToScreen();
+
+					Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+				}
+				else if (!NativeLib.IsUnix())
+				{
+					NativeMethods.StartFormDrag(this);
+				}
+			}
+		}
+
+		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+		{
+			switch (keyData)
+			{
+				case Keys.Escape:
+					Close();
+					return true;
+				case Keys.Up:
+					TryChangeSelection(-1);
+					return true;
+				case Keys.Down:
+					TryChangeSelection(1);
+					return true;
+				case Keys.PageUp:
+					TryChangeSelection(-mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.PageDown:
+					TryChangeSelection(mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.Home | Keys.Control:
+					mResults.SelectedIndex = 0;
+					return true;
+				case Keys.End | Keys.Control:
+					mResults.SelectedIndex = mResults.Items.Count - 1;
+					return true;
+				case Keys.Enter:
+					PerformAction(Settings.Default.DefaultAction, mResults.SelectedItem as SearchResult);
+					break;
+				case Keys.Enter | Keys.Shift:
+					PerformAction(Settings.Default.AlternativeAction, mResults.SelectedItem as SearchResult);
+					break;
+			}
+			
+			return base.ProcessCmdKey(ref msg, keyData);
+		}
+
+		#region Selection Changing
+
+		protected override void OnMouseWheel(MouseEventArgs e)
+		{
+			mResults.TopIndex -= (e.Delta / Math.Abs(e.Delta));
+		}
+
+		private void TryChangeSelection(int delta)
+		{
+			if (mResults.Items.Count > 0)
+			{
+				mResults.SelectedIndex = Math.Max(Math.Min(mResults.Items.Count - 1, mResults.SelectedIndex + delta), 0);
+			}
+		}
+		#endregion
+
+		#region Actions
+
+		private void mResults_MouseClick(object sender, MouseEventArgs e)
+		{
+			var clickIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (clickIndex >= 0)
+			{
+				var clickedResult = mResults.Items[clickIndex] as SearchResult;
+				if (clickedResult != null)
+				{
+					PerformAction((ModifierKeys & Keys.Shift) == Keys.Shift ? Settings.Default.AlternativeAction : Settings.Default.DefaultAction, clickedResult);
+				}
+			}
+		}
+
+		private void PerformAction(Actions action, SearchResult searchResult)
+		{
+			Close();
+
+			if (searchResult != null)
+			{
+				switch (action)
+				{
+					case Actions.PerformAutoType:
+						AutoTypeEntry(searchResult);
+						break;
+					case Actions.EditEntry:
+						EditEntry(searchResult);
+						break;
+					case Actions.ShowEntry:
+						ShowEntry(searchResult);
+						break;
+					case Actions.OpenEntryUrl:
+						OpenEntryUrl(searchResult);
+						break;
+					case Actions.CopyPassword:
+						CopyPassword(searchResult);
+						break;
+					default:
+						throw new ArgumentOutOfRangeException("action");
+				}
+			}
+		}
+
+		private void AutoTypeEntry(SearchResult searchResult)
+		{
+			bool result;
+			if (ActiveForm != null)
+			{
+				result = AutoType.PerformIntoPreviousWindow(mMainForm, searchResult.Entry, searchResult.Database);
+			}
+			else
+			{
+				result = AutoType.PerformIntoCurrentWindow(searchResult.Entry, searchResult.Database);
+			}
+			if (!result)
+			{
+				SystemSounds.Beep.Play();
+
+				if (Settings.Default.AlternativeAction != Actions.PerformAutoType)
+				{
+					PerformAction(Settings.Default.AlternativeAction, searchResult);
+				}
+			}
+		}
+
+		private void EditEntry(SearchResult searchResult)
+		{
+			using (var entryForm = new PwEntryForm())
+			{
+				mMainForm.MakeDocumentActive(mMainForm.DocumentManager.FindDocument(searchResult.Database));
+				
+				entryForm.InitEx(searchResult.Entry, PwEditMode.EditExistingEntry, searchResult.Database, mMainForm.ClientIcons, false, false);
+
+				ShowForegroundDialog(entryForm);
+
+				mMainForm.UpdateUI(false, null, searchResult.Database.UINeedsIconUpdate, null, true, null, entryForm.HasModifiedEntry);
+			}
+		}
+
+// ReSharper disable once UnusedMethodReturnValue.Local - Generic helper, result may be used in future
+		private DialogResult ShowForegroundDialog(Form form)
+		{
+			mMainForm.EnsureVisibleForegroundWindow(false, false);
+			form.StartPosition = FormStartPosition.CenterScreen;
+			if (mMainForm.IsTrayed())
+			{
+				form.ShowInTaskbar = true;
+			}
+
+			form.Shown += ActivateFormOnShown;
+			return form.ShowDialog(mMainForm);
+		}
+
+		private static void ActivateFormOnShown(object sender, EventArgs eventArgs)
+		{
+			var form = (Form)sender;
+			form.Shown -= ActivateFormOnShown;
+			form.Activate();
+		}
+
+		private void ShowEntry(SearchResult searchResult)
+		{
+			// Show this entry
+			mMainForm.UpdateUI(false, mMainForm.DocumentManager.FindDocument(searchResult.Database), true, searchResult.Entry.ParentGroup, true, null, false, null);
+			mMainForm.SelectEntries(new PwObjectList { searchResult.Entry }, true, true);
+			mMainForm.EnsureVisibleEntry(searchResult.Entry.Uuid);
+			mMainForm.UpdateUI(false, null, false, null, false, null, false);
+			mMainForm.EnsureVisibleForegroundWindow(true, true);
+		}
+
+		private void OpenEntryUrl(SearchResult searchResult)
+		{
+			WinUtil.OpenEntryUrl(searchResult.Entry);
+		}
+
+		private void CopyPassword(SearchResult searchResult)
+		{
+			if (ClipboardUtil.Copy(searchResult.Entry.Strings.ReadSafe(PwDefs.PasswordField), true, true, searchResult.Entry,
+									mMainForm.DocumentManager.SafeFindContainerOf(searchResult.Entry),
+									IntPtr.Zero))
+			{
+				mMainForm.StartClipboardCountdown();
+			}
+		}
+		
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.resx b/AutoTypeSearch/SearchWindow.resx
new file mode 100755
index 0000000..8ef82f0
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.resx
@@ -0,0 +1,123 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    17, 17
+  
+
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/AutoTypeSearch/SearchResults.cs b/AutoTypeSearch/SearchResults.cs
new file mode 100755
index 0000000..b2b0529
--- /dev/null
+++ b/AutoTypeSearch/SearchResults.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePass.Util.Spr;
+using KeePassLib;
+using KeePassLib.Utility;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResults
+	{
+		private readonly string mTerm;
+		private readonly SearchResult[] mResults;
+
+		private readonly object mLock = new object();
+		private volatile int mCount;
+		private volatile bool mComplete;
+
+		private readonly AutoResetEvent mResultsUpdated = new AutoResetEvent(false);
+
+		private readonly CompareOptions mStringComparison;
+		private readonly bool mSearchTitle;
+		private readonly bool mSearchUserName;
+		private readonly bool mSearchUrl;
+		private readonly bool mSearchNotes;
+		private readonly bool mSearchCustomFields;
+		private readonly bool mResolveReferences;
+		private readonly bool mSearchTags;
+
+		public SearchResults(int capacity, string term)
+		{
+			mTerm = term;
+			mResults = new SearchResult[capacity];
+
+			mStringComparison = Settings.Default.CaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase;
+			mStringComparison |= CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace;
+			mSearchTitle = Settings.Default.SearchTitle;
+			mSearchUserName = Settings.Default.SearchUserName;
+			mSearchUrl = Settings.Default.SearchUrl;
+			mSearchNotes = Settings.Default.SearchNotes;
+			mSearchCustomFields = Settings.Default.SearchCustomFields;
+			mSearchTags = Settings.Default.SearchTags;
+			mResolveReferences = Settings.Default.ResolveReferences;
+		}
+
+		/// 
+		/// Gets an ordered list of fields to search for the term
+		/// 
+		/// 
+		/// 
+		private IEnumerable GetFieldsToSearch(PwEntry entry)
+		{
+			var fieldsToSearch = new List((int)entry.Strings.UCount);
+			if (mSearchTitle) fieldsToSearch.Add(PwDefs.TitleField);
+			if (mSearchUserName) fieldsToSearch.Add(PwDefs.UserNameField);
+			if (mSearchUrl) fieldsToSearch.Add(PwDefs.UrlField);
+			if (mSearchNotes) fieldsToSearch.Add(PwDefs.NotesField);
+			if (mSearchCustomFields)
+			{
+				foreach (var stringEntry in entry.Strings)
+				{
+					if (!stringEntry.Value.IsProtected && !PwDefs.IsStandardField(stringEntry.Key))
+					{
+						fieldsToSearch.Add(stringEntry.Key);
+					}
+				}
+			}
+			if (mSearchTags) fieldsToSearch.Add(AutoTypeSearchExt.TagsVirtualFieldName);
+
+			return fieldsToSearch;
+		}
+
+		public void AddResultIfMatchesTerm(PwDatabase context, PwEntry entry)
+		{
+			// First try without resolving
+			var addedResult = AddResultIfMatchesTerm(context, entry, false);
+
+			if (!addedResult && mResolveReferences)
+			{
+				// Not found without resolving, so try resolving
+				AddResultIfMatchesTerm(context, entry, true);
+			}
+		}
+
+		private bool AddResultIfMatchesTerm(PwDatabase context, PwEntry entry, bool resolveReferences)
+		{
+			foreach (var fieldName in GetFieldsToSearch(entry))
+			{
+				string fieldValue;
+				if (fieldName == AutoTypeSearchExt.TagsVirtualFieldName)
+				{
+					fieldValue = StrUtil.TagsToString(entry.Tags, true);
+				}
+				else
+				{
+					fieldValue = entry.Strings.ReadSafeEx(fieldName);
+
+					if (resolveReferences)
+					{
+						fieldValue = ResolveReferences(context, entry, fieldValue);
+					}
+				}
+
+				if (!String.IsNullOrEmpty(fieldValue))
+				{
+					var foundIndex = CultureInfo.CurrentCulture.CompareInfo.IndexOf(fieldValue, mTerm, mStringComparison);
+					if (foundIndex >= 0)
+					{
+						// Found a match, create a search result and add it
+						AddResult(new SearchResult(context, entry, entry.Strings.ReadSafe(PwDefs.TitleField), fieldName, fieldValue, foundIndex, mTerm.Length));
+						return true;
+					}
+				}
+			}
+			return false;
+		}
+
+		/// 
+		/// Resolves any references in the field value and returns it. If there were no references,
+		/// returns null (to avoid duplicate searching - it is assumed that the unresolved value has already been searched)
+		/// 
+		private string ResolveReferences(PwDatabase context, PwEntry entry, string fieldValue)
+		{
+			if (fieldValue.IndexOf('{') < 0)
+			{
+				// Can't contain any references
+				return null;
+			}
+			
+			var sprContext = new SprContext(entry, context, SprCompileFlags.Deref) { ForcePlainTextPasswords = false };
+
+			var result = SprEngine.Compile(fieldValue, sprContext);
+			if (CultureInfo.CurrentCulture.CompareInfo.Compare(result,fieldValue, mStringComparison) == 0)
+			{
+				return null;
+			}
+			
+			return result;
+		}
+
+		public void AddResultIfMatchesTerm(SearchResult candidate)
+		{
+			// First see whether the existing candidate is a further match in the same place
+			var fieldValue = candidate.FieldValue;
+			if (fieldValue.Length > candidate.Start + mTerm.Length && CultureInfo.CurrentCulture.CompareInfo.Compare(fieldValue.Substring(candidate.Start, mTerm.Length), mTerm, mStringComparison) == 0)
+			{
+				// Yep, match continues, so add it.
+				AddResult(new SearchResult(candidate.Database, candidate.Entry, candidate.Title, candidate.FieldName, fieldValue, candidate.Start, mTerm.Length));
+			}
+			else
+			{
+				// Existing candidate match couldn't be extended, so search from scratch again
+				AddResultIfMatchesTerm(candidate.Database, candidate.Entry);
+			}
+		}
+
+		private void AddResult(SearchResult result)
+		{
+			lock (mLock)
+			{
+				if (mComplete)
+				{
+					throw new InvalidOperationException("Search results have been completed");
+				}
+				result.SetResultIndex(mCount);
+				mResults[mCount++] = result;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Indicates that the results are complete, and no more will be added.
+		/// 
+		public void SetComplete()
+		{
+			lock (mLock)
+			{
+				mComplete = true;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Gets all the available results so far.
+		/// 
+		/// Index to start returning from. Modified to be the first index not available yet on return.
+		/// Set to true if the results are complete, false if more results are pending but have not been returned.
+		/// 
+		public SearchResult[] GetAvailableResults(ref int index, out bool complete)
+		{
+			int count;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			if (count <= index)
+			{
+				return new SearchResult[0];
+			}
+
+			var availableResults = new SearchResult[count - index];
+			Array.Copy(mResults, index, availableResults, 0, availableResults.Length);
+			index = count;
+
+			return availableResults;
+		}
+
+		/// 
+		/// Gets all the results. Will block until complete.
+		/// 
+		/// 
+		public IEnumerable GetAllResults()
+		{
+			int count = -1;
+
+			for (var i = 0; i < mResults.Length; i++)
+			{
+				if (i > count)
+				{
+					// Reached the limit of availability so far, so see if more is available
+					do
+					{
+						bool moreAvailable, complete;
+
+						lock (mLock)
+						{
+							moreAvailable = mCount > count;
+							count = mCount;
+							complete = mComplete;
+						}
+
+						if (!moreAvailable)
+						{
+							if (complete)
+							{
+								// No more available, but the results are now complete anyway
+								yield break;
+							}
+
+							// No more available yet, not yet complete, wait until more becomes available
+							mResultsUpdated.WaitOne();
+						}
+						else
+						{
+							// More available now, so stop checking for more, continue with the loop to return them
+							break;
+						}
+					} while (true);
+
+					Debug.Assert(i <= count, "More should be available now");
+				}
+
+				yield return mResults[i];
+			}
+		}
+
+		public SearchResults CreateChildResults(string term)
+		{
+			Debug.Assert(term.StartsWith(mTerm));
+
+			int count;
+			bool complete;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			// If complete, then we know we don't need more than count. Otherwise, it can't be more than this capacity anyway
+			var childCapacity = complete ? count : mResults.Length;
+
+			return new SearchResults(childCapacity, term);
+		}
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.Designer.cs b/AutoTypeSearch/SearchWindow.Designer.cs
new file mode 100755
index 0000000..18b37d1
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.Designer.cs
@@ -0,0 +1,201 @@
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	partial class SearchWindow
+	{
+		/// 
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		#region Windows Form Designer generated code
+
+		/// 
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			this.components = new System.ComponentModel.Container();
+			this.mSearch = new System.Windows.Forms.TextBox();
+			this.mResults = new System.Windows.Forms.ListBox();
+			this.mLayout = new System.Windows.Forms.TableLayoutPanel();
+			this.mBanner = new System.Windows.Forms.PictureBox();
+			this.mInfoBanner = new System.Windows.Forms.Panel();
+			this.mInfoLabel = new System.Windows.Forms.Label();
+			this.mInfoBannerImage = new System.Windows.Forms.PictureBox();
+			this.mThrobber = new System.Windows.Forms.PictureBox();
+			this.mResultsUpdater = new System.Windows.Forms.Timer(this.components);
+			this.mNoResultsLabel = new System.Windows.Forms.Label();
+			this.mLayout.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).BeginInit();
+			this.mInfoBanner.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).BeginInit();
+			this.SuspendLayout();
+			// 
+			// mSearch
+			// 
+			this.mSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mSearch.Location = new System.Drawing.Point(1, 78);
+			this.mSearch.Margin = new System.Windows.Forms.Padding(1, 0, 1, 0);
+			this.mSearch.Name = "mSearch";
+			this.mSearch.Size = new System.Drawing.Size(521, 20);
+			this.mSearch.TabIndex = 0;
+			this.mSearch.LocationChanged += new System.EventHandler(this.mSearch_LocationChanged);
+			this.mSearch.TextChanged += new System.EventHandler(this.mSearch_TextChanged);
+			// 
+			// mResults
+			// 
+			this.mResults.BorderStyle = System.Windows.Forms.BorderStyle.None;
+			this.mResults.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mResults.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
+			this.mResults.FormattingEnabled = true;
+			this.mResults.IntegralHeight = false;
+			this.mResults.Location = new System.Drawing.Point(0, 98);
+			this.mResults.Margin = new System.Windows.Forms.Padding(0);
+			this.mResults.Name = "mResults";
+			this.mResults.Size = new System.Drawing.Size(523, 176);
+			this.mResults.TabIndex = 1;
+			this.mResults.TabStop = false;
+			this.mResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseClick);
+			this.mResults.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.mResults_DrawItem);
+			this.mResults.LocationChanged += new System.EventHandler(this.mResults_LocationChanged);
+			this.mResults.MouseEnter += new System.EventHandler(this.mResults_MouseEnter);
+			this.mResults.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseMove);
+			// 
+			// mLayout
+			// 
+			this.mLayout.ColumnCount = 1;
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+			this.mLayout.Controls.Add(this.mSearch, 0, 2);
+			this.mLayout.Controls.Add(this.mResults, 0, 3);
+			this.mLayout.Controls.Add(this.mBanner, 0, 0);
+			this.mLayout.Controls.Add(this.mInfoBanner, 0, 1);
+			this.mLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mLayout.Location = new System.Drawing.Point(0, 0);
+			this.mLayout.Name = "mLayout";
+			this.mLayout.RowCount = 4;
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.Size = new System.Drawing.Size(523, 274);
+			this.mLayout.TabIndex = 2;
+			// 
+			// mBanner
+			// 
+			this.mBanner.Dock = System.Windows.Forms.DockStyle.Top;
+			this.mBanner.Location = new System.Drawing.Point(0, 0);
+			this.mBanner.Margin = new System.Windows.Forms.Padding(0);
+			this.mBanner.Name = "mBanner";
+			this.mBanner.Size = new System.Drawing.Size(523, 60);
+			this.mBanner.TabIndex = 3;
+			this.mBanner.TabStop = false;
+			this.mBanner.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mBannerImage_MouseDown);
+			// 
+			// mInfoBanner
+			// 
+			this.mInfoBanner.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+			this.mInfoBanner.BackColor = System.Drawing.SystemColors.Info;
+			this.mInfoBanner.Controls.Add(this.mInfoLabel);
+			this.mInfoBanner.Controls.Add(this.mInfoBannerImage);
+			this.mInfoBanner.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoBanner.Location = new System.Drawing.Point(2, 61);
+			this.mInfoBanner.Margin = new System.Windows.Forms.Padding(2, 1, 1, 1);
+			this.mInfoBanner.Name = "mInfoBanner";
+			this.mInfoBanner.Size = new System.Drawing.Size(520, 16);
+			this.mInfoBanner.TabIndex = 8;
+			// 
+			// mInfoLabel
+			// 
+			this.mInfoLabel.AutoEllipsis = true;
+			this.mInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoLabel.ForeColor = System.Drawing.SystemColors.InfoText;
+			this.mInfoLabel.Location = new System.Drawing.Point(16, 0);
+			this.mInfoLabel.Name = "mInfoLabel";
+			this.mInfoLabel.Size = new System.Drawing.Size(504, 16);
+			this.mInfoLabel.TabIndex = 6;
+			this.mInfoLabel.Text = "AutoType failed to find";
+			// 
+			// mInfoBannerImage
+			// 
+			this.mInfoBannerImage.Dock = System.Windows.Forms.DockStyle.Left;
+			this.mInfoBannerImage.Image = global::AutoTypeSearch.Properties.Resources.Info;
+			this.mInfoBannerImage.Location = new System.Drawing.Point(0, 0);
+			this.mInfoBannerImage.Margin = new System.Windows.Forms.Padding(0);
+			this.mInfoBannerImage.Name = "mInfoBannerImage";
+			this.mInfoBannerImage.Size = new System.Drawing.Size(16, 16);
+			this.mInfoBannerImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mInfoBannerImage.TabIndex = 7;
+			this.mInfoBannerImage.TabStop = false;
+			// 
+			// mThrobber
+			// 
+			this.mThrobber.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.mThrobber.BackColor = System.Drawing.SystemColors.Window;
+			this.mThrobber.Location = new System.Drawing.Point(503, 81);
+			this.mThrobber.Name = "mThrobber";
+			this.mThrobber.Size = new System.Drawing.Size(16, 16);
+			this.mThrobber.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mThrobber.TabIndex = 4;
+			this.mThrobber.TabStop = false;
+			this.mThrobber.Visible = false;
+			// 
+			// mResultsUpdater
+			// 
+			this.mResultsUpdater.Interval = 250;
+			this.mResultsUpdater.Tick += new System.EventHandler(this.mResultsUpdater_Tick);
+			// 
+			// mNoResultsLabel
+			// 
+			this.mNoResultsLabel.AutoSize = true;
+			this.mNoResultsLabel.Location = new System.Drawing.Point(5, 103);
+			this.mNoResultsLabel.Name = "mNoResultsLabel";
+			this.mNoResultsLabel.Size = new System.Drawing.Size(84, 13);
+			this.mNoResultsLabel.TabIndex = 5;
+			this.mNoResultsLabel.Text = "No results found";
+			// 
+			// SearchWindow
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.BackColor = System.Drawing.SystemColors.Window;
+			this.ClientSize = new System.Drawing.Size(523, 274);
+			this.ControlBox = false;
+			this.Controls.Add(this.mNoResultsLabel);
+			this.Controls.Add(this.mThrobber);
+			this.Controls.Add(this.mLayout);
+			this.MinimumSize = new System.Drawing.Size(160, 96);
+			this.Name = "SearchWindow";
+			this.ShowInTaskbar = false;
+			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+			this.TopMost = true;
+			this.mLayout.ResumeLayout(false);
+			this.mLayout.PerformLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).EndInit();
+			this.mInfoBanner.ResumeLayout(false);
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).EndInit();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.TextBox mSearch;
+		private System.Windows.Forms.ListBox mResults;
+		private System.Windows.Forms.TableLayoutPanel mLayout;
+		private System.Windows.Forms.PictureBox mBanner;
+		private PictureBox mThrobber;
+		private Timer mResultsUpdater;
+		private Label mNoResultsLabel;
+		private Label mInfoLabel;
+		private Panel mInfoBanner;
+		private PictureBox mInfoBannerImage;
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchWindow.cs b/AutoTypeSearch/SearchWindow.cs
new file mode 100755
index 0000000..363b898
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.cs
@@ -0,0 +1,925 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Media;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Resources;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Collections;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	public partial class SearchWindow : Form
+	{
+		private const int SecondLineInset = 10;
+
+		// HACK to work around mono bug
+		private static readonly FieldInfo sMonoListBoxTopIndex = typeof(ListBox).GetField("top_index", BindingFlags.Instance | BindingFlags.NonPublic);
+
+		private readonly MainForm mMainForm;
+		private readonly Bitmap mBannerImage;
+		private readonly Searcher mSearcher;
+
+		private readonly Stream mThrobberImageStream;
+
+		private int? mWindowTopBorderHeight;
+		private int mBannerWidth = -1;
+		private int mMaximumExpandHeight;
+		private bool mManualSizeApplied;
+		private SearchResults mCurrentSearch;
+		private SearchResults mLastResultsUpdated;
+		private int mLastResultsUpdatedNextAvailableIndex;
+
+		#region Opening
+		public SearchWindow()
+		{
+			InitializeComponent();
+
+			// Mono can't load animated gifs from resx without crashing, so load it from an embedded resource instead
+			try
+			{
+				mThrobberImageStream = GetType().Assembly.GetManifestResourceStream("AutoTypeSearch.Throbber.gif");
+				if (mThrobberImageStream != null)
+				{
+					mThrobber.Image = Image.FromStream(mThrobberImageStream);
+				}
+			}
+			catch (Exception ex)
+			{
+				Debug.Fail("Failed to load Throbber.gif from embedded resource: " + ex.Message);
+			}
+
+			GlobalWindowManager.CustomizeControl(this);
+			UIUtil.SetExplorerTheme(mResults, true);
+			SetItemHeight();
+		}
+
+		public SearchWindow(MainForm mainForm, string infoBanner) : this()
+		{
+			mMainForm = mainForm;
+
+			mInfoBanner.Height = Math.Max(mInfoBannerImage.Height, mInfoLabel.Font.Height) + mInfoBanner.Margin.Vertical;
+			mInfoLabel.Padding = new Padding(0, (mInfoBanner.Height - mInfoLabel.Font.Height) / 2, 0, 0);
+			mInfoLabel.Text = infoBanner;
+
+			if (infoBanner == null)
+			{
+				mInfoBanner.Visible = false;
+				mInfoBanner.Height = 0;
+			}
+			
+			mSearcher = new Searcher(mMainForm.DocumentManager.GetOpenDatabases().ToArray());
+
+			Icon = mMainForm.Icon;
+			using (var bannerIcon = new Icon(Icon, 48, 48))
+			{
+				mBannerImage = bannerIcon.ToBitmap();
+			}
+			UpdateBanner();
+
+			ShowThrobber = false;
+
+			FontUtil.AssignDefaultItalic(mNoResultsLabel);
+		}
+
+
+		protected override void OnCreateControl()
+		{
+			base.OnCreateControl();
+
+			if (NativeMethods.IsWindows10())
+			{
+				mWindowTopBorderHeight = PointToScreen(Point.Empty).Y - this.Top;
+				NativeMethods.RefreshWindowFrame(Handle);
+			}
+
+			var windowRect = Settings.Default.WindowPosition;
+			var collapsedWindowRect = windowRect;
+			
+			collapsedWindowRect.Height = mSearch.Bottom + (Height - ClientSize.Height);
+
+			MinimumSize = new Size(MinimumSize.Width, collapsedWindowRect.Height);
+
+			if (windowRect.IsEmpty || !IsOnScreen(collapsedWindowRect))
+			{
+				windowRect = new Rectangle(0, 0, Width, Height);
+				Height = collapsedWindowRect.Height;
+
+				CenterToScreen();
+			}
+			else
+			{
+				Location = windowRect.Location;
+				Size = collapsedWindowRect.Size;
+			}
+
+			mMaximumExpandHeight = Math.Max(windowRect.Height, MinimumSize.Height + mResults.ItemHeight);
+		}
+		
+
+		private static bool IsOnScreen(Rectangle rectangle)
+		{
+			return Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(rectangle));
+		}
+
+		private void SetItemHeight()
+		{
+			mResults.ItemHeight = mResults.Font.Height * 2 + 2;
+		}
+
+		protected override void WndProc(ref Message m)
+		{
+			if (mWindowTopBorderHeight.HasValue)
+			{
+				NativeMethods.RemoveWindowFrameTopBorder(ref m, mWindowTopBorderHeight.Value);
+			}
+			base.WndProc(ref m);
+		}
+
+		#endregion
+
+		#region Closing
+		protected override void OnActivated(EventArgs e)
+		{
+			base.OnActivated(e);
+			Deactivate += OnDeactivate;
+		}
+
+		private void OnDeactivate(object sender, EventArgs eventArgs)
+		{
+			Close();
+		}
+
+		protected override void OnClosed(EventArgs e)
+		{
+			Deactivate -= OnDeactivate;
+			base.OnClosed(e);
+		}
+
+		/// 
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				if (mBannerImage != null)
+				{
+					mBannerImage.Dispose();
+				}
+				if (mThrobber.Image != null)
+				{
+					mThrobber.Image.Dispose();
+					mThrobber.Image = null;
+					mThrobberImageStream.Dispose();
+				}
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+		#endregion
+
+		#region Item Drawing
+		private void mResults_DrawItem(object sender, DrawItemEventArgs e)
+		{
+			var searchResult = mResults.Items[e.Index] as SearchResult;
+			if (searchResult == null)
+			{
+				Debug.Fail("Unexpected item in mResults");
+// ReSharper disable once HeuristicUnreachableCode - Not unreachable
+				return;
+			}
+			var drawingArea = e.Bounds;
+			drawingArea.Height--; // Leave room for a dividing line at the bottom
+			
+			if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
+			{
+				DrawBorderedRectangle(e.Graphics, drawingArea, SystemColors.Highlight);
+			}
+			else
+			{
+				e.Graphics.FillRectangle(SystemBrushes.Window, drawingArea);
+			}
+
+			var image = GetImage(searchResult.Database, searchResult.Entry.CustomIconUuid, searchResult.Entry.IconId);
+			var imageMargin = (drawingArea.Height - image.Height) / 2;
+			e.Graphics.DrawImage(image, drawingArea.Left + imageMargin, drawingArea.Top + imageMargin, image.Width, image.Height);
+
+			var textLeftMargin = drawingArea.Left + imageMargin * 2 + image.Width;
+			var textBounds = new Rectangle(textLeftMargin, drawingArea.Top + 1, drawingArea.Width - textLeftMargin - 1, drawingArea.Height - 2);
+
+			var line1Bounds = textBounds;
+			line1Bounds.Height = e.Font.Height;
+			var line2Bounds = line1Bounds;
+			line2Bounds.Y += line2Bounds.Height - 1;
+			line2Bounds.X += SecondLineInset;
+			line2Bounds.Width -= SecondLineInset;
+
+			var resultInTitleField = searchResult.FieldName == PwDefs.TitleField;
+
+			var title = (resultInTitleField ? searchResult.FieldValue : searchResult.Title).Replace('\n', ' '); // The FieldValue may have references resolved, whereas the title is always read directly.
+
+			var uniqueTitlePartWidth = 0;
+			if (!String.IsNullOrEmpty(searchResult.UniqueTitlePart))
+			{
+				var uniqueTitlePart = searchResult.UniqueTitlePart.Replace('\n', ' ');
+
+				var titleWidth = TextRenderer.MeasureText(e.Graphics, title, e.Font, line1Bounds.Size, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+
+				var availableWidthForUniqueTitlePart = line1Bounds.Width - titleWidth;
+				if (availableWidthForUniqueTitlePart > 20) // Don't bother including a unique part if there's no room for it
+				{
+					var uniqueTitlePartReversed = ReverseString(uniqueTitlePart);
+
+					uniqueTitlePartWidth = TextRenderer.MeasureText(e.Graphics, uniqueTitlePartReversed, e.Font, new Size(availableWidthForUniqueTitlePart, line1Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+					uniqueTitlePart = ReverseString(uniqueTitlePartReversed);
+
+					TextRenderer.DrawText(e.Graphics, uniqueTitlePart, e.Font, new Rectangle(line1Bounds.X, line1Bounds.Y, uniqueTitlePartWidth, line1Bounds.Height), SystemColors.GrayText, TextFormatFlags.NoPadding);
+				}
+			}
+
+			var titleBounds = new Rectangle(line1Bounds.X + uniqueTitlePartWidth, line1Bounds.Y, line1Bounds.Width - uniqueTitlePartWidth, line1Bounds.Height);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Highlight title in first line.
+				DrawHighlight(e, titleBounds, title, searchResult.Start, searchResult.Length);
+			}
+
+			TextRenderer.DrawText(e.Graphics, searchResult.Title, e.Font, titleBounds, SystemColors.WindowText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Use Username for second line.
+				TextRenderer.DrawText(e.Graphics, KPRes.UserName + ": " + searchResult.Entry.Strings.ReadSafeEx(PwDefs.UserNameField), e.Font, line2Bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+			}
+			else
+			{
+				// Found the result in not title field. Show the matching result on second line
+				
+				var fieldValue = searchResult.FieldValue.Replace('\n',' ');
+				var fieldNamePrefix = GetDisplayFieldName(searchResult.FieldName) + ": ";
+
+				var remainingSpace = line2Bounds.Width;
+				var fieldNamePrefixWidth = TextRenderer.MeasureText(e.Graphics, fieldNamePrefix, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+				remainingSpace -= fieldNamePrefixWidth;
+
+				int fieldValueHighlightWidth = 0, fieldValueLeftContextWidth = 0, fieldValueRightContextWidth = 0;
+
+				var leftContext = fieldValue.Substring(0, searchResult.Start);
+				var highlight = fieldValue.Substring(searchResult.Start, searchResult.Length);
+				var rightContext = fieldValue.Substring(searchResult.Start + searchResult.Length);
+
+				if (searchResult.Length == 0)
+				{
+					fieldValueHighlightWidth = remainingSpace;
+				}
+				else
+				{
+					if (remainingSpace > 0)
+					{
+						var availableSpace = remainingSpace;
+						fieldValueHighlightWidth = TextRenderer.MeasureText(e.Graphics, highlight, e.Font, new Size(availableSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						remainingSpace -= fieldValueHighlightWidth;
+					}
+
+					// Of the space remaining, divide it equally between that which comes before, and that which comes after
+					if (!String.IsNullOrEmpty(leftContext))
+					{
+						var leftContextReversed = ReverseString(leftContext);
+						fieldValueLeftContextWidth = TextRenderer.MeasureText(e.Graphics, leftContextReversed, e.Font, new Size(remainingSpace / 2, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+						if (fieldValueLeftContextWidth > remainingSpace)
+						{
+							// Always allow space for the minimal left context
+							fieldValueHighlightWidth -= (fieldValueLeftContextWidth - remainingSpace);
+							remainingSpace = 0;
+						}
+						else
+						{
+							remainingSpace -= fieldValueLeftContextWidth;							
+						}
+						
+						// Replace left context with the truncated reversed left context.
+						leftContext = ReverseString(leftContextReversed);
+					}
+
+					if (remainingSpace > 0 && !String.IsNullOrEmpty(rightContext))
+					{
+						fieldValueRightContextWidth = TextRenderer.MeasureText(e.Graphics, rightContext, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						if (fieldValueRightContextWidth > remainingSpace)
+						{
+							fieldValueRightContextWidth = 0;
+						}
+					}
+				}
+
+				// Now draw it all
+				var bounds = line2Bounds;
+				bounds.Width = fieldNamePrefixWidth;
+				TextRenderer.DrawText(e.Graphics, fieldNamePrefix, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				if (fieldValueLeftContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueLeftContextWidth;
+					TextRenderer.DrawText(e.Graphics, leftContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding); // No ellipsis as the leftContext string has already been truncated appropriately
+				}
+				if (fieldValueHighlightWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueHighlightWidth;
+
+					if (searchResult.Length > 0)
+					{
+						DrawHighlightRectangle(e, bounds);
+					}
+					TextRenderer.DrawText(e.Graphics, highlight, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+				if (fieldValueRightContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueRightContextWidth;
+					TextRenderer.DrawText(e.Graphics, rightContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+			}
+
+			e.Graphics.DrawLine(SystemPens.ButtonFace, drawingArea.Left, drawingArea.Bottom, drawingArea.Right, drawingArea.Bottom);
+		}
+
+		private static string ReverseString(string value)
+		{
+			return new String(value.ToCharArray().TakeWhile(c => c != '\0').Reverse().ToArray());
+		}
+
+		private static void DrawHighlight(DrawItemEventArgs e, Rectangle lineBounds, string text, int highlightFrom, int highlightLength)
+		{
+			var highlightX = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width;
+			var highlightWidth = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom + highlightLength), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width - highlightX;
+
+			DrawHighlightRectangle(e, new Rectangle(lineBounds.Left + highlightX, lineBounds.Top, highlightWidth, lineBounds.Height));
+		}
+
+		private static void DrawHighlightRectangle(DrawItemEventArgs e, Rectangle rectangle)
+		{
+			DrawBorderedRectangle(e.Graphics, rectangle, Color.PaleTurquoise);
+		}
+
+		private static void DrawBorderedRectangle(Graphics graphics, Rectangle rectangle, Color colour)
+		{
+			var border = rectangle;
+			border.Width--;
+			border.Height--;
+
+			using (var brush = new SolidBrush(MergeColors(colour, SystemColors.Window, 0.2)))
+			{
+				graphics.FillRectangle(brush, rectangle);
+			}
+			using (var pen = new Pen(colour, 1f))
+			{
+				graphics.DrawRectangle(pen, border);
+			}
+		}
+
+		private Image GetImage(PwDatabase database, PwUuid customIconId, PwIcon iconId)
+		{
+			Image image = null;
+			if (!customIconId.Equals(PwUuid.Zero))
+			{
+				image = database.GetCustomIcon(customIconId, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16));
+			}
+			if (image == null)
+			{
+				try { image = mMainForm.ClientIcons.Images[(int)iconId]; }
+				catch (Exception) { Debug.Assert(false); }
+			}
+
+			return image;
+		}
+
+		private static string GetDisplayFieldName(string fieldName)
+		{
+			switch (fieldName)
+			{
+				case PwDefs.TitleField:
+					return KPRes.Title;
+				case PwDefs.UserNameField:
+					return KPRes.UserName;
+				case PwDefs.PasswordField:
+					return KPRes.Password;
+				case PwDefs.UrlField:
+					return KPRes.Url;
+				case PwDefs.NotesField:
+					return KPRes.Notes;
+				case AutoTypeSearchExt.TagsVirtualFieldName:
+					return KPRes.Tags;
+				default:
+					return fieldName;
+			}
+		}
+
+		public static Color MergeColors(Color from, Color to, double amount)
+		{
+			var r = (byte)((from.R * amount) + to.R * (1 - amount));
+			var g = (byte)((from.G * amount) + to.G * (1 - amount));
+			var b = (byte)((from.B * amount) + to.B * (1 - amount));
+			return Color.FromArgb(r, g, b);
+		}
+		#endregion
+
+		#region Mouse tracking
+		private Point mMouseEntryPosition;
+		
+		private void mResults_MouseEnter(object sender, EventArgs e)
+		{
+			mMouseEntryPosition = MousePosition;
+		}
+
+		private void mResults_MouseMove(object sender, MouseEventArgs e)
+		{
+			// Discard the location the mouse has on entering the control (as it may be that the control has just moved under the mouse, not the other way around)
+			if (MousePosition == mMouseEntryPosition)
+			{
+				return;
+			}
+
+			// Hot tracking
+			var hoverIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (hoverIndex >= 0 && mResults.SelectedIndex != hoverIndex)
+			{
+				if (mResults.GetItemRectangle(hoverIndex).Bottom <= mResults.ClientRectangle.Bottom)
+				{
+					mResults.SelectedIndex = hoverIndex;
+				}
+				else
+				{
+					// Avoid the control scrolling
+					mResults.BeginUpdate();
+					var topIndex = mResults.TopIndex;
+					mResults.SelectedIndex = hoverIndex;
+					mResults.TopIndex = topIndex;
+					mResults.EndUpdate();
+				}
+			}
+		}
+		#endregion
+
+		#region Resizing
+		protected override void OnResizeBegin(EventArgs e)
+		{
+			// Stop automatically sizing - the user is picking a size they want.
+			mManualSizeApplied = true;
+			base.OnResizeBegin(e);
+		}
+
+		protected override void OnResize(EventArgs e)
+		{
+			base.OnResize(e);
+
+			UpdateBanner();
+
+			mResults.Invalidate();
+		}
+
+		protected override void OnResizeEnd(EventArgs e)
+		{
+			base.OnResizeEnd(e);
+
+			if (Height > MinimumSize.Height && Height != mMaximumExpandHeight)
+			{
+				mMaximumExpandHeight = Math.Max(Height, MinimumSize.Height + mResults.ItemHeight);
+			}
+			else
+			{
+				mManualSizeApplied = false;
+			}
+
+			Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+		}
+
+		private void UpdateBanner()
+		{
+			if (mBannerImage != null)
+			{
+				BannerFactory.UpdateBanner(this, mBanner, mBannerImage, PwDefs.ProductName, Resources.BannerText, ref mBannerWidth);
+			}
+		}
+
+		private void mSearch_LocationChanged(object sender, EventArgs e)
+		{
+			mThrobber.Location = new Point(mSearch.Right - mThrobber.Width - mThrobber.Margin.Right, mSearch.Top + (mSearch.Height - mThrobber.Height) / 2);
+		}
+
+		private void mResults_LocationChanged(object sender, EventArgs e)
+		{
+			mNoResultsLabel.Top = mResults.Top + (mResults.ItemHeight - mNoResultsLabel.Height) / 2;
+		}
+		#endregion
+
+		#region Searching
+		private static readonly SearchResultPrecedence SearchResultPrecedenceComparer = new SearchResultPrecedence();
+		private void mSearch_TextChanged(object sender, EventArgs e)
+		{
+			if (mSearch.Text.Length < 2)
+			{
+				// Stop searching
+				mResultsUpdater.Enabled = false;
+				ShowThrobber = false;
+				Height = MinimumSize.Height;
+				mManualSizeApplied = false;
+				mResults.Items.Clear();
+				mLastResultsUpdated = null;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			else
+			{
+				// Start searching
+				mNoResultsLabel.Visible = false;
+				mCurrentSearch = mSearcher.Search(mSearch.Text);
+				mResultsUpdater.Enabled = true;
+				ShowThrobber = true;
+				mResultsUpdater_Tick(null, EventArgs.Empty); // Quick poke just in case the results are already done.
+			}
+		}
+
+		[SuppressMessage("ReSharper", "CoVariantArrayConversion", Justification = "Object arrays for Listbox.Items, known to be of correct type")]
+		private void mResultsUpdater_Tick(object sender, EventArgs e)
+		{
+			if (mLastResultsUpdated != mCurrentSearch)
+			{
+				// Clear out old results and replace with new ones
+				mResults.Items.Clear();
+				mLastResultsUpdated = mCurrentSearch;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			var existingResultsCount = mResults.Items.Count;
+			
+			bool complete;
+			var newResults = mLastResultsUpdated.GetAvailableResults(ref mLastResultsUpdatedNextAvailableIndex, out complete);
+			if (newResults.Length > 0)
+			{
+				mResults.BeginUpdate();
+				
+				SearchResult[] allResults;
+				if (existingResultsCount > 0)
+				{
+					allResults = new SearchResult[existingResultsCount + newResults.Length];
+					mResults.Items.CopyTo(allResults, 0);
+					newResults.CopyTo(allResults, existingResultsCount);
+
+					mResults.Items.Clear();
+				}
+				else
+				{
+					allResults = newResults;
+				}
+
+				CalculateUniqueTitles(allResults);
+
+				Array.Sort(allResults, SearchResultPrecedenceComparer);
+				mResults.Items.AddRange(allResults);
+				
+				mResults.EndUpdate();
+
+				if (allResults.Length > 0)
+				{
+					if (mResults.SelectedIndex == -1)
+					{
+						try
+						{
+							// HACK to work around mono bug
+							if (sMonoListBoxTopIndex != null)
+							{
+								sMonoListBoxTopIndex.SetValue(mResults, 1); // Set the top_index to 1 so that when selected index is set to 0, and calls EnsureVisible(0), it follows the index < top_index pass and not the broken index >= top_index + rows path. 
+							}
+
+							mResults.SelectedIndex = 0;
+							mResults.TopIndex = 0;
+						}
+						catch (Exception ex)
+						{
+							Debug.Fail("Failed to set selection on count of " + allResults.Length + ": " + ex.Message);
+						}
+					}
+
+					if (!mManualSizeApplied)
+					{
+						Height = Math.Min(mMaximumExpandHeight, MinimumSize.Height + (allResults.Length * mResults.ItemHeight));
+					}
+				}
+			}
+
+			if (complete)
+			{
+				ShowThrobber = false;
+				mResultsUpdater.Enabled = false;
+
+				if (mResults.Items.Count == 0)
+				{
+					mNoResultsLabel.Visible = true;
+					Height = MinimumSize.Height + mResults.ItemHeight;
+					mManualSizeApplied = false;
+				}
+			}
+		}
+
+		private void CalculateUniqueTitles(IEnumerable results, int depth = 0)
+		{
+			// Where results have identical titles, include group titles to make them unique
+			depth += 1;
+
+			// First create a lookup by title
+			var titles = new Dictionary>();
+			foreach (var searchResult in results)
+			{
+				List resultsWithSameTitle;
+				if (titles.TryGetValue(searchResult.UniqueTitle, out resultsWithSameTitle))
+				{
+					resultsWithSameTitle.Add(searchResult);
+				}
+				else
+				{
+					titles.Add(searchResult.UniqueTitle, new List { searchResult });
+				}
+			}
+
+			// Attempt to unique-ify any non-unique titles
+			foreach (var resultsSharingTitle in titles.Values)
+			{
+				if (resultsSharingTitle.Count > 1)
+				{
+					var titlesModified = false;
+					foreach (var searchResult in resultsSharingTitle)
+					{
+						titlesModified |= searchResult.SetUniqueTitleDepth(depth);
+					}
+
+					if (titlesModified)
+					{
+						// Recurse in case of continuing non-uniqueness
+						CalculateUniqueTitles(resultsSharingTitle, depth);
+					}
+				}
+			}
+		}
+
+		private class SearchResultPrecedence : IComparer
+		{
+			public int Compare(SearchResult x, SearchResult y)
+			{
+				// First precedence is that if the result is the start of the field value, it's higher precedence than if it doesn't.
+				var result = -(x.Start == 0).CompareTo(y.Start == 0);
+
+				// Second precedence is that the start of the title field is higher precedence than the start of any other field
+				if (result == 0)
+				{
+					result = -(x.FieldName == PwDefs.TitleField).CompareTo(y.FieldName == PwDefs.TitleField);
+				}
+
+				// Both start the title field, so both equal. Have to have consistent ordering, so return final precedence based search index
+				if (result == 0)
+				{
+					result = x.ResultIndex.CompareTo(y.ResultIndex);
+				}
+				
+				return result;
+			}
+		}
+
+		private bool ShowThrobber
+		{
+			get { return mThrobber.Visible; }
+			set
+			{
+				if (value != ShowThrobber)
+				{
+					if (value)
+					{
+						mThrobber.Visible = true;
+
+						// Set the margin on the textbox to allow room for the throbber
+						NativeMethods.SetTextBoxRightMargin(mSearch, mThrobber.Width + mThrobber.Margin.Right);
+					}
+					else
+					{
+						mThrobber.Visible = false;
+
+						NativeMethods.SetTextBoxRightMargin(mSearch, 0);
+					}
+				}
+			}
+		}
+		#endregion
+
+		private void mBannerImage_MouseDown(object sender, MouseEventArgs e)
+		{
+			// Allow drag by banner image
+			if (e.Button == MouseButtons.Left)
+			{
+				if (e.Clicks == 2)
+				{
+					// Re-center the form on double-click
+					CenterToScreen();
+
+					Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+				}
+				else if (!NativeLib.IsUnix())
+				{
+					NativeMethods.StartFormDrag(this);
+				}
+			}
+		}
+
+		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+		{
+			switch (keyData)
+			{
+				case Keys.Escape:
+					Close();
+					return true;
+				case Keys.Up:
+					TryChangeSelection(-1);
+					return true;
+				case Keys.Down:
+					TryChangeSelection(1);
+					return true;
+				case Keys.PageUp:
+					TryChangeSelection(-mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.PageDown:
+					TryChangeSelection(mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.Home | Keys.Control:
+					mResults.SelectedIndex = 0;
+					return true;
+				case Keys.End | Keys.Control:
+					mResults.SelectedIndex = mResults.Items.Count - 1;
+					return true;
+				case Keys.Enter:
+					PerformAction(Settings.Default.DefaultAction, mResults.SelectedItem as SearchResult);
+					break;
+				case Keys.Enter | Keys.Shift:
+					PerformAction(Settings.Default.AlternativeAction, mResults.SelectedItem as SearchResult);
+					break;
+			}
+			
+			return base.ProcessCmdKey(ref msg, keyData);
+		}
+
+		#region Selection Changing
+
+		protected override void OnMouseWheel(MouseEventArgs e)
+		{
+			mResults.TopIndex -= (e.Delta / Math.Abs(e.Delta));
+		}
+
+		private void TryChangeSelection(int delta)
+		{
+			if (mResults.Items.Count > 0)
+			{
+				mResults.SelectedIndex = Math.Max(Math.Min(mResults.Items.Count - 1, mResults.SelectedIndex + delta), 0);
+			}
+		}
+		#endregion
+
+		#region Actions
+
+		private void mResults_MouseClick(object sender, MouseEventArgs e)
+		{
+			var clickIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (clickIndex >= 0)
+			{
+				var clickedResult = mResults.Items[clickIndex] as SearchResult;
+				if (clickedResult != null)
+				{
+					PerformAction((ModifierKeys & Keys.Shift) == Keys.Shift ? Settings.Default.AlternativeAction : Settings.Default.DefaultAction, clickedResult);
+				}
+			}
+		}
+
+		private void PerformAction(Actions action, SearchResult searchResult)
+		{
+			Close();
+
+			if (searchResult != null)
+			{
+				switch (action)
+				{
+					case Actions.PerformAutoType:
+						AutoTypeEntry(searchResult);
+						break;
+					case Actions.EditEntry:
+						EditEntry(searchResult);
+						break;
+					case Actions.ShowEntry:
+						ShowEntry(searchResult);
+						break;
+					case Actions.OpenEntryUrl:
+						OpenEntryUrl(searchResult);
+						break;
+					case Actions.CopyPassword:
+						CopyPassword(searchResult);
+						break;
+					default:
+						throw new ArgumentOutOfRangeException("action");
+				}
+			}
+		}
+
+		private void AutoTypeEntry(SearchResult searchResult)
+		{
+			bool result;
+			if (ActiveForm != null)
+			{
+				result = AutoType.PerformIntoPreviousWindow(mMainForm, searchResult.Entry, searchResult.Database);
+			}
+			else
+			{
+				result = AutoType.PerformIntoCurrentWindow(searchResult.Entry, searchResult.Database);
+			}
+			if (!result)
+			{
+				SystemSounds.Beep.Play();
+
+				if (Settings.Default.AlternativeAction != Actions.PerformAutoType)
+				{
+					PerformAction(Settings.Default.AlternativeAction, searchResult);
+				}
+			}
+		}
+
+		private void EditEntry(SearchResult searchResult)
+		{
+			using (var entryForm = new PwEntryForm())
+			{
+				mMainForm.MakeDocumentActive(mMainForm.DocumentManager.FindDocument(searchResult.Database));
+				
+				entryForm.InitEx(searchResult.Entry, PwEditMode.EditExistingEntry, searchResult.Database, mMainForm.ClientIcons, false, false);
+
+				ShowForegroundDialog(entryForm);
+
+				mMainForm.UpdateUI(false, null, searchResult.Database.UINeedsIconUpdate, null, true, null, entryForm.HasModifiedEntry);
+			}
+		}
+
+// ReSharper disable once UnusedMethodReturnValue.Local - Generic helper, result may be used in future
+		private DialogResult ShowForegroundDialog(Form form)
+		{
+			mMainForm.EnsureVisibleForegroundWindow(false, false);
+			form.StartPosition = FormStartPosition.CenterScreen;
+			if (mMainForm.IsTrayed())
+			{
+				form.ShowInTaskbar = true;
+			}
+
+			form.Shown += ActivateFormOnShown;
+			return form.ShowDialog(mMainForm);
+		}
+
+		private static void ActivateFormOnShown(object sender, EventArgs eventArgs)
+		{
+			var form = (Form)sender;
+			form.Shown -= ActivateFormOnShown;
+			form.Activate();
+		}
+
+		private void ShowEntry(SearchResult searchResult)
+		{
+			// Show this entry
+			mMainForm.UpdateUI(false, mMainForm.DocumentManager.FindDocument(searchResult.Database), true, searchResult.Entry.ParentGroup, true, null, false, null);
+			mMainForm.SelectEntries(new PwObjectList { searchResult.Entry }, true, true);
+			mMainForm.EnsureVisibleEntry(searchResult.Entry.Uuid);
+			mMainForm.UpdateUI(false, null, false, null, false, null, false);
+			mMainForm.EnsureVisibleForegroundWindow(true, true);
+		}
+
+		private void OpenEntryUrl(SearchResult searchResult)
+		{
+			WinUtil.OpenEntryUrl(searchResult.Entry);
+		}
+
+		private void CopyPassword(SearchResult searchResult)
+		{
+			if (ClipboardUtil.Copy(searchResult.Entry.Strings.ReadSafe(PwDefs.PasswordField), true, true, searchResult.Entry,
+									mMainForm.DocumentManager.SafeFindContainerOf(searchResult.Entry),
+									IntPtr.Zero))
+			{
+				mMainForm.StartClipboardCountdown();
+			}
+		}
+		
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.resx b/AutoTypeSearch/SearchWindow.resx
new file mode 100755
index 0000000..8ef82f0
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.resx
@@ -0,0 +1,123 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    17, 17
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Searcher.cs b/AutoTypeSearch/Searcher.cs
new file mode 100755
index 0000000..433ae94
--- /dev/null
+++ b/AutoTypeSearch/Searcher.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class Searcher
+	{
+		private readonly PwDatabase[] mDatabases;
+		private readonly Dictionary mSearches = new Dictionary();
+
+		public Searcher(PwDatabase[] databases)
+		{
+			mDatabases = databases;
+		}
+
+		public SearchResults Search(string term)
+		{
+			if (term.Length < 2)
+			{
+				throw new ArgumentException("Search term must be at least 2 characters");
+			}
+
+			SearchResults parentResults = null;
+
+			var termParent = term;
+			while (termParent.Length >= 2)
+			{
+				if (mSearches.TryGetValue(termParent, out parentResults))
+				{
+					if (termParent == term)
+					{
+						// This is an exact duplicate search, so return it.
+						return parentResults;
+					}
+
+					// Found an existing search for a parent of the term, start from there.
+					break;
+				}
+		
+				// No existing search for termParent found, try less.
+				termParent = termParent.Remove(termParent.Length - 1, 1);
+			}
+
+			SearchResults searchResults;
+			if (parentResults == null)
+			{
+				// No parent found at all, start from scratch
+				searchResults = new SearchResults(GetCountOfAllDatabaseEntries(), term);
+
+				var rootSearchThread = new Thread(RootSearchWorker) { Name = term };
+				rootSearchThread.Start(searchResults);
+			}
+			else
+			{
+				searchResults = parentResults.CreateChildResults(term);
+
+				var childSearchThread = new Thread(ChildSearchWorker) { Name = term };
+				childSearchThread.Start(new ChildSearchWorkerState{ Source = parentResults, Results = searchResults });
+			}
+
+			mSearches.Add(term, searchResults);
+
+			return searchResults;
+		}
+
+		private int GetCountOfAllDatabaseEntries()
+		{
+			return (from database in mDatabases select (int)database.RootGroup.GetEntriesCount(true)).Sum();
+		}
+
+		private void RootSearchWorker(object stateObject)
+		{
+			var results = (SearchResults)stateObject;
+			var excludeExpired = Settings.Default.ExcludeExpired;
+			var searchStartTime = DateTime.Now;
+
+			foreach (var database in mDatabases)
+			{
+				SearchGroup(database, database.RootGroup, results, excludeExpired, searchStartTime);	
+			}
+
+			results.SetComplete();
+		}
+
+		/// 
+		/// Recursively search  and its children, adding results to 
+		/// 
+		private void SearchGroup(PwDatabase context, PwGroup group, SearchResults results, bool excludeExpired, DateTime searchStartTime)
+		{
+			if (group.EnableSearching ?? true) // Group will only be searched if it's parent enabled searching, so if it is inherit (null) or true, search it.
+			{
+				foreach (var childGroup in group.Groups)
+				{
+					SearchGroup(context, childGroup, results, excludeExpired, searchStartTime);
+				}
+
+				foreach (var entry in group.Entries)
+				{
+					if (!(excludeExpired && entry.Expires && searchStartTime > entry.ExpiryTime))
+					{
+						results.AddResultIfMatchesTerm(context, entry);
+					}
+				}
+			}
+		}
+
+		private struct ChildSearchWorkerState
+		{
+			public SearchResults Source;
+			public SearchResults Results;
+		}
+		private void ChildSearchWorker(object stateObject)
+		{
+			var state = (ChildSearchWorkerState)stateObject;
+
+			bool complete;
+			var index = 0;
+			do
+			{
+				foreach (var entry in state.Source.GetAvailableResults(ref index, out complete))
+				{
+					state.Results.AddResultIfMatchesTerm(entry);
+				}
+			} while (!complete);
+
+			state.Results.SetComplete();
+		}
+	}
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/AutoTypeSearch/SearchResults.cs b/AutoTypeSearch/SearchResults.cs
new file mode 100755
index 0000000..b2b0529
--- /dev/null
+++ b/AutoTypeSearch/SearchResults.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePass.Util.Spr;
+using KeePassLib;
+using KeePassLib.Utility;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResults
+	{
+		private readonly string mTerm;
+		private readonly SearchResult[] mResults;
+
+		private readonly object mLock = new object();
+		private volatile int mCount;
+		private volatile bool mComplete;
+
+		private readonly AutoResetEvent mResultsUpdated = new AutoResetEvent(false);
+
+		private readonly CompareOptions mStringComparison;
+		private readonly bool mSearchTitle;
+		private readonly bool mSearchUserName;
+		private readonly bool mSearchUrl;
+		private readonly bool mSearchNotes;
+		private readonly bool mSearchCustomFields;
+		private readonly bool mResolveReferences;
+		private readonly bool mSearchTags;
+
+		public SearchResults(int capacity, string term)
+		{
+			mTerm = term;
+			mResults = new SearchResult[capacity];
+
+			mStringComparison = Settings.Default.CaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase;
+			mStringComparison |= CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace;
+			mSearchTitle = Settings.Default.SearchTitle;
+			mSearchUserName = Settings.Default.SearchUserName;
+			mSearchUrl = Settings.Default.SearchUrl;
+			mSearchNotes = Settings.Default.SearchNotes;
+			mSearchCustomFields = Settings.Default.SearchCustomFields;
+			mSearchTags = Settings.Default.SearchTags;
+			mResolveReferences = Settings.Default.ResolveReferences;
+		}
+
+		/// 
+		/// Gets an ordered list of fields to search for the term
+		/// 
+		/// 
+		/// 
+		private IEnumerable GetFieldsToSearch(PwEntry entry)
+		{
+			var fieldsToSearch = new List((int)entry.Strings.UCount);
+			if (mSearchTitle) fieldsToSearch.Add(PwDefs.TitleField);
+			if (mSearchUserName) fieldsToSearch.Add(PwDefs.UserNameField);
+			if (mSearchUrl) fieldsToSearch.Add(PwDefs.UrlField);
+			if (mSearchNotes) fieldsToSearch.Add(PwDefs.NotesField);
+			if (mSearchCustomFields)
+			{
+				foreach (var stringEntry in entry.Strings)
+				{
+					if (!stringEntry.Value.IsProtected && !PwDefs.IsStandardField(stringEntry.Key))
+					{
+						fieldsToSearch.Add(stringEntry.Key);
+					}
+				}
+			}
+			if (mSearchTags) fieldsToSearch.Add(AutoTypeSearchExt.TagsVirtualFieldName);
+
+			return fieldsToSearch;
+		}
+
+		public void AddResultIfMatchesTerm(PwDatabase context, PwEntry entry)
+		{
+			// First try without resolving
+			var addedResult = AddResultIfMatchesTerm(context, entry, false);
+
+			if (!addedResult && mResolveReferences)
+			{
+				// Not found without resolving, so try resolving
+				AddResultIfMatchesTerm(context, entry, true);
+			}
+		}
+
+		private bool AddResultIfMatchesTerm(PwDatabase context, PwEntry entry, bool resolveReferences)
+		{
+			foreach (var fieldName in GetFieldsToSearch(entry))
+			{
+				string fieldValue;
+				if (fieldName == AutoTypeSearchExt.TagsVirtualFieldName)
+				{
+					fieldValue = StrUtil.TagsToString(entry.Tags, true);
+				}
+				else
+				{
+					fieldValue = entry.Strings.ReadSafeEx(fieldName);
+
+					if (resolveReferences)
+					{
+						fieldValue = ResolveReferences(context, entry, fieldValue);
+					}
+				}
+
+				if (!String.IsNullOrEmpty(fieldValue))
+				{
+					var foundIndex = CultureInfo.CurrentCulture.CompareInfo.IndexOf(fieldValue, mTerm, mStringComparison);
+					if (foundIndex >= 0)
+					{
+						// Found a match, create a search result and add it
+						AddResult(new SearchResult(context, entry, entry.Strings.ReadSafe(PwDefs.TitleField), fieldName, fieldValue, foundIndex, mTerm.Length));
+						return true;
+					}
+				}
+			}
+			return false;
+		}
+
+		/// 
+		/// Resolves any references in the field value and returns it. If there were no references,
+		/// returns null (to avoid duplicate searching - it is assumed that the unresolved value has already been searched)
+		/// 
+		private string ResolveReferences(PwDatabase context, PwEntry entry, string fieldValue)
+		{
+			if (fieldValue.IndexOf('{') < 0)
+			{
+				// Can't contain any references
+				return null;
+			}
+			
+			var sprContext = new SprContext(entry, context, SprCompileFlags.Deref) { ForcePlainTextPasswords = false };
+
+			var result = SprEngine.Compile(fieldValue, sprContext);
+			if (CultureInfo.CurrentCulture.CompareInfo.Compare(result,fieldValue, mStringComparison) == 0)
+			{
+				return null;
+			}
+			
+			return result;
+		}
+
+		public void AddResultIfMatchesTerm(SearchResult candidate)
+		{
+			// First see whether the existing candidate is a further match in the same place
+			var fieldValue = candidate.FieldValue;
+			if (fieldValue.Length > candidate.Start + mTerm.Length && CultureInfo.CurrentCulture.CompareInfo.Compare(fieldValue.Substring(candidate.Start, mTerm.Length), mTerm, mStringComparison) == 0)
+			{
+				// Yep, match continues, so add it.
+				AddResult(new SearchResult(candidate.Database, candidate.Entry, candidate.Title, candidate.FieldName, fieldValue, candidate.Start, mTerm.Length));
+			}
+			else
+			{
+				// Existing candidate match couldn't be extended, so search from scratch again
+				AddResultIfMatchesTerm(candidate.Database, candidate.Entry);
+			}
+		}
+
+		private void AddResult(SearchResult result)
+		{
+			lock (mLock)
+			{
+				if (mComplete)
+				{
+					throw new InvalidOperationException("Search results have been completed");
+				}
+				result.SetResultIndex(mCount);
+				mResults[mCount++] = result;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Indicates that the results are complete, and no more will be added.
+		/// 
+		public void SetComplete()
+		{
+			lock (mLock)
+			{
+				mComplete = true;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Gets all the available results so far.
+		/// 
+		/// Index to start returning from. Modified to be the first index not available yet on return.
+		/// Set to true if the results are complete, false if more results are pending but have not been returned.
+		/// 
+		public SearchResult[] GetAvailableResults(ref int index, out bool complete)
+		{
+			int count;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			if (count <= index)
+			{
+				return new SearchResult[0];
+			}
+
+			var availableResults = new SearchResult[count - index];
+			Array.Copy(mResults, index, availableResults, 0, availableResults.Length);
+			index = count;
+
+			return availableResults;
+		}
+
+		/// 
+		/// Gets all the results. Will block until complete.
+		/// 
+		/// 
+		public IEnumerable GetAllResults()
+		{
+			int count = -1;
+
+			for (var i = 0; i < mResults.Length; i++)
+			{
+				if (i > count)
+				{
+					// Reached the limit of availability so far, so see if more is available
+					do
+					{
+						bool moreAvailable, complete;
+
+						lock (mLock)
+						{
+							moreAvailable = mCount > count;
+							count = mCount;
+							complete = mComplete;
+						}
+
+						if (!moreAvailable)
+						{
+							if (complete)
+							{
+								// No more available, but the results are now complete anyway
+								yield break;
+							}
+
+							// No more available yet, not yet complete, wait until more becomes available
+							mResultsUpdated.WaitOne();
+						}
+						else
+						{
+							// More available now, so stop checking for more, continue with the loop to return them
+							break;
+						}
+					} while (true);
+
+					Debug.Assert(i <= count, "More should be available now");
+				}
+
+				yield return mResults[i];
+			}
+		}
+
+		public SearchResults CreateChildResults(string term)
+		{
+			Debug.Assert(term.StartsWith(mTerm));
+
+			int count;
+			bool complete;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			// If complete, then we know we don't need more than count. Otherwise, it can't be more than this capacity anyway
+			var childCapacity = complete ? count : mResults.Length;
+
+			return new SearchResults(childCapacity, term);
+		}
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.Designer.cs b/AutoTypeSearch/SearchWindow.Designer.cs
new file mode 100755
index 0000000..18b37d1
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.Designer.cs
@@ -0,0 +1,201 @@
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	partial class SearchWindow
+	{
+		/// 
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		#region Windows Form Designer generated code
+
+		/// 
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			this.components = new System.ComponentModel.Container();
+			this.mSearch = new System.Windows.Forms.TextBox();
+			this.mResults = new System.Windows.Forms.ListBox();
+			this.mLayout = new System.Windows.Forms.TableLayoutPanel();
+			this.mBanner = new System.Windows.Forms.PictureBox();
+			this.mInfoBanner = new System.Windows.Forms.Panel();
+			this.mInfoLabel = new System.Windows.Forms.Label();
+			this.mInfoBannerImage = new System.Windows.Forms.PictureBox();
+			this.mThrobber = new System.Windows.Forms.PictureBox();
+			this.mResultsUpdater = new System.Windows.Forms.Timer(this.components);
+			this.mNoResultsLabel = new System.Windows.Forms.Label();
+			this.mLayout.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).BeginInit();
+			this.mInfoBanner.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).BeginInit();
+			this.SuspendLayout();
+			// 
+			// mSearch
+			// 
+			this.mSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mSearch.Location = new System.Drawing.Point(1, 78);
+			this.mSearch.Margin = new System.Windows.Forms.Padding(1, 0, 1, 0);
+			this.mSearch.Name = "mSearch";
+			this.mSearch.Size = new System.Drawing.Size(521, 20);
+			this.mSearch.TabIndex = 0;
+			this.mSearch.LocationChanged += new System.EventHandler(this.mSearch_LocationChanged);
+			this.mSearch.TextChanged += new System.EventHandler(this.mSearch_TextChanged);
+			// 
+			// mResults
+			// 
+			this.mResults.BorderStyle = System.Windows.Forms.BorderStyle.None;
+			this.mResults.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mResults.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
+			this.mResults.FormattingEnabled = true;
+			this.mResults.IntegralHeight = false;
+			this.mResults.Location = new System.Drawing.Point(0, 98);
+			this.mResults.Margin = new System.Windows.Forms.Padding(0);
+			this.mResults.Name = "mResults";
+			this.mResults.Size = new System.Drawing.Size(523, 176);
+			this.mResults.TabIndex = 1;
+			this.mResults.TabStop = false;
+			this.mResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseClick);
+			this.mResults.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.mResults_DrawItem);
+			this.mResults.LocationChanged += new System.EventHandler(this.mResults_LocationChanged);
+			this.mResults.MouseEnter += new System.EventHandler(this.mResults_MouseEnter);
+			this.mResults.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseMove);
+			// 
+			// mLayout
+			// 
+			this.mLayout.ColumnCount = 1;
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+			this.mLayout.Controls.Add(this.mSearch, 0, 2);
+			this.mLayout.Controls.Add(this.mResults, 0, 3);
+			this.mLayout.Controls.Add(this.mBanner, 0, 0);
+			this.mLayout.Controls.Add(this.mInfoBanner, 0, 1);
+			this.mLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mLayout.Location = new System.Drawing.Point(0, 0);
+			this.mLayout.Name = "mLayout";
+			this.mLayout.RowCount = 4;
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.Size = new System.Drawing.Size(523, 274);
+			this.mLayout.TabIndex = 2;
+			// 
+			// mBanner
+			// 
+			this.mBanner.Dock = System.Windows.Forms.DockStyle.Top;
+			this.mBanner.Location = new System.Drawing.Point(0, 0);
+			this.mBanner.Margin = new System.Windows.Forms.Padding(0);
+			this.mBanner.Name = "mBanner";
+			this.mBanner.Size = new System.Drawing.Size(523, 60);
+			this.mBanner.TabIndex = 3;
+			this.mBanner.TabStop = false;
+			this.mBanner.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mBannerImage_MouseDown);
+			// 
+			// mInfoBanner
+			// 
+			this.mInfoBanner.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+			this.mInfoBanner.BackColor = System.Drawing.SystemColors.Info;
+			this.mInfoBanner.Controls.Add(this.mInfoLabel);
+			this.mInfoBanner.Controls.Add(this.mInfoBannerImage);
+			this.mInfoBanner.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoBanner.Location = new System.Drawing.Point(2, 61);
+			this.mInfoBanner.Margin = new System.Windows.Forms.Padding(2, 1, 1, 1);
+			this.mInfoBanner.Name = "mInfoBanner";
+			this.mInfoBanner.Size = new System.Drawing.Size(520, 16);
+			this.mInfoBanner.TabIndex = 8;
+			// 
+			// mInfoLabel
+			// 
+			this.mInfoLabel.AutoEllipsis = true;
+			this.mInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoLabel.ForeColor = System.Drawing.SystemColors.InfoText;
+			this.mInfoLabel.Location = new System.Drawing.Point(16, 0);
+			this.mInfoLabel.Name = "mInfoLabel";
+			this.mInfoLabel.Size = new System.Drawing.Size(504, 16);
+			this.mInfoLabel.TabIndex = 6;
+			this.mInfoLabel.Text = "AutoType failed to find";
+			// 
+			// mInfoBannerImage
+			// 
+			this.mInfoBannerImage.Dock = System.Windows.Forms.DockStyle.Left;
+			this.mInfoBannerImage.Image = global::AutoTypeSearch.Properties.Resources.Info;
+			this.mInfoBannerImage.Location = new System.Drawing.Point(0, 0);
+			this.mInfoBannerImage.Margin = new System.Windows.Forms.Padding(0);
+			this.mInfoBannerImage.Name = "mInfoBannerImage";
+			this.mInfoBannerImage.Size = new System.Drawing.Size(16, 16);
+			this.mInfoBannerImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mInfoBannerImage.TabIndex = 7;
+			this.mInfoBannerImage.TabStop = false;
+			// 
+			// mThrobber
+			// 
+			this.mThrobber.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.mThrobber.BackColor = System.Drawing.SystemColors.Window;
+			this.mThrobber.Location = new System.Drawing.Point(503, 81);
+			this.mThrobber.Name = "mThrobber";
+			this.mThrobber.Size = new System.Drawing.Size(16, 16);
+			this.mThrobber.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mThrobber.TabIndex = 4;
+			this.mThrobber.TabStop = false;
+			this.mThrobber.Visible = false;
+			// 
+			// mResultsUpdater
+			// 
+			this.mResultsUpdater.Interval = 250;
+			this.mResultsUpdater.Tick += new System.EventHandler(this.mResultsUpdater_Tick);
+			// 
+			// mNoResultsLabel
+			// 
+			this.mNoResultsLabel.AutoSize = true;
+			this.mNoResultsLabel.Location = new System.Drawing.Point(5, 103);
+			this.mNoResultsLabel.Name = "mNoResultsLabel";
+			this.mNoResultsLabel.Size = new System.Drawing.Size(84, 13);
+			this.mNoResultsLabel.TabIndex = 5;
+			this.mNoResultsLabel.Text = "No results found";
+			// 
+			// SearchWindow
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.BackColor = System.Drawing.SystemColors.Window;
+			this.ClientSize = new System.Drawing.Size(523, 274);
+			this.ControlBox = false;
+			this.Controls.Add(this.mNoResultsLabel);
+			this.Controls.Add(this.mThrobber);
+			this.Controls.Add(this.mLayout);
+			this.MinimumSize = new System.Drawing.Size(160, 96);
+			this.Name = "SearchWindow";
+			this.ShowInTaskbar = false;
+			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+			this.TopMost = true;
+			this.mLayout.ResumeLayout(false);
+			this.mLayout.PerformLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).EndInit();
+			this.mInfoBanner.ResumeLayout(false);
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).EndInit();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.TextBox mSearch;
+		private System.Windows.Forms.ListBox mResults;
+		private System.Windows.Forms.TableLayoutPanel mLayout;
+		private System.Windows.Forms.PictureBox mBanner;
+		private PictureBox mThrobber;
+		private Timer mResultsUpdater;
+		private Label mNoResultsLabel;
+		private Label mInfoLabel;
+		private Panel mInfoBanner;
+		private PictureBox mInfoBannerImage;
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchWindow.cs b/AutoTypeSearch/SearchWindow.cs
new file mode 100755
index 0000000..363b898
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.cs
@@ -0,0 +1,925 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Media;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Resources;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Collections;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	public partial class SearchWindow : Form
+	{
+		private const int SecondLineInset = 10;
+
+		// HACK to work around mono bug
+		private static readonly FieldInfo sMonoListBoxTopIndex = typeof(ListBox).GetField("top_index", BindingFlags.Instance | BindingFlags.NonPublic);
+
+		private readonly MainForm mMainForm;
+		private readonly Bitmap mBannerImage;
+		private readonly Searcher mSearcher;
+
+		private readonly Stream mThrobberImageStream;
+
+		private int? mWindowTopBorderHeight;
+		private int mBannerWidth = -1;
+		private int mMaximumExpandHeight;
+		private bool mManualSizeApplied;
+		private SearchResults mCurrentSearch;
+		private SearchResults mLastResultsUpdated;
+		private int mLastResultsUpdatedNextAvailableIndex;
+
+		#region Opening
+		public SearchWindow()
+		{
+			InitializeComponent();
+
+			// Mono can't load animated gifs from resx without crashing, so load it from an embedded resource instead
+			try
+			{
+				mThrobberImageStream = GetType().Assembly.GetManifestResourceStream("AutoTypeSearch.Throbber.gif");
+				if (mThrobberImageStream != null)
+				{
+					mThrobber.Image = Image.FromStream(mThrobberImageStream);
+				}
+			}
+			catch (Exception ex)
+			{
+				Debug.Fail("Failed to load Throbber.gif from embedded resource: " + ex.Message);
+			}
+
+			GlobalWindowManager.CustomizeControl(this);
+			UIUtil.SetExplorerTheme(mResults, true);
+			SetItemHeight();
+		}
+
+		public SearchWindow(MainForm mainForm, string infoBanner) : this()
+		{
+			mMainForm = mainForm;
+
+			mInfoBanner.Height = Math.Max(mInfoBannerImage.Height, mInfoLabel.Font.Height) + mInfoBanner.Margin.Vertical;
+			mInfoLabel.Padding = new Padding(0, (mInfoBanner.Height - mInfoLabel.Font.Height) / 2, 0, 0);
+			mInfoLabel.Text = infoBanner;
+
+			if (infoBanner == null)
+			{
+				mInfoBanner.Visible = false;
+				mInfoBanner.Height = 0;
+			}
+			
+			mSearcher = new Searcher(mMainForm.DocumentManager.GetOpenDatabases().ToArray());
+
+			Icon = mMainForm.Icon;
+			using (var bannerIcon = new Icon(Icon, 48, 48))
+			{
+				mBannerImage = bannerIcon.ToBitmap();
+			}
+			UpdateBanner();
+
+			ShowThrobber = false;
+
+			FontUtil.AssignDefaultItalic(mNoResultsLabel);
+		}
+
+
+		protected override void OnCreateControl()
+		{
+			base.OnCreateControl();
+
+			if (NativeMethods.IsWindows10())
+			{
+				mWindowTopBorderHeight = PointToScreen(Point.Empty).Y - this.Top;
+				NativeMethods.RefreshWindowFrame(Handle);
+			}
+
+			var windowRect = Settings.Default.WindowPosition;
+			var collapsedWindowRect = windowRect;
+			
+			collapsedWindowRect.Height = mSearch.Bottom + (Height - ClientSize.Height);
+
+			MinimumSize = new Size(MinimumSize.Width, collapsedWindowRect.Height);
+
+			if (windowRect.IsEmpty || !IsOnScreen(collapsedWindowRect))
+			{
+				windowRect = new Rectangle(0, 0, Width, Height);
+				Height = collapsedWindowRect.Height;
+
+				CenterToScreen();
+			}
+			else
+			{
+				Location = windowRect.Location;
+				Size = collapsedWindowRect.Size;
+			}
+
+			mMaximumExpandHeight = Math.Max(windowRect.Height, MinimumSize.Height + mResults.ItemHeight);
+		}
+		
+
+		private static bool IsOnScreen(Rectangle rectangle)
+		{
+			return Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(rectangle));
+		}
+
+		private void SetItemHeight()
+		{
+			mResults.ItemHeight = mResults.Font.Height * 2 + 2;
+		}
+
+		protected override void WndProc(ref Message m)
+		{
+			if (mWindowTopBorderHeight.HasValue)
+			{
+				NativeMethods.RemoveWindowFrameTopBorder(ref m, mWindowTopBorderHeight.Value);
+			}
+			base.WndProc(ref m);
+		}
+
+		#endregion
+
+		#region Closing
+		protected override void OnActivated(EventArgs e)
+		{
+			base.OnActivated(e);
+			Deactivate += OnDeactivate;
+		}
+
+		private void OnDeactivate(object sender, EventArgs eventArgs)
+		{
+			Close();
+		}
+
+		protected override void OnClosed(EventArgs e)
+		{
+			Deactivate -= OnDeactivate;
+			base.OnClosed(e);
+		}
+
+		/// 
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				if (mBannerImage != null)
+				{
+					mBannerImage.Dispose();
+				}
+				if (mThrobber.Image != null)
+				{
+					mThrobber.Image.Dispose();
+					mThrobber.Image = null;
+					mThrobberImageStream.Dispose();
+				}
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+		#endregion
+
+		#region Item Drawing
+		private void mResults_DrawItem(object sender, DrawItemEventArgs e)
+		{
+			var searchResult = mResults.Items[e.Index] as SearchResult;
+			if (searchResult == null)
+			{
+				Debug.Fail("Unexpected item in mResults");
+// ReSharper disable once HeuristicUnreachableCode - Not unreachable
+				return;
+			}
+			var drawingArea = e.Bounds;
+			drawingArea.Height--; // Leave room for a dividing line at the bottom
+			
+			if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
+			{
+				DrawBorderedRectangle(e.Graphics, drawingArea, SystemColors.Highlight);
+			}
+			else
+			{
+				e.Graphics.FillRectangle(SystemBrushes.Window, drawingArea);
+			}
+
+			var image = GetImage(searchResult.Database, searchResult.Entry.CustomIconUuid, searchResult.Entry.IconId);
+			var imageMargin = (drawingArea.Height - image.Height) / 2;
+			e.Graphics.DrawImage(image, drawingArea.Left + imageMargin, drawingArea.Top + imageMargin, image.Width, image.Height);
+
+			var textLeftMargin = drawingArea.Left + imageMargin * 2 + image.Width;
+			var textBounds = new Rectangle(textLeftMargin, drawingArea.Top + 1, drawingArea.Width - textLeftMargin - 1, drawingArea.Height - 2);
+
+			var line1Bounds = textBounds;
+			line1Bounds.Height = e.Font.Height;
+			var line2Bounds = line1Bounds;
+			line2Bounds.Y += line2Bounds.Height - 1;
+			line2Bounds.X += SecondLineInset;
+			line2Bounds.Width -= SecondLineInset;
+
+			var resultInTitleField = searchResult.FieldName == PwDefs.TitleField;
+
+			var title = (resultInTitleField ? searchResult.FieldValue : searchResult.Title).Replace('\n', ' '); // The FieldValue may have references resolved, whereas the title is always read directly.
+
+			var uniqueTitlePartWidth = 0;
+			if (!String.IsNullOrEmpty(searchResult.UniqueTitlePart))
+			{
+				var uniqueTitlePart = searchResult.UniqueTitlePart.Replace('\n', ' ');
+
+				var titleWidth = TextRenderer.MeasureText(e.Graphics, title, e.Font, line1Bounds.Size, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+
+				var availableWidthForUniqueTitlePart = line1Bounds.Width - titleWidth;
+				if (availableWidthForUniqueTitlePart > 20) // Don't bother including a unique part if there's no room for it
+				{
+					var uniqueTitlePartReversed = ReverseString(uniqueTitlePart);
+
+					uniqueTitlePartWidth = TextRenderer.MeasureText(e.Graphics, uniqueTitlePartReversed, e.Font, new Size(availableWidthForUniqueTitlePart, line1Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+					uniqueTitlePart = ReverseString(uniqueTitlePartReversed);
+
+					TextRenderer.DrawText(e.Graphics, uniqueTitlePart, e.Font, new Rectangle(line1Bounds.X, line1Bounds.Y, uniqueTitlePartWidth, line1Bounds.Height), SystemColors.GrayText, TextFormatFlags.NoPadding);
+				}
+			}
+
+			var titleBounds = new Rectangle(line1Bounds.X + uniqueTitlePartWidth, line1Bounds.Y, line1Bounds.Width - uniqueTitlePartWidth, line1Bounds.Height);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Highlight title in first line.
+				DrawHighlight(e, titleBounds, title, searchResult.Start, searchResult.Length);
+			}
+
+			TextRenderer.DrawText(e.Graphics, searchResult.Title, e.Font, titleBounds, SystemColors.WindowText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Use Username for second line.
+				TextRenderer.DrawText(e.Graphics, KPRes.UserName + ": " + searchResult.Entry.Strings.ReadSafeEx(PwDefs.UserNameField), e.Font, line2Bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+			}
+			else
+			{
+				// Found the result in not title field. Show the matching result on second line
+				
+				var fieldValue = searchResult.FieldValue.Replace('\n',' ');
+				var fieldNamePrefix = GetDisplayFieldName(searchResult.FieldName) + ": ";
+
+				var remainingSpace = line2Bounds.Width;
+				var fieldNamePrefixWidth = TextRenderer.MeasureText(e.Graphics, fieldNamePrefix, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+				remainingSpace -= fieldNamePrefixWidth;
+
+				int fieldValueHighlightWidth = 0, fieldValueLeftContextWidth = 0, fieldValueRightContextWidth = 0;
+
+				var leftContext = fieldValue.Substring(0, searchResult.Start);
+				var highlight = fieldValue.Substring(searchResult.Start, searchResult.Length);
+				var rightContext = fieldValue.Substring(searchResult.Start + searchResult.Length);
+
+				if (searchResult.Length == 0)
+				{
+					fieldValueHighlightWidth = remainingSpace;
+				}
+				else
+				{
+					if (remainingSpace > 0)
+					{
+						var availableSpace = remainingSpace;
+						fieldValueHighlightWidth = TextRenderer.MeasureText(e.Graphics, highlight, e.Font, new Size(availableSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						remainingSpace -= fieldValueHighlightWidth;
+					}
+
+					// Of the space remaining, divide it equally between that which comes before, and that which comes after
+					if (!String.IsNullOrEmpty(leftContext))
+					{
+						var leftContextReversed = ReverseString(leftContext);
+						fieldValueLeftContextWidth = TextRenderer.MeasureText(e.Graphics, leftContextReversed, e.Font, new Size(remainingSpace / 2, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+						if (fieldValueLeftContextWidth > remainingSpace)
+						{
+							// Always allow space for the minimal left context
+							fieldValueHighlightWidth -= (fieldValueLeftContextWidth - remainingSpace);
+							remainingSpace = 0;
+						}
+						else
+						{
+							remainingSpace -= fieldValueLeftContextWidth;							
+						}
+						
+						// Replace left context with the truncated reversed left context.
+						leftContext = ReverseString(leftContextReversed);
+					}
+
+					if (remainingSpace > 0 && !String.IsNullOrEmpty(rightContext))
+					{
+						fieldValueRightContextWidth = TextRenderer.MeasureText(e.Graphics, rightContext, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						if (fieldValueRightContextWidth > remainingSpace)
+						{
+							fieldValueRightContextWidth = 0;
+						}
+					}
+				}
+
+				// Now draw it all
+				var bounds = line2Bounds;
+				bounds.Width = fieldNamePrefixWidth;
+				TextRenderer.DrawText(e.Graphics, fieldNamePrefix, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				if (fieldValueLeftContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueLeftContextWidth;
+					TextRenderer.DrawText(e.Graphics, leftContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding); // No ellipsis as the leftContext string has already been truncated appropriately
+				}
+				if (fieldValueHighlightWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueHighlightWidth;
+
+					if (searchResult.Length > 0)
+					{
+						DrawHighlightRectangle(e, bounds);
+					}
+					TextRenderer.DrawText(e.Graphics, highlight, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+				if (fieldValueRightContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueRightContextWidth;
+					TextRenderer.DrawText(e.Graphics, rightContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+			}
+
+			e.Graphics.DrawLine(SystemPens.ButtonFace, drawingArea.Left, drawingArea.Bottom, drawingArea.Right, drawingArea.Bottom);
+		}
+
+		private static string ReverseString(string value)
+		{
+			return new String(value.ToCharArray().TakeWhile(c => c != '\0').Reverse().ToArray());
+		}
+
+		private static void DrawHighlight(DrawItemEventArgs e, Rectangle lineBounds, string text, int highlightFrom, int highlightLength)
+		{
+			var highlightX = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width;
+			var highlightWidth = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom + highlightLength), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width - highlightX;
+
+			DrawHighlightRectangle(e, new Rectangle(lineBounds.Left + highlightX, lineBounds.Top, highlightWidth, lineBounds.Height));
+		}
+
+		private static void DrawHighlightRectangle(DrawItemEventArgs e, Rectangle rectangle)
+		{
+			DrawBorderedRectangle(e.Graphics, rectangle, Color.PaleTurquoise);
+		}
+
+		private static void DrawBorderedRectangle(Graphics graphics, Rectangle rectangle, Color colour)
+		{
+			var border = rectangle;
+			border.Width--;
+			border.Height--;
+
+			using (var brush = new SolidBrush(MergeColors(colour, SystemColors.Window, 0.2)))
+			{
+				graphics.FillRectangle(brush, rectangle);
+			}
+			using (var pen = new Pen(colour, 1f))
+			{
+				graphics.DrawRectangle(pen, border);
+			}
+		}
+
+		private Image GetImage(PwDatabase database, PwUuid customIconId, PwIcon iconId)
+		{
+			Image image = null;
+			if (!customIconId.Equals(PwUuid.Zero))
+			{
+				image = database.GetCustomIcon(customIconId, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16));
+			}
+			if (image == null)
+			{
+				try { image = mMainForm.ClientIcons.Images[(int)iconId]; }
+				catch (Exception) { Debug.Assert(false); }
+			}
+
+			return image;
+		}
+
+		private static string GetDisplayFieldName(string fieldName)
+		{
+			switch (fieldName)
+			{
+				case PwDefs.TitleField:
+					return KPRes.Title;
+				case PwDefs.UserNameField:
+					return KPRes.UserName;
+				case PwDefs.PasswordField:
+					return KPRes.Password;
+				case PwDefs.UrlField:
+					return KPRes.Url;
+				case PwDefs.NotesField:
+					return KPRes.Notes;
+				case AutoTypeSearchExt.TagsVirtualFieldName:
+					return KPRes.Tags;
+				default:
+					return fieldName;
+			}
+		}
+
+		public static Color MergeColors(Color from, Color to, double amount)
+		{
+			var r = (byte)((from.R * amount) + to.R * (1 - amount));
+			var g = (byte)((from.G * amount) + to.G * (1 - amount));
+			var b = (byte)((from.B * amount) + to.B * (1 - amount));
+			return Color.FromArgb(r, g, b);
+		}
+		#endregion
+
+		#region Mouse tracking
+		private Point mMouseEntryPosition;
+		
+		private void mResults_MouseEnter(object sender, EventArgs e)
+		{
+			mMouseEntryPosition = MousePosition;
+		}
+
+		private void mResults_MouseMove(object sender, MouseEventArgs e)
+		{
+			// Discard the location the mouse has on entering the control (as it may be that the control has just moved under the mouse, not the other way around)
+			if (MousePosition == mMouseEntryPosition)
+			{
+				return;
+			}
+
+			// Hot tracking
+			var hoverIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (hoverIndex >= 0 && mResults.SelectedIndex != hoverIndex)
+			{
+				if (mResults.GetItemRectangle(hoverIndex).Bottom <= mResults.ClientRectangle.Bottom)
+				{
+					mResults.SelectedIndex = hoverIndex;
+				}
+				else
+				{
+					// Avoid the control scrolling
+					mResults.BeginUpdate();
+					var topIndex = mResults.TopIndex;
+					mResults.SelectedIndex = hoverIndex;
+					mResults.TopIndex = topIndex;
+					mResults.EndUpdate();
+				}
+			}
+		}
+		#endregion
+
+		#region Resizing
+		protected override void OnResizeBegin(EventArgs e)
+		{
+			// Stop automatically sizing - the user is picking a size they want.
+			mManualSizeApplied = true;
+			base.OnResizeBegin(e);
+		}
+
+		protected override void OnResize(EventArgs e)
+		{
+			base.OnResize(e);
+
+			UpdateBanner();
+
+			mResults.Invalidate();
+		}
+
+		protected override void OnResizeEnd(EventArgs e)
+		{
+			base.OnResizeEnd(e);
+
+			if (Height > MinimumSize.Height && Height != mMaximumExpandHeight)
+			{
+				mMaximumExpandHeight = Math.Max(Height, MinimumSize.Height + mResults.ItemHeight);
+			}
+			else
+			{
+				mManualSizeApplied = false;
+			}
+
+			Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+		}
+
+		private void UpdateBanner()
+		{
+			if (mBannerImage != null)
+			{
+				BannerFactory.UpdateBanner(this, mBanner, mBannerImage, PwDefs.ProductName, Resources.BannerText, ref mBannerWidth);
+			}
+		}
+
+		private void mSearch_LocationChanged(object sender, EventArgs e)
+		{
+			mThrobber.Location = new Point(mSearch.Right - mThrobber.Width - mThrobber.Margin.Right, mSearch.Top + (mSearch.Height - mThrobber.Height) / 2);
+		}
+
+		private void mResults_LocationChanged(object sender, EventArgs e)
+		{
+			mNoResultsLabel.Top = mResults.Top + (mResults.ItemHeight - mNoResultsLabel.Height) / 2;
+		}
+		#endregion
+
+		#region Searching
+		private static readonly SearchResultPrecedence SearchResultPrecedenceComparer = new SearchResultPrecedence();
+		private void mSearch_TextChanged(object sender, EventArgs e)
+		{
+			if (mSearch.Text.Length < 2)
+			{
+				// Stop searching
+				mResultsUpdater.Enabled = false;
+				ShowThrobber = false;
+				Height = MinimumSize.Height;
+				mManualSizeApplied = false;
+				mResults.Items.Clear();
+				mLastResultsUpdated = null;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			else
+			{
+				// Start searching
+				mNoResultsLabel.Visible = false;
+				mCurrentSearch = mSearcher.Search(mSearch.Text);
+				mResultsUpdater.Enabled = true;
+				ShowThrobber = true;
+				mResultsUpdater_Tick(null, EventArgs.Empty); // Quick poke just in case the results are already done.
+			}
+		}
+
+		[SuppressMessage("ReSharper", "CoVariantArrayConversion", Justification = "Object arrays for Listbox.Items, known to be of correct type")]
+		private void mResultsUpdater_Tick(object sender, EventArgs e)
+		{
+			if (mLastResultsUpdated != mCurrentSearch)
+			{
+				// Clear out old results and replace with new ones
+				mResults.Items.Clear();
+				mLastResultsUpdated = mCurrentSearch;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			var existingResultsCount = mResults.Items.Count;
+			
+			bool complete;
+			var newResults = mLastResultsUpdated.GetAvailableResults(ref mLastResultsUpdatedNextAvailableIndex, out complete);
+			if (newResults.Length > 0)
+			{
+				mResults.BeginUpdate();
+				
+				SearchResult[] allResults;
+				if (existingResultsCount > 0)
+				{
+					allResults = new SearchResult[existingResultsCount + newResults.Length];
+					mResults.Items.CopyTo(allResults, 0);
+					newResults.CopyTo(allResults, existingResultsCount);
+
+					mResults.Items.Clear();
+				}
+				else
+				{
+					allResults = newResults;
+				}
+
+				CalculateUniqueTitles(allResults);
+
+				Array.Sort(allResults, SearchResultPrecedenceComparer);
+				mResults.Items.AddRange(allResults);
+				
+				mResults.EndUpdate();
+
+				if (allResults.Length > 0)
+				{
+					if (mResults.SelectedIndex == -1)
+					{
+						try
+						{
+							// HACK to work around mono bug
+							if (sMonoListBoxTopIndex != null)
+							{
+								sMonoListBoxTopIndex.SetValue(mResults, 1); // Set the top_index to 1 so that when selected index is set to 0, and calls EnsureVisible(0), it follows the index < top_index pass and not the broken index >= top_index + rows path. 
+							}
+
+							mResults.SelectedIndex = 0;
+							mResults.TopIndex = 0;
+						}
+						catch (Exception ex)
+						{
+							Debug.Fail("Failed to set selection on count of " + allResults.Length + ": " + ex.Message);
+						}
+					}
+
+					if (!mManualSizeApplied)
+					{
+						Height = Math.Min(mMaximumExpandHeight, MinimumSize.Height + (allResults.Length * mResults.ItemHeight));
+					}
+				}
+			}
+
+			if (complete)
+			{
+				ShowThrobber = false;
+				mResultsUpdater.Enabled = false;
+
+				if (mResults.Items.Count == 0)
+				{
+					mNoResultsLabel.Visible = true;
+					Height = MinimumSize.Height + mResults.ItemHeight;
+					mManualSizeApplied = false;
+				}
+			}
+		}
+
+		private void CalculateUniqueTitles(IEnumerable results, int depth = 0)
+		{
+			// Where results have identical titles, include group titles to make them unique
+			depth += 1;
+
+			// First create a lookup by title
+			var titles = new Dictionary>();
+			foreach (var searchResult in results)
+			{
+				List resultsWithSameTitle;
+				if (titles.TryGetValue(searchResult.UniqueTitle, out resultsWithSameTitle))
+				{
+					resultsWithSameTitle.Add(searchResult);
+				}
+				else
+				{
+					titles.Add(searchResult.UniqueTitle, new List { searchResult });
+				}
+			}
+
+			// Attempt to unique-ify any non-unique titles
+			foreach (var resultsSharingTitle in titles.Values)
+			{
+				if (resultsSharingTitle.Count > 1)
+				{
+					var titlesModified = false;
+					foreach (var searchResult in resultsSharingTitle)
+					{
+						titlesModified |= searchResult.SetUniqueTitleDepth(depth);
+					}
+
+					if (titlesModified)
+					{
+						// Recurse in case of continuing non-uniqueness
+						CalculateUniqueTitles(resultsSharingTitle, depth);
+					}
+				}
+			}
+		}
+
+		private class SearchResultPrecedence : IComparer
+		{
+			public int Compare(SearchResult x, SearchResult y)
+			{
+				// First precedence is that if the result is the start of the field value, it's higher precedence than if it doesn't.
+				var result = -(x.Start == 0).CompareTo(y.Start == 0);
+
+				// Second precedence is that the start of the title field is higher precedence than the start of any other field
+				if (result == 0)
+				{
+					result = -(x.FieldName == PwDefs.TitleField).CompareTo(y.FieldName == PwDefs.TitleField);
+				}
+
+				// Both start the title field, so both equal. Have to have consistent ordering, so return final precedence based search index
+				if (result == 0)
+				{
+					result = x.ResultIndex.CompareTo(y.ResultIndex);
+				}
+				
+				return result;
+			}
+		}
+
+		private bool ShowThrobber
+		{
+			get { return mThrobber.Visible; }
+			set
+			{
+				if (value != ShowThrobber)
+				{
+					if (value)
+					{
+						mThrobber.Visible = true;
+
+						// Set the margin on the textbox to allow room for the throbber
+						NativeMethods.SetTextBoxRightMargin(mSearch, mThrobber.Width + mThrobber.Margin.Right);
+					}
+					else
+					{
+						mThrobber.Visible = false;
+
+						NativeMethods.SetTextBoxRightMargin(mSearch, 0);
+					}
+				}
+			}
+		}
+		#endregion
+
+		private void mBannerImage_MouseDown(object sender, MouseEventArgs e)
+		{
+			// Allow drag by banner image
+			if (e.Button == MouseButtons.Left)
+			{
+				if (e.Clicks == 2)
+				{
+					// Re-center the form on double-click
+					CenterToScreen();
+
+					Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+				}
+				else if (!NativeLib.IsUnix())
+				{
+					NativeMethods.StartFormDrag(this);
+				}
+			}
+		}
+
+		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+		{
+			switch (keyData)
+			{
+				case Keys.Escape:
+					Close();
+					return true;
+				case Keys.Up:
+					TryChangeSelection(-1);
+					return true;
+				case Keys.Down:
+					TryChangeSelection(1);
+					return true;
+				case Keys.PageUp:
+					TryChangeSelection(-mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.PageDown:
+					TryChangeSelection(mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.Home | Keys.Control:
+					mResults.SelectedIndex = 0;
+					return true;
+				case Keys.End | Keys.Control:
+					mResults.SelectedIndex = mResults.Items.Count - 1;
+					return true;
+				case Keys.Enter:
+					PerformAction(Settings.Default.DefaultAction, mResults.SelectedItem as SearchResult);
+					break;
+				case Keys.Enter | Keys.Shift:
+					PerformAction(Settings.Default.AlternativeAction, mResults.SelectedItem as SearchResult);
+					break;
+			}
+			
+			return base.ProcessCmdKey(ref msg, keyData);
+		}
+
+		#region Selection Changing
+
+		protected override void OnMouseWheel(MouseEventArgs e)
+		{
+			mResults.TopIndex -= (e.Delta / Math.Abs(e.Delta));
+		}
+
+		private void TryChangeSelection(int delta)
+		{
+			if (mResults.Items.Count > 0)
+			{
+				mResults.SelectedIndex = Math.Max(Math.Min(mResults.Items.Count - 1, mResults.SelectedIndex + delta), 0);
+			}
+		}
+		#endregion
+
+		#region Actions
+
+		private void mResults_MouseClick(object sender, MouseEventArgs e)
+		{
+			var clickIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (clickIndex >= 0)
+			{
+				var clickedResult = mResults.Items[clickIndex] as SearchResult;
+				if (clickedResult != null)
+				{
+					PerformAction((ModifierKeys & Keys.Shift) == Keys.Shift ? Settings.Default.AlternativeAction : Settings.Default.DefaultAction, clickedResult);
+				}
+			}
+		}
+
+		private void PerformAction(Actions action, SearchResult searchResult)
+		{
+			Close();
+
+			if (searchResult != null)
+			{
+				switch (action)
+				{
+					case Actions.PerformAutoType:
+						AutoTypeEntry(searchResult);
+						break;
+					case Actions.EditEntry:
+						EditEntry(searchResult);
+						break;
+					case Actions.ShowEntry:
+						ShowEntry(searchResult);
+						break;
+					case Actions.OpenEntryUrl:
+						OpenEntryUrl(searchResult);
+						break;
+					case Actions.CopyPassword:
+						CopyPassword(searchResult);
+						break;
+					default:
+						throw new ArgumentOutOfRangeException("action");
+				}
+			}
+		}
+
+		private void AutoTypeEntry(SearchResult searchResult)
+		{
+			bool result;
+			if (ActiveForm != null)
+			{
+				result = AutoType.PerformIntoPreviousWindow(mMainForm, searchResult.Entry, searchResult.Database);
+			}
+			else
+			{
+				result = AutoType.PerformIntoCurrentWindow(searchResult.Entry, searchResult.Database);
+			}
+			if (!result)
+			{
+				SystemSounds.Beep.Play();
+
+				if (Settings.Default.AlternativeAction != Actions.PerformAutoType)
+				{
+					PerformAction(Settings.Default.AlternativeAction, searchResult);
+				}
+			}
+		}
+
+		private void EditEntry(SearchResult searchResult)
+		{
+			using (var entryForm = new PwEntryForm())
+			{
+				mMainForm.MakeDocumentActive(mMainForm.DocumentManager.FindDocument(searchResult.Database));
+				
+				entryForm.InitEx(searchResult.Entry, PwEditMode.EditExistingEntry, searchResult.Database, mMainForm.ClientIcons, false, false);
+
+				ShowForegroundDialog(entryForm);
+
+				mMainForm.UpdateUI(false, null, searchResult.Database.UINeedsIconUpdate, null, true, null, entryForm.HasModifiedEntry);
+			}
+		}
+
+// ReSharper disable once UnusedMethodReturnValue.Local - Generic helper, result may be used in future
+		private DialogResult ShowForegroundDialog(Form form)
+		{
+			mMainForm.EnsureVisibleForegroundWindow(false, false);
+			form.StartPosition = FormStartPosition.CenterScreen;
+			if (mMainForm.IsTrayed())
+			{
+				form.ShowInTaskbar = true;
+			}
+
+			form.Shown += ActivateFormOnShown;
+			return form.ShowDialog(mMainForm);
+		}
+
+		private static void ActivateFormOnShown(object sender, EventArgs eventArgs)
+		{
+			var form = (Form)sender;
+			form.Shown -= ActivateFormOnShown;
+			form.Activate();
+		}
+
+		private void ShowEntry(SearchResult searchResult)
+		{
+			// Show this entry
+			mMainForm.UpdateUI(false, mMainForm.DocumentManager.FindDocument(searchResult.Database), true, searchResult.Entry.ParentGroup, true, null, false, null);
+			mMainForm.SelectEntries(new PwObjectList { searchResult.Entry }, true, true);
+			mMainForm.EnsureVisibleEntry(searchResult.Entry.Uuid);
+			mMainForm.UpdateUI(false, null, false, null, false, null, false);
+			mMainForm.EnsureVisibleForegroundWindow(true, true);
+		}
+
+		private void OpenEntryUrl(SearchResult searchResult)
+		{
+			WinUtil.OpenEntryUrl(searchResult.Entry);
+		}
+
+		private void CopyPassword(SearchResult searchResult)
+		{
+			if (ClipboardUtil.Copy(searchResult.Entry.Strings.ReadSafe(PwDefs.PasswordField), true, true, searchResult.Entry,
+									mMainForm.DocumentManager.SafeFindContainerOf(searchResult.Entry),
+									IntPtr.Zero))
+			{
+				mMainForm.StartClipboardCountdown();
+			}
+		}
+		
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.resx b/AutoTypeSearch/SearchWindow.resx
new file mode 100755
index 0000000..8ef82f0
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.resx
@@ -0,0 +1,123 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    17, 17
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Searcher.cs b/AutoTypeSearch/Searcher.cs
new file mode 100755
index 0000000..433ae94
--- /dev/null
+++ b/AutoTypeSearch/Searcher.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class Searcher
+	{
+		private readonly PwDatabase[] mDatabases;
+		private readonly Dictionary mSearches = new Dictionary();
+
+		public Searcher(PwDatabase[] databases)
+		{
+			mDatabases = databases;
+		}
+
+		public SearchResults Search(string term)
+		{
+			if (term.Length < 2)
+			{
+				throw new ArgumentException("Search term must be at least 2 characters");
+			}
+
+			SearchResults parentResults = null;
+
+			var termParent = term;
+			while (termParent.Length >= 2)
+			{
+				if (mSearches.TryGetValue(termParent, out parentResults))
+				{
+					if (termParent == term)
+					{
+						// This is an exact duplicate search, so return it.
+						return parentResults;
+					}
+
+					// Found an existing search for a parent of the term, start from there.
+					break;
+				}
+		
+				// No existing search for termParent found, try less.
+				termParent = termParent.Remove(termParent.Length - 1, 1);
+			}
+
+			SearchResults searchResults;
+			if (parentResults == null)
+			{
+				// No parent found at all, start from scratch
+				searchResults = new SearchResults(GetCountOfAllDatabaseEntries(), term);
+
+				var rootSearchThread = new Thread(RootSearchWorker) { Name = term };
+				rootSearchThread.Start(searchResults);
+			}
+			else
+			{
+				searchResults = parentResults.CreateChildResults(term);
+
+				var childSearchThread = new Thread(ChildSearchWorker) { Name = term };
+				childSearchThread.Start(new ChildSearchWorkerState{ Source = parentResults, Results = searchResults });
+			}
+
+			mSearches.Add(term, searchResults);
+
+			return searchResults;
+		}
+
+		private int GetCountOfAllDatabaseEntries()
+		{
+			return (from database in mDatabases select (int)database.RootGroup.GetEntriesCount(true)).Sum();
+		}
+
+		private void RootSearchWorker(object stateObject)
+		{
+			var results = (SearchResults)stateObject;
+			var excludeExpired = Settings.Default.ExcludeExpired;
+			var searchStartTime = DateTime.Now;
+
+			foreach (var database in mDatabases)
+			{
+				SearchGroup(database, database.RootGroup, results, excludeExpired, searchStartTime);	
+			}
+
+			results.SetComplete();
+		}
+
+		/// 
+		/// Recursively search  and its children, adding results to 
+		/// 
+		private void SearchGroup(PwDatabase context, PwGroup group, SearchResults results, bool excludeExpired, DateTime searchStartTime)
+		{
+			if (group.EnableSearching ?? true) // Group will only be searched if it's parent enabled searching, so if it is inherit (null) or true, search it.
+			{
+				foreach (var childGroup in group.Groups)
+				{
+					SearchGroup(context, childGroup, results, excludeExpired, searchStartTime);
+				}
+
+				foreach (var entry in group.Entries)
+				{
+					if (!(excludeExpired && entry.Expires && searchStartTime > entry.ExpiryTime))
+					{
+						results.AddResultIfMatchesTerm(context, entry);
+					}
+				}
+			}
+		}
+
+		private struct ChildSearchWorkerState
+		{
+			public SearchResults Source;
+			public SearchResults Results;
+		}
+		private void ChildSearchWorker(object stateObject)
+		{
+			var state = (ChildSearchWorkerState)stateObject;
+
+			bool complete;
+			var index = 0;
+			do
+			{
+				foreach (var entry in state.Source.GetAvailableResults(ref index, out complete))
+				{
+					state.Results.AddResultIfMatchesTerm(entry);
+				}
+			} while (!complete);
+
+			state.Results.SetComplete();
+		}
+	}
+}
diff --git a/AutoTypeSearch/Throbber.gif b/AutoTypeSearch/Throbber.gif
new file mode 100755
index 0000000..494d426
--- /dev/null
+++ b/AutoTypeSearch/Throbber.gif
Binary files differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/AutoTypeSearch/SearchResults.cs b/AutoTypeSearch/SearchResults.cs
new file mode 100755
index 0000000..b2b0529
--- /dev/null
+++ b/AutoTypeSearch/SearchResults.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePass.Util.Spr;
+using KeePassLib;
+using KeePassLib.Utility;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResults
+	{
+		private readonly string mTerm;
+		private readonly SearchResult[] mResults;
+
+		private readonly object mLock = new object();
+		private volatile int mCount;
+		private volatile bool mComplete;
+
+		private readonly AutoResetEvent mResultsUpdated = new AutoResetEvent(false);
+
+		private readonly CompareOptions mStringComparison;
+		private readonly bool mSearchTitle;
+		private readonly bool mSearchUserName;
+		private readonly bool mSearchUrl;
+		private readonly bool mSearchNotes;
+		private readonly bool mSearchCustomFields;
+		private readonly bool mResolveReferences;
+		private readonly bool mSearchTags;
+
+		public SearchResults(int capacity, string term)
+		{
+			mTerm = term;
+			mResults = new SearchResult[capacity];
+
+			mStringComparison = Settings.Default.CaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase;
+			mStringComparison |= CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace;
+			mSearchTitle = Settings.Default.SearchTitle;
+			mSearchUserName = Settings.Default.SearchUserName;
+			mSearchUrl = Settings.Default.SearchUrl;
+			mSearchNotes = Settings.Default.SearchNotes;
+			mSearchCustomFields = Settings.Default.SearchCustomFields;
+			mSearchTags = Settings.Default.SearchTags;
+			mResolveReferences = Settings.Default.ResolveReferences;
+		}
+
+		/// 
+		/// Gets an ordered list of fields to search for the term
+		/// 
+		/// 
+		/// 
+		private IEnumerable GetFieldsToSearch(PwEntry entry)
+		{
+			var fieldsToSearch = new List((int)entry.Strings.UCount);
+			if (mSearchTitle) fieldsToSearch.Add(PwDefs.TitleField);
+			if (mSearchUserName) fieldsToSearch.Add(PwDefs.UserNameField);
+			if (mSearchUrl) fieldsToSearch.Add(PwDefs.UrlField);
+			if (mSearchNotes) fieldsToSearch.Add(PwDefs.NotesField);
+			if (mSearchCustomFields)
+			{
+				foreach (var stringEntry in entry.Strings)
+				{
+					if (!stringEntry.Value.IsProtected && !PwDefs.IsStandardField(stringEntry.Key))
+					{
+						fieldsToSearch.Add(stringEntry.Key);
+					}
+				}
+			}
+			if (mSearchTags) fieldsToSearch.Add(AutoTypeSearchExt.TagsVirtualFieldName);
+
+			return fieldsToSearch;
+		}
+
+		public void AddResultIfMatchesTerm(PwDatabase context, PwEntry entry)
+		{
+			// First try without resolving
+			var addedResult = AddResultIfMatchesTerm(context, entry, false);
+
+			if (!addedResult && mResolveReferences)
+			{
+				// Not found without resolving, so try resolving
+				AddResultIfMatchesTerm(context, entry, true);
+			}
+		}
+
+		private bool AddResultIfMatchesTerm(PwDatabase context, PwEntry entry, bool resolveReferences)
+		{
+			foreach (var fieldName in GetFieldsToSearch(entry))
+			{
+				string fieldValue;
+				if (fieldName == AutoTypeSearchExt.TagsVirtualFieldName)
+				{
+					fieldValue = StrUtil.TagsToString(entry.Tags, true);
+				}
+				else
+				{
+					fieldValue = entry.Strings.ReadSafeEx(fieldName);
+
+					if (resolveReferences)
+					{
+						fieldValue = ResolveReferences(context, entry, fieldValue);
+					}
+				}
+
+				if (!String.IsNullOrEmpty(fieldValue))
+				{
+					var foundIndex = CultureInfo.CurrentCulture.CompareInfo.IndexOf(fieldValue, mTerm, mStringComparison);
+					if (foundIndex >= 0)
+					{
+						// Found a match, create a search result and add it
+						AddResult(new SearchResult(context, entry, entry.Strings.ReadSafe(PwDefs.TitleField), fieldName, fieldValue, foundIndex, mTerm.Length));
+						return true;
+					}
+				}
+			}
+			return false;
+		}
+
+		/// 
+		/// Resolves any references in the field value and returns it. If there were no references,
+		/// returns null (to avoid duplicate searching - it is assumed that the unresolved value has already been searched)
+		/// 
+		private string ResolveReferences(PwDatabase context, PwEntry entry, string fieldValue)
+		{
+			if (fieldValue.IndexOf('{') < 0)
+			{
+				// Can't contain any references
+				return null;
+			}
+			
+			var sprContext = new SprContext(entry, context, SprCompileFlags.Deref) { ForcePlainTextPasswords = false };
+
+			var result = SprEngine.Compile(fieldValue, sprContext);
+			if (CultureInfo.CurrentCulture.CompareInfo.Compare(result,fieldValue, mStringComparison) == 0)
+			{
+				return null;
+			}
+			
+			return result;
+		}
+
+		public void AddResultIfMatchesTerm(SearchResult candidate)
+		{
+			// First see whether the existing candidate is a further match in the same place
+			var fieldValue = candidate.FieldValue;
+			if (fieldValue.Length > candidate.Start + mTerm.Length && CultureInfo.CurrentCulture.CompareInfo.Compare(fieldValue.Substring(candidate.Start, mTerm.Length), mTerm, mStringComparison) == 0)
+			{
+				// Yep, match continues, so add it.
+				AddResult(new SearchResult(candidate.Database, candidate.Entry, candidate.Title, candidate.FieldName, fieldValue, candidate.Start, mTerm.Length));
+			}
+			else
+			{
+				// Existing candidate match couldn't be extended, so search from scratch again
+				AddResultIfMatchesTerm(candidate.Database, candidate.Entry);
+			}
+		}
+
+		private void AddResult(SearchResult result)
+		{
+			lock (mLock)
+			{
+				if (mComplete)
+				{
+					throw new InvalidOperationException("Search results have been completed");
+				}
+				result.SetResultIndex(mCount);
+				mResults[mCount++] = result;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Indicates that the results are complete, and no more will be added.
+		/// 
+		public void SetComplete()
+		{
+			lock (mLock)
+			{
+				mComplete = true;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Gets all the available results so far.
+		/// 
+		/// Index to start returning from. Modified to be the first index not available yet on return.
+		/// Set to true if the results are complete, false if more results are pending but have not been returned.
+		/// 
+		public SearchResult[] GetAvailableResults(ref int index, out bool complete)
+		{
+			int count;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			if (count <= index)
+			{
+				return new SearchResult[0];
+			}
+
+			var availableResults = new SearchResult[count - index];
+			Array.Copy(mResults, index, availableResults, 0, availableResults.Length);
+			index = count;
+
+			return availableResults;
+		}
+
+		/// 
+		/// Gets all the results. Will block until complete.
+		/// 
+		/// 
+		public IEnumerable GetAllResults()
+		{
+			int count = -1;
+
+			for (var i = 0; i < mResults.Length; i++)
+			{
+				if (i > count)
+				{
+					// Reached the limit of availability so far, so see if more is available
+					do
+					{
+						bool moreAvailable, complete;
+
+						lock (mLock)
+						{
+							moreAvailable = mCount > count;
+							count = mCount;
+							complete = mComplete;
+						}
+
+						if (!moreAvailable)
+						{
+							if (complete)
+							{
+								// No more available, but the results are now complete anyway
+								yield break;
+							}
+
+							// No more available yet, not yet complete, wait until more becomes available
+							mResultsUpdated.WaitOne();
+						}
+						else
+						{
+							// More available now, so stop checking for more, continue with the loop to return them
+							break;
+						}
+					} while (true);
+
+					Debug.Assert(i <= count, "More should be available now");
+				}
+
+				yield return mResults[i];
+			}
+		}
+
+		public SearchResults CreateChildResults(string term)
+		{
+			Debug.Assert(term.StartsWith(mTerm));
+
+			int count;
+			bool complete;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			// If complete, then we know we don't need more than count. Otherwise, it can't be more than this capacity anyway
+			var childCapacity = complete ? count : mResults.Length;
+
+			return new SearchResults(childCapacity, term);
+		}
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.Designer.cs b/AutoTypeSearch/SearchWindow.Designer.cs
new file mode 100755
index 0000000..18b37d1
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.Designer.cs
@@ -0,0 +1,201 @@
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	partial class SearchWindow
+	{
+		/// 
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		#region Windows Form Designer generated code
+
+		/// 
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			this.components = new System.ComponentModel.Container();
+			this.mSearch = new System.Windows.Forms.TextBox();
+			this.mResults = new System.Windows.Forms.ListBox();
+			this.mLayout = new System.Windows.Forms.TableLayoutPanel();
+			this.mBanner = new System.Windows.Forms.PictureBox();
+			this.mInfoBanner = new System.Windows.Forms.Panel();
+			this.mInfoLabel = new System.Windows.Forms.Label();
+			this.mInfoBannerImage = new System.Windows.Forms.PictureBox();
+			this.mThrobber = new System.Windows.Forms.PictureBox();
+			this.mResultsUpdater = new System.Windows.Forms.Timer(this.components);
+			this.mNoResultsLabel = new System.Windows.Forms.Label();
+			this.mLayout.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).BeginInit();
+			this.mInfoBanner.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).BeginInit();
+			this.SuspendLayout();
+			// 
+			// mSearch
+			// 
+			this.mSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mSearch.Location = new System.Drawing.Point(1, 78);
+			this.mSearch.Margin = new System.Windows.Forms.Padding(1, 0, 1, 0);
+			this.mSearch.Name = "mSearch";
+			this.mSearch.Size = new System.Drawing.Size(521, 20);
+			this.mSearch.TabIndex = 0;
+			this.mSearch.LocationChanged += new System.EventHandler(this.mSearch_LocationChanged);
+			this.mSearch.TextChanged += new System.EventHandler(this.mSearch_TextChanged);
+			// 
+			// mResults
+			// 
+			this.mResults.BorderStyle = System.Windows.Forms.BorderStyle.None;
+			this.mResults.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mResults.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
+			this.mResults.FormattingEnabled = true;
+			this.mResults.IntegralHeight = false;
+			this.mResults.Location = new System.Drawing.Point(0, 98);
+			this.mResults.Margin = new System.Windows.Forms.Padding(0);
+			this.mResults.Name = "mResults";
+			this.mResults.Size = new System.Drawing.Size(523, 176);
+			this.mResults.TabIndex = 1;
+			this.mResults.TabStop = false;
+			this.mResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseClick);
+			this.mResults.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.mResults_DrawItem);
+			this.mResults.LocationChanged += new System.EventHandler(this.mResults_LocationChanged);
+			this.mResults.MouseEnter += new System.EventHandler(this.mResults_MouseEnter);
+			this.mResults.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseMove);
+			// 
+			// mLayout
+			// 
+			this.mLayout.ColumnCount = 1;
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+			this.mLayout.Controls.Add(this.mSearch, 0, 2);
+			this.mLayout.Controls.Add(this.mResults, 0, 3);
+			this.mLayout.Controls.Add(this.mBanner, 0, 0);
+			this.mLayout.Controls.Add(this.mInfoBanner, 0, 1);
+			this.mLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mLayout.Location = new System.Drawing.Point(0, 0);
+			this.mLayout.Name = "mLayout";
+			this.mLayout.RowCount = 4;
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.Size = new System.Drawing.Size(523, 274);
+			this.mLayout.TabIndex = 2;
+			// 
+			// mBanner
+			// 
+			this.mBanner.Dock = System.Windows.Forms.DockStyle.Top;
+			this.mBanner.Location = new System.Drawing.Point(0, 0);
+			this.mBanner.Margin = new System.Windows.Forms.Padding(0);
+			this.mBanner.Name = "mBanner";
+			this.mBanner.Size = new System.Drawing.Size(523, 60);
+			this.mBanner.TabIndex = 3;
+			this.mBanner.TabStop = false;
+			this.mBanner.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mBannerImage_MouseDown);
+			// 
+			// mInfoBanner
+			// 
+			this.mInfoBanner.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+			this.mInfoBanner.BackColor = System.Drawing.SystemColors.Info;
+			this.mInfoBanner.Controls.Add(this.mInfoLabel);
+			this.mInfoBanner.Controls.Add(this.mInfoBannerImage);
+			this.mInfoBanner.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoBanner.Location = new System.Drawing.Point(2, 61);
+			this.mInfoBanner.Margin = new System.Windows.Forms.Padding(2, 1, 1, 1);
+			this.mInfoBanner.Name = "mInfoBanner";
+			this.mInfoBanner.Size = new System.Drawing.Size(520, 16);
+			this.mInfoBanner.TabIndex = 8;
+			// 
+			// mInfoLabel
+			// 
+			this.mInfoLabel.AutoEllipsis = true;
+			this.mInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoLabel.ForeColor = System.Drawing.SystemColors.InfoText;
+			this.mInfoLabel.Location = new System.Drawing.Point(16, 0);
+			this.mInfoLabel.Name = "mInfoLabel";
+			this.mInfoLabel.Size = new System.Drawing.Size(504, 16);
+			this.mInfoLabel.TabIndex = 6;
+			this.mInfoLabel.Text = "AutoType failed to find";
+			// 
+			// mInfoBannerImage
+			// 
+			this.mInfoBannerImage.Dock = System.Windows.Forms.DockStyle.Left;
+			this.mInfoBannerImage.Image = global::AutoTypeSearch.Properties.Resources.Info;
+			this.mInfoBannerImage.Location = new System.Drawing.Point(0, 0);
+			this.mInfoBannerImage.Margin = new System.Windows.Forms.Padding(0);
+			this.mInfoBannerImage.Name = "mInfoBannerImage";
+			this.mInfoBannerImage.Size = new System.Drawing.Size(16, 16);
+			this.mInfoBannerImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mInfoBannerImage.TabIndex = 7;
+			this.mInfoBannerImage.TabStop = false;
+			// 
+			// mThrobber
+			// 
+			this.mThrobber.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.mThrobber.BackColor = System.Drawing.SystemColors.Window;
+			this.mThrobber.Location = new System.Drawing.Point(503, 81);
+			this.mThrobber.Name = "mThrobber";
+			this.mThrobber.Size = new System.Drawing.Size(16, 16);
+			this.mThrobber.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mThrobber.TabIndex = 4;
+			this.mThrobber.TabStop = false;
+			this.mThrobber.Visible = false;
+			// 
+			// mResultsUpdater
+			// 
+			this.mResultsUpdater.Interval = 250;
+			this.mResultsUpdater.Tick += new System.EventHandler(this.mResultsUpdater_Tick);
+			// 
+			// mNoResultsLabel
+			// 
+			this.mNoResultsLabel.AutoSize = true;
+			this.mNoResultsLabel.Location = new System.Drawing.Point(5, 103);
+			this.mNoResultsLabel.Name = "mNoResultsLabel";
+			this.mNoResultsLabel.Size = new System.Drawing.Size(84, 13);
+			this.mNoResultsLabel.TabIndex = 5;
+			this.mNoResultsLabel.Text = "No results found";
+			// 
+			// SearchWindow
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.BackColor = System.Drawing.SystemColors.Window;
+			this.ClientSize = new System.Drawing.Size(523, 274);
+			this.ControlBox = false;
+			this.Controls.Add(this.mNoResultsLabel);
+			this.Controls.Add(this.mThrobber);
+			this.Controls.Add(this.mLayout);
+			this.MinimumSize = new System.Drawing.Size(160, 96);
+			this.Name = "SearchWindow";
+			this.ShowInTaskbar = false;
+			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+			this.TopMost = true;
+			this.mLayout.ResumeLayout(false);
+			this.mLayout.PerformLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).EndInit();
+			this.mInfoBanner.ResumeLayout(false);
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).EndInit();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.TextBox mSearch;
+		private System.Windows.Forms.ListBox mResults;
+		private System.Windows.Forms.TableLayoutPanel mLayout;
+		private System.Windows.Forms.PictureBox mBanner;
+		private PictureBox mThrobber;
+		private Timer mResultsUpdater;
+		private Label mNoResultsLabel;
+		private Label mInfoLabel;
+		private Panel mInfoBanner;
+		private PictureBox mInfoBannerImage;
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchWindow.cs b/AutoTypeSearch/SearchWindow.cs
new file mode 100755
index 0000000..363b898
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.cs
@@ -0,0 +1,925 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Media;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Resources;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Collections;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	public partial class SearchWindow : Form
+	{
+		private const int SecondLineInset = 10;
+
+		// HACK to work around mono bug
+		private static readonly FieldInfo sMonoListBoxTopIndex = typeof(ListBox).GetField("top_index", BindingFlags.Instance | BindingFlags.NonPublic);
+
+		private readonly MainForm mMainForm;
+		private readonly Bitmap mBannerImage;
+		private readonly Searcher mSearcher;
+
+		private readonly Stream mThrobberImageStream;
+
+		private int? mWindowTopBorderHeight;
+		private int mBannerWidth = -1;
+		private int mMaximumExpandHeight;
+		private bool mManualSizeApplied;
+		private SearchResults mCurrentSearch;
+		private SearchResults mLastResultsUpdated;
+		private int mLastResultsUpdatedNextAvailableIndex;
+
+		#region Opening
+		public SearchWindow()
+		{
+			InitializeComponent();
+
+			// Mono can't load animated gifs from resx without crashing, so load it from an embedded resource instead
+			try
+			{
+				mThrobberImageStream = GetType().Assembly.GetManifestResourceStream("AutoTypeSearch.Throbber.gif");
+				if (mThrobberImageStream != null)
+				{
+					mThrobber.Image = Image.FromStream(mThrobberImageStream);
+				}
+			}
+			catch (Exception ex)
+			{
+				Debug.Fail("Failed to load Throbber.gif from embedded resource: " + ex.Message);
+			}
+
+			GlobalWindowManager.CustomizeControl(this);
+			UIUtil.SetExplorerTheme(mResults, true);
+			SetItemHeight();
+		}
+
+		public SearchWindow(MainForm mainForm, string infoBanner) : this()
+		{
+			mMainForm = mainForm;
+
+			mInfoBanner.Height = Math.Max(mInfoBannerImage.Height, mInfoLabel.Font.Height) + mInfoBanner.Margin.Vertical;
+			mInfoLabel.Padding = new Padding(0, (mInfoBanner.Height - mInfoLabel.Font.Height) / 2, 0, 0);
+			mInfoLabel.Text = infoBanner;
+
+			if (infoBanner == null)
+			{
+				mInfoBanner.Visible = false;
+				mInfoBanner.Height = 0;
+			}
+			
+			mSearcher = new Searcher(mMainForm.DocumentManager.GetOpenDatabases().ToArray());
+
+			Icon = mMainForm.Icon;
+			using (var bannerIcon = new Icon(Icon, 48, 48))
+			{
+				mBannerImage = bannerIcon.ToBitmap();
+			}
+			UpdateBanner();
+
+			ShowThrobber = false;
+
+			FontUtil.AssignDefaultItalic(mNoResultsLabel);
+		}
+
+
+		protected override void OnCreateControl()
+		{
+			base.OnCreateControl();
+
+			if (NativeMethods.IsWindows10())
+			{
+				mWindowTopBorderHeight = PointToScreen(Point.Empty).Y - this.Top;
+				NativeMethods.RefreshWindowFrame(Handle);
+			}
+
+			var windowRect = Settings.Default.WindowPosition;
+			var collapsedWindowRect = windowRect;
+			
+			collapsedWindowRect.Height = mSearch.Bottom + (Height - ClientSize.Height);
+
+			MinimumSize = new Size(MinimumSize.Width, collapsedWindowRect.Height);
+
+			if (windowRect.IsEmpty || !IsOnScreen(collapsedWindowRect))
+			{
+				windowRect = new Rectangle(0, 0, Width, Height);
+				Height = collapsedWindowRect.Height;
+
+				CenterToScreen();
+			}
+			else
+			{
+				Location = windowRect.Location;
+				Size = collapsedWindowRect.Size;
+			}
+
+			mMaximumExpandHeight = Math.Max(windowRect.Height, MinimumSize.Height + mResults.ItemHeight);
+		}
+		
+
+		private static bool IsOnScreen(Rectangle rectangle)
+		{
+			return Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(rectangle));
+		}
+
+		private void SetItemHeight()
+		{
+			mResults.ItemHeight = mResults.Font.Height * 2 + 2;
+		}
+
+		protected override void WndProc(ref Message m)
+		{
+			if (mWindowTopBorderHeight.HasValue)
+			{
+				NativeMethods.RemoveWindowFrameTopBorder(ref m, mWindowTopBorderHeight.Value);
+			}
+			base.WndProc(ref m);
+		}
+
+		#endregion
+
+		#region Closing
+		protected override void OnActivated(EventArgs e)
+		{
+			base.OnActivated(e);
+			Deactivate += OnDeactivate;
+		}
+
+		private void OnDeactivate(object sender, EventArgs eventArgs)
+		{
+			Close();
+		}
+
+		protected override void OnClosed(EventArgs e)
+		{
+			Deactivate -= OnDeactivate;
+			base.OnClosed(e);
+		}
+
+		/// 
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				if (mBannerImage != null)
+				{
+					mBannerImage.Dispose();
+				}
+				if (mThrobber.Image != null)
+				{
+					mThrobber.Image.Dispose();
+					mThrobber.Image = null;
+					mThrobberImageStream.Dispose();
+				}
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+		#endregion
+
+		#region Item Drawing
+		private void mResults_DrawItem(object sender, DrawItemEventArgs e)
+		{
+			var searchResult = mResults.Items[e.Index] as SearchResult;
+			if (searchResult == null)
+			{
+				Debug.Fail("Unexpected item in mResults");
+// ReSharper disable once HeuristicUnreachableCode - Not unreachable
+				return;
+			}
+			var drawingArea = e.Bounds;
+			drawingArea.Height--; // Leave room for a dividing line at the bottom
+			
+			if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
+			{
+				DrawBorderedRectangle(e.Graphics, drawingArea, SystemColors.Highlight);
+			}
+			else
+			{
+				e.Graphics.FillRectangle(SystemBrushes.Window, drawingArea);
+			}
+
+			var image = GetImage(searchResult.Database, searchResult.Entry.CustomIconUuid, searchResult.Entry.IconId);
+			var imageMargin = (drawingArea.Height - image.Height) / 2;
+			e.Graphics.DrawImage(image, drawingArea.Left + imageMargin, drawingArea.Top + imageMargin, image.Width, image.Height);
+
+			var textLeftMargin = drawingArea.Left + imageMargin * 2 + image.Width;
+			var textBounds = new Rectangle(textLeftMargin, drawingArea.Top + 1, drawingArea.Width - textLeftMargin - 1, drawingArea.Height - 2);
+
+			var line1Bounds = textBounds;
+			line1Bounds.Height = e.Font.Height;
+			var line2Bounds = line1Bounds;
+			line2Bounds.Y += line2Bounds.Height - 1;
+			line2Bounds.X += SecondLineInset;
+			line2Bounds.Width -= SecondLineInset;
+
+			var resultInTitleField = searchResult.FieldName == PwDefs.TitleField;
+
+			var title = (resultInTitleField ? searchResult.FieldValue : searchResult.Title).Replace('\n', ' '); // The FieldValue may have references resolved, whereas the title is always read directly.
+
+			var uniqueTitlePartWidth = 0;
+			if (!String.IsNullOrEmpty(searchResult.UniqueTitlePart))
+			{
+				var uniqueTitlePart = searchResult.UniqueTitlePart.Replace('\n', ' ');
+
+				var titleWidth = TextRenderer.MeasureText(e.Graphics, title, e.Font, line1Bounds.Size, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+
+				var availableWidthForUniqueTitlePart = line1Bounds.Width - titleWidth;
+				if (availableWidthForUniqueTitlePart > 20) // Don't bother including a unique part if there's no room for it
+				{
+					var uniqueTitlePartReversed = ReverseString(uniqueTitlePart);
+
+					uniqueTitlePartWidth = TextRenderer.MeasureText(e.Graphics, uniqueTitlePartReversed, e.Font, new Size(availableWidthForUniqueTitlePart, line1Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+					uniqueTitlePart = ReverseString(uniqueTitlePartReversed);
+
+					TextRenderer.DrawText(e.Graphics, uniqueTitlePart, e.Font, new Rectangle(line1Bounds.X, line1Bounds.Y, uniqueTitlePartWidth, line1Bounds.Height), SystemColors.GrayText, TextFormatFlags.NoPadding);
+				}
+			}
+
+			var titleBounds = new Rectangle(line1Bounds.X + uniqueTitlePartWidth, line1Bounds.Y, line1Bounds.Width - uniqueTitlePartWidth, line1Bounds.Height);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Highlight title in first line.
+				DrawHighlight(e, titleBounds, title, searchResult.Start, searchResult.Length);
+			}
+
+			TextRenderer.DrawText(e.Graphics, searchResult.Title, e.Font, titleBounds, SystemColors.WindowText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Use Username for second line.
+				TextRenderer.DrawText(e.Graphics, KPRes.UserName + ": " + searchResult.Entry.Strings.ReadSafeEx(PwDefs.UserNameField), e.Font, line2Bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+			}
+			else
+			{
+				// Found the result in not title field. Show the matching result on second line
+				
+				var fieldValue = searchResult.FieldValue.Replace('\n',' ');
+				var fieldNamePrefix = GetDisplayFieldName(searchResult.FieldName) + ": ";
+
+				var remainingSpace = line2Bounds.Width;
+				var fieldNamePrefixWidth = TextRenderer.MeasureText(e.Graphics, fieldNamePrefix, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+				remainingSpace -= fieldNamePrefixWidth;
+
+				int fieldValueHighlightWidth = 0, fieldValueLeftContextWidth = 0, fieldValueRightContextWidth = 0;
+
+				var leftContext = fieldValue.Substring(0, searchResult.Start);
+				var highlight = fieldValue.Substring(searchResult.Start, searchResult.Length);
+				var rightContext = fieldValue.Substring(searchResult.Start + searchResult.Length);
+
+				if (searchResult.Length == 0)
+				{
+					fieldValueHighlightWidth = remainingSpace;
+				}
+				else
+				{
+					if (remainingSpace > 0)
+					{
+						var availableSpace = remainingSpace;
+						fieldValueHighlightWidth = TextRenderer.MeasureText(e.Graphics, highlight, e.Font, new Size(availableSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						remainingSpace -= fieldValueHighlightWidth;
+					}
+
+					// Of the space remaining, divide it equally between that which comes before, and that which comes after
+					if (!String.IsNullOrEmpty(leftContext))
+					{
+						var leftContextReversed = ReverseString(leftContext);
+						fieldValueLeftContextWidth = TextRenderer.MeasureText(e.Graphics, leftContextReversed, e.Font, new Size(remainingSpace / 2, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+						if (fieldValueLeftContextWidth > remainingSpace)
+						{
+							// Always allow space for the minimal left context
+							fieldValueHighlightWidth -= (fieldValueLeftContextWidth - remainingSpace);
+							remainingSpace = 0;
+						}
+						else
+						{
+							remainingSpace -= fieldValueLeftContextWidth;							
+						}
+						
+						// Replace left context with the truncated reversed left context.
+						leftContext = ReverseString(leftContextReversed);
+					}
+
+					if (remainingSpace > 0 && !String.IsNullOrEmpty(rightContext))
+					{
+						fieldValueRightContextWidth = TextRenderer.MeasureText(e.Graphics, rightContext, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						if (fieldValueRightContextWidth > remainingSpace)
+						{
+							fieldValueRightContextWidth = 0;
+						}
+					}
+				}
+
+				// Now draw it all
+				var bounds = line2Bounds;
+				bounds.Width = fieldNamePrefixWidth;
+				TextRenderer.DrawText(e.Graphics, fieldNamePrefix, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				if (fieldValueLeftContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueLeftContextWidth;
+					TextRenderer.DrawText(e.Graphics, leftContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding); // No ellipsis as the leftContext string has already been truncated appropriately
+				}
+				if (fieldValueHighlightWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueHighlightWidth;
+
+					if (searchResult.Length > 0)
+					{
+						DrawHighlightRectangle(e, bounds);
+					}
+					TextRenderer.DrawText(e.Graphics, highlight, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+				if (fieldValueRightContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueRightContextWidth;
+					TextRenderer.DrawText(e.Graphics, rightContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+			}
+
+			e.Graphics.DrawLine(SystemPens.ButtonFace, drawingArea.Left, drawingArea.Bottom, drawingArea.Right, drawingArea.Bottom);
+		}
+
+		private static string ReverseString(string value)
+		{
+			return new String(value.ToCharArray().TakeWhile(c => c != '\0').Reverse().ToArray());
+		}
+
+		private static void DrawHighlight(DrawItemEventArgs e, Rectangle lineBounds, string text, int highlightFrom, int highlightLength)
+		{
+			var highlightX = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width;
+			var highlightWidth = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom + highlightLength), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width - highlightX;
+
+			DrawHighlightRectangle(e, new Rectangle(lineBounds.Left + highlightX, lineBounds.Top, highlightWidth, lineBounds.Height));
+		}
+
+		private static void DrawHighlightRectangle(DrawItemEventArgs e, Rectangle rectangle)
+		{
+			DrawBorderedRectangle(e.Graphics, rectangle, Color.PaleTurquoise);
+		}
+
+		private static void DrawBorderedRectangle(Graphics graphics, Rectangle rectangle, Color colour)
+		{
+			var border = rectangle;
+			border.Width--;
+			border.Height--;
+
+			using (var brush = new SolidBrush(MergeColors(colour, SystemColors.Window, 0.2)))
+			{
+				graphics.FillRectangle(brush, rectangle);
+			}
+			using (var pen = new Pen(colour, 1f))
+			{
+				graphics.DrawRectangle(pen, border);
+			}
+		}
+
+		private Image GetImage(PwDatabase database, PwUuid customIconId, PwIcon iconId)
+		{
+			Image image = null;
+			if (!customIconId.Equals(PwUuid.Zero))
+			{
+				image = database.GetCustomIcon(customIconId, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16));
+			}
+			if (image == null)
+			{
+				try { image = mMainForm.ClientIcons.Images[(int)iconId]; }
+				catch (Exception) { Debug.Assert(false); }
+			}
+
+			return image;
+		}
+
+		private static string GetDisplayFieldName(string fieldName)
+		{
+			switch (fieldName)
+			{
+				case PwDefs.TitleField:
+					return KPRes.Title;
+				case PwDefs.UserNameField:
+					return KPRes.UserName;
+				case PwDefs.PasswordField:
+					return KPRes.Password;
+				case PwDefs.UrlField:
+					return KPRes.Url;
+				case PwDefs.NotesField:
+					return KPRes.Notes;
+				case AutoTypeSearchExt.TagsVirtualFieldName:
+					return KPRes.Tags;
+				default:
+					return fieldName;
+			}
+		}
+
+		public static Color MergeColors(Color from, Color to, double amount)
+		{
+			var r = (byte)((from.R * amount) + to.R * (1 - amount));
+			var g = (byte)((from.G * amount) + to.G * (1 - amount));
+			var b = (byte)((from.B * amount) + to.B * (1 - amount));
+			return Color.FromArgb(r, g, b);
+		}
+		#endregion
+
+		#region Mouse tracking
+		private Point mMouseEntryPosition;
+		
+		private void mResults_MouseEnter(object sender, EventArgs e)
+		{
+			mMouseEntryPosition = MousePosition;
+		}
+
+		private void mResults_MouseMove(object sender, MouseEventArgs e)
+		{
+			// Discard the location the mouse has on entering the control (as it may be that the control has just moved under the mouse, not the other way around)
+			if (MousePosition == mMouseEntryPosition)
+			{
+				return;
+			}
+
+			// Hot tracking
+			var hoverIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (hoverIndex >= 0 && mResults.SelectedIndex != hoverIndex)
+			{
+				if (mResults.GetItemRectangle(hoverIndex).Bottom <= mResults.ClientRectangle.Bottom)
+				{
+					mResults.SelectedIndex = hoverIndex;
+				}
+				else
+				{
+					// Avoid the control scrolling
+					mResults.BeginUpdate();
+					var topIndex = mResults.TopIndex;
+					mResults.SelectedIndex = hoverIndex;
+					mResults.TopIndex = topIndex;
+					mResults.EndUpdate();
+				}
+			}
+		}
+		#endregion
+
+		#region Resizing
+		protected override void OnResizeBegin(EventArgs e)
+		{
+			// Stop automatically sizing - the user is picking a size they want.
+			mManualSizeApplied = true;
+			base.OnResizeBegin(e);
+		}
+
+		protected override void OnResize(EventArgs e)
+		{
+			base.OnResize(e);
+
+			UpdateBanner();
+
+			mResults.Invalidate();
+		}
+
+		protected override void OnResizeEnd(EventArgs e)
+		{
+			base.OnResizeEnd(e);
+
+			if (Height > MinimumSize.Height && Height != mMaximumExpandHeight)
+			{
+				mMaximumExpandHeight = Math.Max(Height, MinimumSize.Height + mResults.ItemHeight);
+			}
+			else
+			{
+				mManualSizeApplied = false;
+			}
+
+			Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+		}
+
+		private void UpdateBanner()
+		{
+			if (mBannerImage != null)
+			{
+				BannerFactory.UpdateBanner(this, mBanner, mBannerImage, PwDefs.ProductName, Resources.BannerText, ref mBannerWidth);
+			}
+		}
+
+		private void mSearch_LocationChanged(object sender, EventArgs e)
+		{
+			mThrobber.Location = new Point(mSearch.Right - mThrobber.Width - mThrobber.Margin.Right, mSearch.Top + (mSearch.Height - mThrobber.Height) / 2);
+		}
+
+		private void mResults_LocationChanged(object sender, EventArgs e)
+		{
+			mNoResultsLabel.Top = mResults.Top + (mResults.ItemHeight - mNoResultsLabel.Height) / 2;
+		}
+		#endregion
+
+		#region Searching
+		private static readonly SearchResultPrecedence SearchResultPrecedenceComparer = new SearchResultPrecedence();
+		private void mSearch_TextChanged(object sender, EventArgs e)
+		{
+			if (mSearch.Text.Length < 2)
+			{
+				// Stop searching
+				mResultsUpdater.Enabled = false;
+				ShowThrobber = false;
+				Height = MinimumSize.Height;
+				mManualSizeApplied = false;
+				mResults.Items.Clear();
+				mLastResultsUpdated = null;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			else
+			{
+				// Start searching
+				mNoResultsLabel.Visible = false;
+				mCurrentSearch = mSearcher.Search(mSearch.Text);
+				mResultsUpdater.Enabled = true;
+				ShowThrobber = true;
+				mResultsUpdater_Tick(null, EventArgs.Empty); // Quick poke just in case the results are already done.
+			}
+		}
+
+		[SuppressMessage("ReSharper", "CoVariantArrayConversion", Justification = "Object arrays for Listbox.Items, known to be of correct type")]
+		private void mResultsUpdater_Tick(object sender, EventArgs e)
+		{
+			if (mLastResultsUpdated != mCurrentSearch)
+			{
+				// Clear out old results and replace with new ones
+				mResults.Items.Clear();
+				mLastResultsUpdated = mCurrentSearch;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			var existingResultsCount = mResults.Items.Count;
+			
+			bool complete;
+			var newResults = mLastResultsUpdated.GetAvailableResults(ref mLastResultsUpdatedNextAvailableIndex, out complete);
+			if (newResults.Length > 0)
+			{
+				mResults.BeginUpdate();
+				
+				SearchResult[] allResults;
+				if (existingResultsCount > 0)
+				{
+					allResults = new SearchResult[existingResultsCount + newResults.Length];
+					mResults.Items.CopyTo(allResults, 0);
+					newResults.CopyTo(allResults, existingResultsCount);
+
+					mResults.Items.Clear();
+				}
+				else
+				{
+					allResults = newResults;
+				}
+
+				CalculateUniqueTitles(allResults);
+
+				Array.Sort(allResults, SearchResultPrecedenceComparer);
+				mResults.Items.AddRange(allResults);
+				
+				mResults.EndUpdate();
+
+				if (allResults.Length > 0)
+				{
+					if (mResults.SelectedIndex == -1)
+					{
+						try
+						{
+							// HACK to work around mono bug
+							if (sMonoListBoxTopIndex != null)
+							{
+								sMonoListBoxTopIndex.SetValue(mResults, 1); // Set the top_index to 1 so that when selected index is set to 0, and calls EnsureVisible(0), it follows the index < top_index pass and not the broken index >= top_index + rows path. 
+							}
+
+							mResults.SelectedIndex = 0;
+							mResults.TopIndex = 0;
+						}
+						catch (Exception ex)
+						{
+							Debug.Fail("Failed to set selection on count of " + allResults.Length + ": " + ex.Message);
+						}
+					}
+
+					if (!mManualSizeApplied)
+					{
+						Height = Math.Min(mMaximumExpandHeight, MinimumSize.Height + (allResults.Length * mResults.ItemHeight));
+					}
+				}
+			}
+
+			if (complete)
+			{
+				ShowThrobber = false;
+				mResultsUpdater.Enabled = false;
+
+				if (mResults.Items.Count == 0)
+				{
+					mNoResultsLabel.Visible = true;
+					Height = MinimumSize.Height + mResults.ItemHeight;
+					mManualSizeApplied = false;
+				}
+			}
+		}
+
+		private void CalculateUniqueTitles(IEnumerable results, int depth = 0)
+		{
+			// Where results have identical titles, include group titles to make them unique
+			depth += 1;
+
+			// First create a lookup by title
+			var titles = new Dictionary>();
+			foreach (var searchResult in results)
+			{
+				List resultsWithSameTitle;
+				if (titles.TryGetValue(searchResult.UniqueTitle, out resultsWithSameTitle))
+				{
+					resultsWithSameTitle.Add(searchResult);
+				}
+				else
+				{
+					titles.Add(searchResult.UniqueTitle, new List { searchResult });
+				}
+			}
+
+			// Attempt to unique-ify any non-unique titles
+			foreach (var resultsSharingTitle in titles.Values)
+			{
+				if (resultsSharingTitle.Count > 1)
+				{
+					var titlesModified = false;
+					foreach (var searchResult in resultsSharingTitle)
+					{
+						titlesModified |= searchResult.SetUniqueTitleDepth(depth);
+					}
+
+					if (titlesModified)
+					{
+						// Recurse in case of continuing non-uniqueness
+						CalculateUniqueTitles(resultsSharingTitle, depth);
+					}
+				}
+			}
+		}
+
+		private class SearchResultPrecedence : IComparer
+		{
+			public int Compare(SearchResult x, SearchResult y)
+			{
+				// First precedence is that if the result is the start of the field value, it's higher precedence than if it doesn't.
+				var result = -(x.Start == 0).CompareTo(y.Start == 0);
+
+				// Second precedence is that the start of the title field is higher precedence than the start of any other field
+				if (result == 0)
+				{
+					result = -(x.FieldName == PwDefs.TitleField).CompareTo(y.FieldName == PwDefs.TitleField);
+				}
+
+				// Both start the title field, so both equal. Have to have consistent ordering, so return final precedence based search index
+				if (result == 0)
+				{
+					result = x.ResultIndex.CompareTo(y.ResultIndex);
+				}
+				
+				return result;
+			}
+		}
+
+		private bool ShowThrobber
+		{
+			get { return mThrobber.Visible; }
+			set
+			{
+				if (value != ShowThrobber)
+				{
+					if (value)
+					{
+						mThrobber.Visible = true;
+
+						// Set the margin on the textbox to allow room for the throbber
+						NativeMethods.SetTextBoxRightMargin(mSearch, mThrobber.Width + mThrobber.Margin.Right);
+					}
+					else
+					{
+						mThrobber.Visible = false;
+
+						NativeMethods.SetTextBoxRightMargin(mSearch, 0);
+					}
+				}
+			}
+		}
+		#endregion
+
+		private void mBannerImage_MouseDown(object sender, MouseEventArgs e)
+		{
+			// Allow drag by banner image
+			if (e.Button == MouseButtons.Left)
+			{
+				if (e.Clicks == 2)
+				{
+					// Re-center the form on double-click
+					CenterToScreen();
+
+					Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+				}
+				else if (!NativeLib.IsUnix())
+				{
+					NativeMethods.StartFormDrag(this);
+				}
+			}
+		}
+
+		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+		{
+			switch (keyData)
+			{
+				case Keys.Escape:
+					Close();
+					return true;
+				case Keys.Up:
+					TryChangeSelection(-1);
+					return true;
+				case Keys.Down:
+					TryChangeSelection(1);
+					return true;
+				case Keys.PageUp:
+					TryChangeSelection(-mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.PageDown:
+					TryChangeSelection(mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.Home | Keys.Control:
+					mResults.SelectedIndex = 0;
+					return true;
+				case Keys.End | Keys.Control:
+					mResults.SelectedIndex = mResults.Items.Count - 1;
+					return true;
+				case Keys.Enter:
+					PerformAction(Settings.Default.DefaultAction, mResults.SelectedItem as SearchResult);
+					break;
+				case Keys.Enter | Keys.Shift:
+					PerformAction(Settings.Default.AlternativeAction, mResults.SelectedItem as SearchResult);
+					break;
+			}
+			
+			return base.ProcessCmdKey(ref msg, keyData);
+		}
+
+		#region Selection Changing
+
+		protected override void OnMouseWheel(MouseEventArgs e)
+		{
+			mResults.TopIndex -= (e.Delta / Math.Abs(e.Delta));
+		}
+
+		private void TryChangeSelection(int delta)
+		{
+			if (mResults.Items.Count > 0)
+			{
+				mResults.SelectedIndex = Math.Max(Math.Min(mResults.Items.Count - 1, mResults.SelectedIndex + delta), 0);
+			}
+		}
+		#endregion
+
+		#region Actions
+
+		private void mResults_MouseClick(object sender, MouseEventArgs e)
+		{
+			var clickIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (clickIndex >= 0)
+			{
+				var clickedResult = mResults.Items[clickIndex] as SearchResult;
+				if (clickedResult != null)
+				{
+					PerformAction((ModifierKeys & Keys.Shift) == Keys.Shift ? Settings.Default.AlternativeAction : Settings.Default.DefaultAction, clickedResult);
+				}
+			}
+		}
+
+		private void PerformAction(Actions action, SearchResult searchResult)
+		{
+			Close();
+
+			if (searchResult != null)
+			{
+				switch (action)
+				{
+					case Actions.PerformAutoType:
+						AutoTypeEntry(searchResult);
+						break;
+					case Actions.EditEntry:
+						EditEntry(searchResult);
+						break;
+					case Actions.ShowEntry:
+						ShowEntry(searchResult);
+						break;
+					case Actions.OpenEntryUrl:
+						OpenEntryUrl(searchResult);
+						break;
+					case Actions.CopyPassword:
+						CopyPassword(searchResult);
+						break;
+					default:
+						throw new ArgumentOutOfRangeException("action");
+				}
+			}
+		}
+
+		private void AutoTypeEntry(SearchResult searchResult)
+		{
+			bool result;
+			if (ActiveForm != null)
+			{
+				result = AutoType.PerformIntoPreviousWindow(mMainForm, searchResult.Entry, searchResult.Database);
+			}
+			else
+			{
+				result = AutoType.PerformIntoCurrentWindow(searchResult.Entry, searchResult.Database);
+			}
+			if (!result)
+			{
+				SystemSounds.Beep.Play();
+
+				if (Settings.Default.AlternativeAction != Actions.PerformAutoType)
+				{
+					PerformAction(Settings.Default.AlternativeAction, searchResult);
+				}
+			}
+		}
+
+		private void EditEntry(SearchResult searchResult)
+		{
+			using (var entryForm = new PwEntryForm())
+			{
+				mMainForm.MakeDocumentActive(mMainForm.DocumentManager.FindDocument(searchResult.Database));
+				
+				entryForm.InitEx(searchResult.Entry, PwEditMode.EditExistingEntry, searchResult.Database, mMainForm.ClientIcons, false, false);
+
+				ShowForegroundDialog(entryForm);
+
+				mMainForm.UpdateUI(false, null, searchResult.Database.UINeedsIconUpdate, null, true, null, entryForm.HasModifiedEntry);
+			}
+		}
+
+// ReSharper disable once UnusedMethodReturnValue.Local - Generic helper, result may be used in future
+		private DialogResult ShowForegroundDialog(Form form)
+		{
+			mMainForm.EnsureVisibleForegroundWindow(false, false);
+			form.StartPosition = FormStartPosition.CenterScreen;
+			if (mMainForm.IsTrayed())
+			{
+				form.ShowInTaskbar = true;
+			}
+
+			form.Shown += ActivateFormOnShown;
+			return form.ShowDialog(mMainForm);
+		}
+
+		private static void ActivateFormOnShown(object sender, EventArgs eventArgs)
+		{
+			var form = (Form)sender;
+			form.Shown -= ActivateFormOnShown;
+			form.Activate();
+		}
+
+		private void ShowEntry(SearchResult searchResult)
+		{
+			// Show this entry
+			mMainForm.UpdateUI(false, mMainForm.DocumentManager.FindDocument(searchResult.Database), true, searchResult.Entry.ParentGroup, true, null, false, null);
+			mMainForm.SelectEntries(new PwObjectList { searchResult.Entry }, true, true);
+			mMainForm.EnsureVisibleEntry(searchResult.Entry.Uuid);
+			mMainForm.UpdateUI(false, null, false, null, false, null, false);
+			mMainForm.EnsureVisibleForegroundWindow(true, true);
+		}
+
+		private void OpenEntryUrl(SearchResult searchResult)
+		{
+			WinUtil.OpenEntryUrl(searchResult.Entry);
+		}
+
+		private void CopyPassword(SearchResult searchResult)
+		{
+			if (ClipboardUtil.Copy(searchResult.Entry.Strings.ReadSafe(PwDefs.PasswordField), true, true, searchResult.Entry,
+									mMainForm.DocumentManager.SafeFindContainerOf(searchResult.Entry),
+									IntPtr.Zero))
+			{
+				mMainForm.StartClipboardCountdown();
+			}
+		}
+		
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.resx b/AutoTypeSearch/SearchWindow.resx
new file mode 100755
index 0000000..8ef82f0
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.resx
@@ -0,0 +1,123 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    17, 17
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Searcher.cs b/AutoTypeSearch/Searcher.cs
new file mode 100755
index 0000000..433ae94
--- /dev/null
+++ b/AutoTypeSearch/Searcher.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class Searcher
+	{
+		private readonly PwDatabase[] mDatabases;
+		private readonly Dictionary mSearches = new Dictionary();
+
+		public Searcher(PwDatabase[] databases)
+		{
+			mDatabases = databases;
+		}
+
+		public SearchResults Search(string term)
+		{
+			if (term.Length < 2)
+			{
+				throw new ArgumentException("Search term must be at least 2 characters");
+			}
+
+			SearchResults parentResults = null;
+
+			var termParent = term;
+			while (termParent.Length >= 2)
+			{
+				if (mSearches.TryGetValue(termParent, out parentResults))
+				{
+					if (termParent == term)
+					{
+						// This is an exact duplicate search, so return it.
+						return parentResults;
+					}
+
+					// Found an existing search for a parent of the term, start from there.
+					break;
+				}
+		
+				// No existing search for termParent found, try less.
+				termParent = termParent.Remove(termParent.Length - 1, 1);
+			}
+
+			SearchResults searchResults;
+			if (parentResults == null)
+			{
+				// No parent found at all, start from scratch
+				searchResults = new SearchResults(GetCountOfAllDatabaseEntries(), term);
+
+				var rootSearchThread = new Thread(RootSearchWorker) { Name = term };
+				rootSearchThread.Start(searchResults);
+			}
+			else
+			{
+				searchResults = parentResults.CreateChildResults(term);
+
+				var childSearchThread = new Thread(ChildSearchWorker) { Name = term };
+				childSearchThread.Start(new ChildSearchWorkerState{ Source = parentResults, Results = searchResults });
+			}
+
+			mSearches.Add(term, searchResults);
+
+			return searchResults;
+		}
+
+		private int GetCountOfAllDatabaseEntries()
+		{
+			return (from database in mDatabases select (int)database.RootGroup.GetEntriesCount(true)).Sum();
+		}
+
+		private void RootSearchWorker(object stateObject)
+		{
+			var results = (SearchResults)stateObject;
+			var excludeExpired = Settings.Default.ExcludeExpired;
+			var searchStartTime = DateTime.Now;
+
+			foreach (var database in mDatabases)
+			{
+				SearchGroup(database, database.RootGroup, results, excludeExpired, searchStartTime);	
+			}
+
+			results.SetComplete();
+		}
+
+		/// 
+		/// Recursively search  and its children, adding results to 
+		/// 
+		private void SearchGroup(PwDatabase context, PwGroup group, SearchResults results, bool excludeExpired, DateTime searchStartTime)
+		{
+			if (group.EnableSearching ?? true) // Group will only be searched if it's parent enabled searching, so if it is inherit (null) or true, search it.
+			{
+				foreach (var childGroup in group.Groups)
+				{
+					SearchGroup(context, childGroup, results, excludeExpired, searchStartTime);
+				}
+
+				foreach (var entry in group.Entries)
+				{
+					if (!(excludeExpired && entry.Expires && searchStartTime > entry.ExpiryTime))
+					{
+						results.AddResultIfMatchesTerm(context, entry);
+					}
+				}
+			}
+		}
+
+		private struct ChildSearchWorkerState
+		{
+			public SearchResults Source;
+			public SearchResults Results;
+		}
+		private void ChildSearchWorker(object stateObject)
+		{
+			var state = (ChildSearchWorkerState)stateObject;
+
+			bool complete;
+			var index = 0;
+			do
+			{
+				foreach (var entry in state.Source.GetAvailableResults(ref index, out complete))
+				{
+					state.Results.AddResultIfMatchesTerm(entry);
+				}
+			} while (!complete);
+
+			state.Results.SetComplete();
+		}
+	}
+}
diff --git a/AutoTypeSearch/Throbber.gif b/AutoTypeSearch/Throbber.gif
new file mode 100755
index 0000000..494d426
--- /dev/null
+++ b/AutoTypeSearch/Throbber.gif
Binary files differ
diff --git a/AutoTypeSearch/app.config b/AutoTypeSearch/app.config
new file mode 100755
index 0000000..1370758
--- /dev/null
+++ b/AutoTypeSearch/app.config
@@ -0,0 +1,60 @@
+
+
+    
+        
+            
+        
+    
+    
+        
+            
+                True
+            
+            
+                False
+            
+            
+                True
+            
+            
+                True
+            
+            
+                True
+            
+            
+                True
+            
+            
+                False
+            
+            
+                0, 0, 0, 0
+            
+            
+                True
+            
+            
+                False
+            
+            
+                True
+            
+            
+                False
+            
+            
+                False
+            
+            
+                PerformAutoType
+            
+            
+                EditEntry
+            
+            
+                None
+            
+        
+    
+
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/AutoTypeSearch/SearchResults.cs b/AutoTypeSearch/SearchResults.cs
new file mode 100755
index 0000000..b2b0529
--- /dev/null
+++ b/AutoTypeSearch/SearchResults.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePass.Util.Spr;
+using KeePassLib;
+using KeePassLib.Utility;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResults
+	{
+		private readonly string mTerm;
+		private readonly SearchResult[] mResults;
+
+		private readonly object mLock = new object();
+		private volatile int mCount;
+		private volatile bool mComplete;
+
+		private readonly AutoResetEvent mResultsUpdated = new AutoResetEvent(false);
+
+		private readonly CompareOptions mStringComparison;
+		private readonly bool mSearchTitle;
+		private readonly bool mSearchUserName;
+		private readonly bool mSearchUrl;
+		private readonly bool mSearchNotes;
+		private readonly bool mSearchCustomFields;
+		private readonly bool mResolveReferences;
+		private readonly bool mSearchTags;
+
+		public SearchResults(int capacity, string term)
+		{
+			mTerm = term;
+			mResults = new SearchResult[capacity];
+
+			mStringComparison = Settings.Default.CaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase;
+			mStringComparison |= CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace;
+			mSearchTitle = Settings.Default.SearchTitle;
+			mSearchUserName = Settings.Default.SearchUserName;
+			mSearchUrl = Settings.Default.SearchUrl;
+			mSearchNotes = Settings.Default.SearchNotes;
+			mSearchCustomFields = Settings.Default.SearchCustomFields;
+			mSearchTags = Settings.Default.SearchTags;
+			mResolveReferences = Settings.Default.ResolveReferences;
+		}
+
+		/// 
+		/// Gets an ordered list of fields to search for the term
+		/// 
+		/// 
+		/// 
+		private IEnumerable GetFieldsToSearch(PwEntry entry)
+		{
+			var fieldsToSearch = new List((int)entry.Strings.UCount);
+			if (mSearchTitle) fieldsToSearch.Add(PwDefs.TitleField);
+			if (mSearchUserName) fieldsToSearch.Add(PwDefs.UserNameField);
+			if (mSearchUrl) fieldsToSearch.Add(PwDefs.UrlField);
+			if (mSearchNotes) fieldsToSearch.Add(PwDefs.NotesField);
+			if (mSearchCustomFields)
+			{
+				foreach (var stringEntry in entry.Strings)
+				{
+					if (!stringEntry.Value.IsProtected && !PwDefs.IsStandardField(stringEntry.Key))
+					{
+						fieldsToSearch.Add(stringEntry.Key);
+					}
+				}
+			}
+			if (mSearchTags) fieldsToSearch.Add(AutoTypeSearchExt.TagsVirtualFieldName);
+
+			return fieldsToSearch;
+		}
+
+		public void AddResultIfMatchesTerm(PwDatabase context, PwEntry entry)
+		{
+			// First try without resolving
+			var addedResult = AddResultIfMatchesTerm(context, entry, false);
+
+			if (!addedResult && mResolveReferences)
+			{
+				// Not found without resolving, so try resolving
+				AddResultIfMatchesTerm(context, entry, true);
+			}
+		}
+
+		private bool AddResultIfMatchesTerm(PwDatabase context, PwEntry entry, bool resolveReferences)
+		{
+			foreach (var fieldName in GetFieldsToSearch(entry))
+			{
+				string fieldValue;
+				if (fieldName == AutoTypeSearchExt.TagsVirtualFieldName)
+				{
+					fieldValue = StrUtil.TagsToString(entry.Tags, true);
+				}
+				else
+				{
+					fieldValue = entry.Strings.ReadSafeEx(fieldName);
+
+					if (resolveReferences)
+					{
+						fieldValue = ResolveReferences(context, entry, fieldValue);
+					}
+				}
+
+				if (!String.IsNullOrEmpty(fieldValue))
+				{
+					var foundIndex = CultureInfo.CurrentCulture.CompareInfo.IndexOf(fieldValue, mTerm, mStringComparison);
+					if (foundIndex >= 0)
+					{
+						// Found a match, create a search result and add it
+						AddResult(new SearchResult(context, entry, entry.Strings.ReadSafe(PwDefs.TitleField), fieldName, fieldValue, foundIndex, mTerm.Length));
+						return true;
+					}
+				}
+			}
+			return false;
+		}
+
+		/// 
+		/// Resolves any references in the field value and returns it. If there were no references,
+		/// returns null (to avoid duplicate searching - it is assumed that the unresolved value has already been searched)
+		/// 
+		private string ResolveReferences(PwDatabase context, PwEntry entry, string fieldValue)
+		{
+			if (fieldValue.IndexOf('{') < 0)
+			{
+				// Can't contain any references
+				return null;
+			}
+			
+			var sprContext = new SprContext(entry, context, SprCompileFlags.Deref) { ForcePlainTextPasswords = false };
+
+			var result = SprEngine.Compile(fieldValue, sprContext);
+			if (CultureInfo.CurrentCulture.CompareInfo.Compare(result,fieldValue, mStringComparison) == 0)
+			{
+				return null;
+			}
+			
+			return result;
+		}
+
+		public void AddResultIfMatchesTerm(SearchResult candidate)
+		{
+			// First see whether the existing candidate is a further match in the same place
+			var fieldValue = candidate.FieldValue;
+			if (fieldValue.Length > candidate.Start + mTerm.Length && CultureInfo.CurrentCulture.CompareInfo.Compare(fieldValue.Substring(candidate.Start, mTerm.Length), mTerm, mStringComparison) == 0)
+			{
+				// Yep, match continues, so add it.
+				AddResult(new SearchResult(candidate.Database, candidate.Entry, candidate.Title, candidate.FieldName, fieldValue, candidate.Start, mTerm.Length));
+			}
+			else
+			{
+				// Existing candidate match couldn't be extended, so search from scratch again
+				AddResultIfMatchesTerm(candidate.Database, candidate.Entry);
+			}
+		}
+
+		private void AddResult(SearchResult result)
+		{
+			lock (mLock)
+			{
+				if (mComplete)
+				{
+					throw new InvalidOperationException("Search results have been completed");
+				}
+				result.SetResultIndex(mCount);
+				mResults[mCount++] = result;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Indicates that the results are complete, and no more will be added.
+		/// 
+		public void SetComplete()
+		{
+			lock (mLock)
+			{
+				mComplete = true;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Gets all the available results so far.
+		/// 
+		/// Index to start returning from. Modified to be the first index not available yet on return.
+		/// Set to true if the results are complete, false if more results are pending but have not been returned.
+		/// 
+		public SearchResult[] GetAvailableResults(ref int index, out bool complete)
+		{
+			int count;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			if (count <= index)
+			{
+				return new SearchResult[0];
+			}
+
+			var availableResults = new SearchResult[count - index];
+			Array.Copy(mResults, index, availableResults, 0, availableResults.Length);
+			index = count;
+
+			return availableResults;
+		}
+
+		/// 
+		/// Gets all the results. Will block until complete.
+		/// 
+		/// 
+		public IEnumerable GetAllResults()
+		{
+			int count = -1;
+
+			for (var i = 0; i < mResults.Length; i++)
+			{
+				if (i > count)
+				{
+					// Reached the limit of availability so far, so see if more is available
+					do
+					{
+						bool moreAvailable, complete;
+
+						lock (mLock)
+						{
+							moreAvailable = mCount > count;
+							count = mCount;
+							complete = mComplete;
+						}
+
+						if (!moreAvailable)
+						{
+							if (complete)
+							{
+								// No more available, but the results are now complete anyway
+								yield break;
+							}
+
+							// No more available yet, not yet complete, wait until more becomes available
+							mResultsUpdated.WaitOne();
+						}
+						else
+						{
+							// More available now, so stop checking for more, continue with the loop to return them
+							break;
+						}
+					} while (true);
+
+					Debug.Assert(i <= count, "More should be available now");
+				}
+
+				yield return mResults[i];
+			}
+		}
+
+		public SearchResults CreateChildResults(string term)
+		{
+			Debug.Assert(term.StartsWith(mTerm));
+
+			int count;
+			bool complete;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			// If complete, then we know we don't need more than count. Otherwise, it can't be more than this capacity anyway
+			var childCapacity = complete ? count : mResults.Length;
+
+			return new SearchResults(childCapacity, term);
+		}
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.Designer.cs b/AutoTypeSearch/SearchWindow.Designer.cs
new file mode 100755
index 0000000..18b37d1
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.Designer.cs
@@ -0,0 +1,201 @@
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	partial class SearchWindow
+	{
+		/// 
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		#region Windows Form Designer generated code
+
+		/// 
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			this.components = new System.ComponentModel.Container();
+			this.mSearch = new System.Windows.Forms.TextBox();
+			this.mResults = new System.Windows.Forms.ListBox();
+			this.mLayout = new System.Windows.Forms.TableLayoutPanel();
+			this.mBanner = new System.Windows.Forms.PictureBox();
+			this.mInfoBanner = new System.Windows.Forms.Panel();
+			this.mInfoLabel = new System.Windows.Forms.Label();
+			this.mInfoBannerImage = new System.Windows.Forms.PictureBox();
+			this.mThrobber = new System.Windows.Forms.PictureBox();
+			this.mResultsUpdater = new System.Windows.Forms.Timer(this.components);
+			this.mNoResultsLabel = new System.Windows.Forms.Label();
+			this.mLayout.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).BeginInit();
+			this.mInfoBanner.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).BeginInit();
+			this.SuspendLayout();
+			// 
+			// mSearch
+			// 
+			this.mSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mSearch.Location = new System.Drawing.Point(1, 78);
+			this.mSearch.Margin = new System.Windows.Forms.Padding(1, 0, 1, 0);
+			this.mSearch.Name = "mSearch";
+			this.mSearch.Size = new System.Drawing.Size(521, 20);
+			this.mSearch.TabIndex = 0;
+			this.mSearch.LocationChanged += new System.EventHandler(this.mSearch_LocationChanged);
+			this.mSearch.TextChanged += new System.EventHandler(this.mSearch_TextChanged);
+			// 
+			// mResults
+			// 
+			this.mResults.BorderStyle = System.Windows.Forms.BorderStyle.None;
+			this.mResults.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mResults.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
+			this.mResults.FormattingEnabled = true;
+			this.mResults.IntegralHeight = false;
+			this.mResults.Location = new System.Drawing.Point(0, 98);
+			this.mResults.Margin = new System.Windows.Forms.Padding(0);
+			this.mResults.Name = "mResults";
+			this.mResults.Size = new System.Drawing.Size(523, 176);
+			this.mResults.TabIndex = 1;
+			this.mResults.TabStop = false;
+			this.mResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseClick);
+			this.mResults.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.mResults_DrawItem);
+			this.mResults.LocationChanged += new System.EventHandler(this.mResults_LocationChanged);
+			this.mResults.MouseEnter += new System.EventHandler(this.mResults_MouseEnter);
+			this.mResults.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseMove);
+			// 
+			// mLayout
+			// 
+			this.mLayout.ColumnCount = 1;
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+			this.mLayout.Controls.Add(this.mSearch, 0, 2);
+			this.mLayout.Controls.Add(this.mResults, 0, 3);
+			this.mLayout.Controls.Add(this.mBanner, 0, 0);
+			this.mLayout.Controls.Add(this.mInfoBanner, 0, 1);
+			this.mLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mLayout.Location = new System.Drawing.Point(0, 0);
+			this.mLayout.Name = "mLayout";
+			this.mLayout.RowCount = 4;
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.Size = new System.Drawing.Size(523, 274);
+			this.mLayout.TabIndex = 2;
+			// 
+			// mBanner
+			// 
+			this.mBanner.Dock = System.Windows.Forms.DockStyle.Top;
+			this.mBanner.Location = new System.Drawing.Point(0, 0);
+			this.mBanner.Margin = new System.Windows.Forms.Padding(0);
+			this.mBanner.Name = "mBanner";
+			this.mBanner.Size = new System.Drawing.Size(523, 60);
+			this.mBanner.TabIndex = 3;
+			this.mBanner.TabStop = false;
+			this.mBanner.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mBannerImage_MouseDown);
+			// 
+			// mInfoBanner
+			// 
+			this.mInfoBanner.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+			this.mInfoBanner.BackColor = System.Drawing.SystemColors.Info;
+			this.mInfoBanner.Controls.Add(this.mInfoLabel);
+			this.mInfoBanner.Controls.Add(this.mInfoBannerImage);
+			this.mInfoBanner.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoBanner.Location = new System.Drawing.Point(2, 61);
+			this.mInfoBanner.Margin = new System.Windows.Forms.Padding(2, 1, 1, 1);
+			this.mInfoBanner.Name = "mInfoBanner";
+			this.mInfoBanner.Size = new System.Drawing.Size(520, 16);
+			this.mInfoBanner.TabIndex = 8;
+			// 
+			// mInfoLabel
+			// 
+			this.mInfoLabel.AutoEllipsis = true;
+			this.mInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoLabel.ForeColor = System.Drawing.SystemColors.InfoText;
+			this.mInfoLabel.Location = new System.Drawing.Point(16, 0);
+			this.mInfoLabel.Name = "mInfoLabel";
+			this.mInfoLabel.Size = new System.Drawing.Size(504, 16);
+			this.mInfoLabel.TabIndex = 6;
+			this.mInfoLabel.Text = "AutoType failed to find";
+			// 
+			// mInfoBannerImage
+			// 
+			this.mInfoBannerImage.Dock = System.Windows.Forms.DockStyle.Left;
+			this.mInfoBannerImage.Image = global::AutoTypeSearch.Properties.Resources.Info;
+			this.mInfoBannerImage.Location = new System.Drawing.Point(0, 0);
+			this.mInfoBannerImage.Margin = new System.Windows.Forms.Padding(0);
+			this.mInfoBannerImage.Name = "mInfoBannerImage";
+			this.mInfoBannerImage.Size = new System.Drawing.Size(16, 16);
+			this.mInfoBannerImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mInfoBannerImage.TabIndex = 7;
+			this.mInfoBannerImage.TabStop = false;
+			// 
+			// mThrobber
+			// 
+			this.mThrobber.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.mThrobber.BackColor = System.Drawing.SystemColors.Window;
+			this.mThrobber.Location = new System.Drawing.Point(503, 81);
+			this.mThrobber.Name = "mThrobber";
+			this.mThrobber.Size = new System.Drawing.Size(16, 16);
+			this.mThrobber.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mThrobber.TabIndex = 4;
+			this.mThrobber.TabStop = false;
+			this.mThrobber.Visible = false;
+			// 
+			// mResultsUpdater
+			// 
+			this.mResultsUpdater.Interval = 250;
+			this.mResultsUpdater.Tick += new System.EventHandler(this.mResultsUpdater_Tick);
+			// 
+			// mNoResultsLabel
+			// 
+			this.mNoResultsLabel.AutoSize = true;
+			this.mNoResultsLabel.Location = new System.Drawing.Point(5, 103);
+			this.mNoResultsLabel.Name = "mNoResultsLabel";
+			this.mNoResultsLabel.Size = new System.Drawing.Size(84, 13);
+			this.mNoResultsLabel.TabIndex = 5;
+			this.mNoResultsLabel.Text = "No results found";
+			// 
+			// SearchWindow
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.BackColor = System.Drawing.SystemColors.Window;
+			this.ClientSize = new System.Drawing.Size(523, 274);
+			this.ControlBox = false;
+			this.Controls.Add(this.mNoResultsLabel);
+			this.Controls.Add(this.mThrobber);
+			this.Controls.Add(this.mLayout);
+			this.MinimumSize = new System.Drawing.Size(160, 96);
+			this.Name = "SearchWindow";
+			this.ShowInTaskbar = false;
+			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+			this.TopMost = true;
+			this.mLayout.ResumeLayout(false);
+			this.mLayout.PerformLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).EndInit();
+			this.mInfoBanner.ResumeLayout(false);
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).EndInit();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.TextBox mSearch;
+		private System.Windows.Forms.ListBox mResults;
+		private System.Windows.Forms.TableLayoutPanel mLayout;
+		private System.Windows.Forms.PictureBox mBanner;
+		private PictureBox mThrobber;
+		private Timer mResultsUpdater;
+		private Label mNoResultsLabel;
+		private Label mInfoLabel;
+		private Panel mInfoBanner;
+		private PictureBox mInfoBannerImage;
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchWindow.cs b/AutoTypeSearch/SearchWindow.cs
new file mode 100755
index 0000000..363b898
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.cs
@@ -0,0 +1,925 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Media;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Resources;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Collections;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	public partial class SearchWindow : Form
+	{
+		private const int SecondLineInset = 10;
+
+		// HACK to work around mono bug
+		private static readonly FieldInfo sMonoListBoxTopIndex = typeof(ListBox).GetField("top_index", BindingFlags.Instance | BindingFlags.NonPublic);
+
+		private readonly MainForm mMainForm;
+		private readonly Bitmap mBannerImage;
+		private readonly Searcher mSearcher;
+
+		private readonly Stream mThrobberImageStream;
+
+		private int? mWindowTopBorderHeight;
+		private int mBannerWidth = -1;
+		private int mMaximumExpandHeight;
+		private bool mManualSizeApplied;
+		private SearchResults mCurrentSearch;
+		private SearchResults mLastResultsUpdated;
+		private int mLastResultsUpdatedNextAvailableIndex;
+
+		#region Opening
+		public SearchWindow()
+		{
+			InitializeComponent();
+
+			// Mono can't load animated gifs from resx without crashing, so load it from an embedded resource instead
+			try
+			{
+				mThrobberImageStream = GetType().Assembly.GetManifestResourceStream("AutoTypeSearch.Throbber.gif");
+				if (mThrobberImageStream != null)
+				{
+					mThrobber.Image = Image.FromStream(mThrobberImageStream);
+				}
+			}
+			catch (Exception ex)
+			{
+				Debug.Fail("Failed to load Throbber.gif from embedded resource: " + ex.Message);
+			}
+
+			GlobalWindowManager.CustomizeControl(this);
+			UIUtil.SetExplorerTheme(mResults, true);
+			SetItemHeight();
+		}
+
+		public SearchWindow(MainForm mainForm, string infoBanner) : this()
+		{
+			mMainForm = mainForm;
+
+			mInfoBanner.Height = Math.Max(mInfoBannerImage.Height, mInfoLabel.Font.Height) + mInfoBanner.Margin.Vertical;
+			mInfoLabel.Padding = new Padding(0, (mInfoBanner.Height - mInfoLabel.Font.Height) / 2, 0, 0);
+			mInfoLabel.Text = infoBanner;
+
+			if (infoBanner == null)
+			{
+				mInfoBanner.Visible = false;
+				mInfoBanner.Height = 0;
+			}
+			
+			mSearcher = new Searcher(mMainForm.DocumentManager.GetOpenDatabases().ToArray());
+
+			Icon = mMainForm.Icon;
+			using (var bannerIcon = new Icon(Icon, 48, 48))
+			{
+				mBannerImage = bannerIcon.ToBitmap();
+			}
+			UpdateBanner();
+
+			ShowThrobber = false;
+
+			FontUtil.AssignDefaultItalic(mNoResultsLabel);
+		}
+
+
+		protected override void OnCreateControl()
+		{
+			base.OnCreateControl();
+
+			if (NativeMethods.IsWindows10())
+			{
+				mWindowTopBorderHeight = PointToScreen(Point.Empty).Y - this.Top;
+				NativeMethods.RefreshWindowFrame(Handle);
+			}
+
+			var windowRect = Settings.Default.WindowPosition;
+			var collapsedWindowRect = windowRect;
+			
+			collapsedWindowRect.Height = mSearch.Bottom + (Height - ClientSize.Height);
+
+			MinimumSize = new Size(MinimumSize.Width, collapsedWindowRect.Height);
+
+			if (windowRect.IsEmpty || !IsOnScreen(collapsedWindowRect))
+			{
+				windowRect = new Rectangle(0, 0, Width, Height);
+				Height = collapsedWindowRect.Height;
+
+				CenterToScreen();
+			}
+			else
+			{
+				Location = windowRect.Location;
+				Size = collapsedWindowRect.Size;
+			}
+
+			mMaximumExpandHeight = Math.Max(windowRect.Height, MinimumSize.Height + mResults.ItemHeight);
+		}
+		
+
+		private static bool IsOnScreen(Rectangle rectangle)
+		{
+			return Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(rectangle));
+		}
+
+		private void SetItemHeight()
+		{
+			mResults.ItemHeight = mResults.Font.Height * 2 + 2;
+		}
+
+		protected override void WndProc(ref Message m)
+		{
+			if (mWindowTopBorderHeight.HasValue)
+			{
+				NativeMethods.RemoveWindowFrameTopBorder(ref m, mWindowTopBorderHeight.Value);
+			}
+			base.WndProc(ref m);
+		}
+
+		#endregion
+
+		#region Closing
+		protected override void OnActivated(EventArgs e)
+		{
+			base.OnActivated(e);
+			Deactivate += OnDeactivate;
+		}
+
+		private void OnDeactivate(object sender, EventArgs eventArgs)
+		{
+			Close();
+		}
+
+		protected override void OnClosed(EventArgs e)
+		{
+			Deactivate -= OnDeactivate;
+			base.OnClosed(e);
+		}
+
+		/// 
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				if (mBannerImage != null)
+				{
+					mBannerImage.Dispose();
+				}
+				if (mThrobber.Image != null)
+				{
+					mThrobber.Image.Dispose();
+					mThrobber.Image = null;
+					mThrobberImageStream.Dispose();
+				}
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+		#endregion
+
+		#region Item Drawing
+		private void mResults_DrawItem(object sender, DrawItemEventArgs e)
+		{
+			var searchResult = mResults.Items[e.Index] as SearchResult;
+			if (searchResult == null)
+			{
+				Debug.Fail("Unexpected item in mResults");
+// ReSharper disable once HeuristicUnreachableCode - Not unreachable
+				return;
+			}
+			var drawingArea = e.Bounds;
+			drawingArea.Height--; // Leave room for a dividing line at the bottom
+			
+			if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
+			{
+				DrawBorderedRectangle(e.Graphics, drawingArea, SystemColors.Highlight);
+			}
+			else
+			{
+				e.Graphics.FillRectangle(SystemBrushes.Window, drawingArea);
+			}
+
+			var image = GetImage(searchResult.Database, searchResult.Entry.CustomIconUuid, searchResult.Entry.IconId);
+			var imageMargin = (drawingArea.Height - image.Height) / 2;
+			e.Graphics.DrawImage(image, drawingArea.Left + imageMargin, drawingArea.Top + imageMargin, image.Width, image.Height);
+
+			var textLeftMargin = drawingArea.Left + imageMargin * 2 + image.Width;
+			var textBounds = new Rectangle(textLeftMargin, drawingArea.Top + 1, drawingArea.Width - textLeftMargin - 1, drawingArea.Height - 2);
+
+			var line1Bounds = textBounds;
+			line1Bounds.Height = e.Font.Height;
+			var line2Bounds = line1Bounds;
+			line2Bounds.Y += line2Bounds.Height - 1;
+			line2Bounds.X += SecondLineInset;
+			line2Bounds.Width -= SecondLineInset;
+
+			var resultInTitleField = searchResult.FieldName == PwDefs.TitleField;
+
+			var title = (resultInTitleField ? searchResult.FieldValue : searchResult.Title).Replace('\n', ' '); // The FieldValue may have references resolved, whereas the title is always read directly.
+
+			var uniqueTitlePartWidth = 0;
+			if (!String.IsNullOrEmpty(searchResult.UniqueTitlePart))
+			{
+				var uniqueTitlePart = searchResult.UniqueTitlePart.Replace('\n', ' ');
+
+				var titleWidth = TextRenderer.MeasureText(e.Graphics, title, e.Font, line1Bounds.Size, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+
+				var availableWidthForUniqueTitlePart = line1Bounds.Width - titleWidth;
+				if (availableWidthForUniqueTitlePart > 20) // Don't bother including a unique part if there's no room for it
+				{
+					var uniqueTitlePartReversed = ReverseString(uniqueTitlePart);
+
+					uniqueTitlePartWidth = TextRenderer.MeasureText(e.Graphics, uniqueTitlePartReversed, e.Font, new Size(availableWidthForUniqueTitlePart, line1Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+					uniqueTitlePart = ReverseString(uniqueTitlePartReversed);
+
+					TextRenderer.DrawText(e.Graphics, uniqueTitlePart, e.Font, new Rectangle(line1Bounds.X, line1Bounds.Y, uniqueTitlePartWidth, line1Bounds.Height), SystemColors.GrayText, TextFormatFlags.NoPadding);
+				}
+			}
+
+			var titleBounds = new Rectangle(line1Bounds.X + uniqueTitlePartWidth, line1Bounds.Y, line1Bounds.Width - uniqueTitlePartWidth, line1Bounds.Height);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Highlight title in first line.
+				DrawHighlight(e, titleBounds, title, searchResult.Start, searchResult.Length);
+			}
+
+			TextRenderer.DrawText(e.Graphics, searchResult.Title, e.Font, titleBounds, SystemColors.WindowText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Use Username for second line.
+				TextRenderer.DrawText(e.Graphics, KPRes.UserName + ": " + searchResult.Entry.Strings.ReadSafeEx(PwDefs.UserNameField), e.Font, line2Bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+			}
+			else
+			{
+				// Found the result in not title field. Show the matching result on second line
+				
+				var fieldValue = searchResult.FieldValue.Replace('\n',' ');
+				var fieldNamePrefix = GetDisplayFieldName(searchResult.FieldName) + ": ";
+
+				var remainingSpace = line2Bounds.Width;
+				var fieldNamePrefixWidth = TextRenderer.MeasureText(e.Graphics, fieldNamePrefix, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+				remainingSpace -= fieldNamePrefixWidth;
+
+				int fieldValueHighlightWidth = 0, fieldValueLeftContextWidth = 0, fieldValueRightContextWidth = 0;
+
+				var leftContext = fieldValue.Substring(0, searchResult.Start);
+				var highlight = fieldValue.Substring(searchResult.Start, searchResult.Length);
+				var rightContext = fieldValue.Substring(searchResult.Start + searchResult.Length);
+
+				if (searchResult.Length == 0)
+				{
+					fieldValueHighlightWidth = remainingSpace;
+				}
+				else
+				{
+					if (remainingSpace > 0)
+					{
+						var availableSpace = remainingSpace;
+						fieldValueHighlightWidth = TextRenderer.MeasureText(e.Graphics, highlight, e.Font, new Size(availableSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						remainingSpace -= fieldValueHighlightWidth;
+					}
+
+					// Of the space remaining, divide it equally between that which comes before, and that which comes after
+					if (!String.IsNullOrEmpty(leftContext))
+					{
+						var leftContextReversed = ReverseString(leftContext);
+						fieldValueLeftContextWidth = TextRenderer.MeasureText(e.Graphics, leftContextReversed, e.Font, new Size(remainingSpace / 2, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+						if (fieldValueLeftContextWidth > remainingSpace)
+						{
+							// Always allow space for the minimal left context
+							fieldValueHighlightWidth -= (fieldValueLeftContextWidth - remainingSpace);
+							remainingSpace = 0;
+						}
+						else
+						{
+							remainingSpace -= fieldValueLeftContextWidth;							
+						}
+						
+						// Replace left context with the truncated reversed left context.
+						leftContext = ReverseString(leftContextReversed);
+					}
+
+					if (remainingSpace > 0 && !String.IsNullOrEmpty(rightContext))
+					{
+						fieldValueRightContextWidth = TextRenderer.MeasureText(e.Graphics, rightContext, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						if (fieldValueRightContextWidth > remainingSpace)
+						{
+							fieldValueRightContextWidth = 0;
+						}
+					}
+				}
+
+				// Now draw it all
+				var bounds = line2Bounds;
+				bounds.Width = fieldNamePrefixWidth;
+				TextRenderer.DrawText(e.Graphics, fieldNamePrefix, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				if (fieldValueLeftContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueLeftContextWidth;
+					TextRenderer.DrawText(e.Graphics, leftContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding); // No ellipsis as the leftContext string has already been truncated appropriately
+				}
+				if (fieldValueHighlightWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueHighlightWidth;
+
+					if (searchResult.Length > 0)
+					{
+						DrawHighlightRectangle(e, bounds);
+					}
+					TextRenderer.DrawText(e.Graphics, highlight, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+				if (fieldValueRightContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueRightContextWidth;
+					TextRenderer.DrawText(e.Graphics, rightContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+			}
+
+			e.Graphics.DrawLine(SystemPens.ButtonFace, drawingArea.Left, drawingArea.Bottom, drawingArea.Right, drawingArea.Bottom);
+		}
+
+		private static string ReverseString(string value)
+		{
+			return new String(value.ToCharArray().TakeWhile(c => c != '\0').Reverse().ToArray());
+		}
+
+		private static void DrawHighlight(DrawItemEventArgs e, Rectangle lineBounds, string text, int highlightFrom, int highlightLength)
+		{
+			var highlightX = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width;
+			var highlightWidth = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom + highlightLength), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width - highlightX;
+
+			DrawHighlightRectangle(e, new Rectangle(lineBounds.Left + highlightX, lineBounds.Top, highlightWidth, lineBounds.Height));
+		}
+
+		private static void DrawHighlightRectangle(DrawItemEventArgs e, Rectangle rectangle)
+		{
+			DrawBorderedRectangle(e.Graphics, rectangle, Color.PaleTurquoise);
+		}
+
+		private static void DrawBorderedRectangle(Graphics graphics, Rectangle rectangle, Color colour)
+		{
+			var border = rectangle;
+			border.Width--;
+			border.Height--;
+
+			using (var brush = new SolidBrush(MergeColors(colour, SystemColors.Window, 0.2)))
+			{
+				graphics.FillRectangle(brush, rectangle);
+			}
+			using (var pen = new Pen(colour, 1f))
+			{
+				graphics.DrawRectangle(pen, border);
+			}
+		}
+
+		private Image GetImage(PwDatabase database, PwUuid customIconId, PwIcon iconId)
+		{
+			Image image = null;
+			if (!customIconId.Equals(PwUuid.Zero))
+			{
+				image = database.GetCustomIcon(customIconId, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16));
+			}
+			if (image == null)
+			{
+				try { image = mMainForm.ClientIcons.Images[(int)iconId]; }
+				catch (Exception) { Debug.Assert(false); }
+			}
+
+			return image;
+		}
+
+		private static string GetDisplayFieldName(string fieldName)
+		{
+			switch (fieldName)
+			{
+				case PwDefs.TitleField:
+					return KPRes.Title;
+				case PwDefs.UserNameField:
+					return KPRes.UserName;
+				case PwDefs.PasswordField:
+					return KPRes.Password;
+				case PwDefs.UrlField:
+					return KPRes.Url;
+				case PwDefs.NotesField:
+					return KPRes.Notes;
+				case AutoTypeSearchExt.TagsVirtualFieldName:
+					return KPRes.Tags;
+				default:
+					return fieldName;
+			}
+		}
+
+		public static Color MergeColors(Color from, Color to, double amount)
+		{
+			var r = (byte)((from.R * amount) + to.R * (1 - amount));
+			var g = (byte)((from.G * amount) + to.G * (1 - amount));
+			var b = (byte)((from.B * amount) + to.B * (1 - amount));
+			return Color.FromArgb(r, g, b);
+		}
+		#endregion
+
+		#region Mouse tracking
+		private Point mMouseEntryPosition;
+		
+		private void mResults_MouseEnter(object sender, EventArgs e)
+		{
+			mMouseEntryPosition = MousePosition;
+		}
+
+		private void mResults_MouseMove(object sender, MouseEventArgs e)
+		{
+			// Discard the location the mouse has on entering the control (as it may be that the control has just moved under the mouse, not the other way around)
+			if (MousePosition == mMouseEntryPosition)
+			{
+				return;
+			}
+
+			// Hot tracking
+			var hoverIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (hoverIndex >= 0 && mResults.SelectedIndex != hoverIndex)
+			{
+				if (mResults.GetItemRectangle(hoverIndex).Bottom <= mResults.ClientRectangle.Bottom)
+				{
+					mResults.SelectedIndex = hoverIndex;
+				}
+				else
+				{
+					// Avoid the control scrolling
+					mResults.BeginUpdate();
+					var topIndex = mResults.TopIndex;
+					mResults.SelectedIndex = hoverIndex;
+					mResults.TopIndex = topIndex;
+					mResults.EndUpdate();
+				}
+			}
+		}
+		#endregion
+
+		#region Resizing
+		protected override void OnResizeBegin(EventArgs e)
+		{
+			// Stop automatically sizing - the user is picking a size they want.
+			mManualSizeApplied = true;
+			base.OnResizeBegin(e);
+		}
+
+		protected override void OnResize(EventArgs e)
+		{
+			base.OnResize(e);
+
+			UpdateBanner();
+
+			mResults.Invalidate();
+		}
+
+		protected override void OnResizeEnd(EventArgs e)
+		{
+			base.OnResizeEnd(e);
+
+			if (Height > MinimumSize.Height && Height != mMaximumExpandHeight)
+			{
+				mMaximumExpandHeight = Math.Max(Height, MinimumSize.Height + mResults.ItemHeight);
+			}
+			else
+			{
+				mManualSizeApplied = false;
+			}
+
+			Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+		}
+
+		private void UpdateBanner()
+		{
+			if (mBannerImage != null)
+			{
+				BannerFactory.UpdateBanner(this, mBanner, mBannerImage, PwDefs.ProductName, Resources.BannerText, ref mBannerWidth);
+			}
+		}
+
+		private void mSearch_LocationChanged(object sender, EventArgs e)
+		{
+			mThrobber.Location = new Point(mSearch.Right - mThrobber.Width - mThrobber.Margin.Right, mSearch.Top + (mSearch.Height - mThrobber.Height) / 2);
+		}
+
+		private void mResults_LocationChanged(object sender, EventArgs e)
+		{
+			mNoResultsLabel.Top = mResults.Top + (mResults.ItemHeight - mNoResultsLabel.Height) / 2;
+		}
+		#endregion
+
+		#region Searching
+		private static readonly SearchResultPrecedence SearchResultPrecedenceComparer = new SearchResultPrecedence();
+		private void mSearch_TextChanged(object sender, EventArgs e)
+		{
+			if (mSearch.Text.Length < 2)
+			{
+				// Stop searching
+				mResultsUpdater.Enabled = false;
+				ShowThrobber = false;
+				Height = MinimumSize.Height;
+				mManualSizeApplied = false;
+				mResults.Items.Clear();
+				mLastResultsUpdated = null;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			else
+			{
+				// Start searching
+				mNoResultsLabel.Visible = false;
+				mCurrentSearch = mSearcher.Search(mSearch.Text);
+				mResultsUpdater.Enabled = true;
+				ShowThrobber = true;
+				mResultsUpdater_Tick(null, EventArgs.Empty); // Quick poke just in case the results are already done.
+			}
+		}
+
+		[SuppressMessage("ReSharper", "CoVariantArrayConversion", Justification = "Object arrays for Listbox.Items, known to be of correct type")]
+		private void mResultsUpdater_Tick(object sender, EventArgs e)
+		{
+			if (mLastResultsUpdated != mCurrentSearch)
+			{
+				// Clear out old results and replace with new ones
+				mResults.Items.Clear();
+				mLastResultsUpdated = mCurrentSearch;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			var existingResultsCount = mResults.Items.Count;
+			
+			bool complete;
+			var newResults = mLastResultsUpdated.GetAvailableResults(ref mLastResultsUpdatedNextAvailableIndex, out complete);
+			if (newResults.Length > 0)
+			{
+				mResults.BeginUpdate();
+				
+				SearchResult[] allResults;
+				if (existingResultsCount > 0)
+				{
+					allResults = new SearchResult[existingResultsCount + newResults.Length];
+					mResults.Items.CopyTo(allResults, 0);
+					newResults.CopyTo(allResults, existingResultsCount);
+
+					mResults.Items.Clear();
+				}
+				else
+				{
+					allResults = newResults;
+				}
+
+				CalculateUniqueTitles(allResults);
+
+				Array.Sort(allResults, SearchResultPrecedenceComparer);
+				mResults.Items.AddRange(allResults);
+				
+				mResults.EndUpdate();
+
+				if (allResults.Length > 0)
+				{
+					if (mResults.SelectedIndex == -1)
+					{
+						try
+						{
+							// HACK to work around mono bug
+							if (sMonoListBoxTopIndex != null)
+							{
+								sMonoListBoxTopIndex.SetValue(mResults, 1); // Set the top_index to 1 so that when selected index is set to 0, and calls EnsureVisible(0), it follows the index < top_index pass and not the broken index >= top_index + rows path. 
+							}
+
+							mResults.SelectedIndex = 0;
+							mResults.TopIndex = 0;
+						}
+						catch (Exception ex)
+						{
+							Debug.Fail("Failed to set selection on count of " + allResults.Length + ": " + ex.Message);
+						}
+					}
+
+					if (!mManualSizeApplied)
+					{
+						Height = Math.Min(mMaximumExpandHeight, MinimumSize.Height + (allResults.Length * mResults.ItemHeight));
+					}
+				}
+			}
+
+			if (complete)
+			{
+				ShowThrobber = false;
+				mResultsUpdater.Enabled = false;
+
+				if (mResults.Items.Count == 0)
+				{
+					mNoResultsLabel.Visible = true;
+					Height = MinimumSize.Height + mResults.ItemHeight;
+					mManualSizeApplied = false;
+				}
+			}
+		}
+
+		private void CalculateUniqueTitles(IEnumerable results, int depth = 0)
+		{
+			// Where results have identical titles, include group titles to make them unique
+			depth += 1;
+
+			// First create a lookup by title
+			var titles = new Dictionary>();
+			foreach (var searchResult in results)
+			{
+				List resultsWithSameTitle;
+				if (titles.TryGetValue(searchResult.UniqueTitle, out resultsWithSameTitle))
+				{
+					resultsWithSameTitle.Add(searchResult);
+				}
+				else
+				{
+					titles.Add(searchResult.UniqueTitle, new List { searchResult });
+				}
+			}
+
+			// Attempt to unique-ify any non-unique titles
+			foreach (var resultsSharingTitle in titles.Values)
+			{
+				if (resultsSharingTitle.Count > 1)
+				{
+					var titlesModified = false;
+					foreach (var searchResult in resultsSharingTitle)
+					{
+						titlesModified |= searchResult.SetUniqueTitleDepth(depth);
+					}
+
+					if (titlesModified)
+					{
+						// Recurse in case of continuing non-uniqueness
+						CalculateUniqueTitles(resultsSharingTitle, depth);
+					}
+				}
+			}
+		}
+
+		private class SearchResultPrecedence : IComparer
+		{
+			public int Compare(SearchResult x, SearchResult y)
+			{
+				// First precedence is that if the result is the start of the field value, it's higher precedence than if it doesn't.
+				var result = -(x.Start == 0).CompareTo(y.Start == 0);
+
+				// Second precedence is that the start of the title field is higher precedence than the start of any other field
+				if (result == 0)
+				{
+					result = -(x.FieldName == PwDefs.TitleField).CompareTo(y.FieldName == PwDefs.TitleField);
+				}
+
+				// Both start the title field, so both equal. Have to have consistent ordering, so return final precedence based search index
+				if (result == 0)
+				{
+					result = x.ResultIndex.CompareTo(y.ResultIndex);
+				}
+				
+				return result;
+			}
+		}
+
+		private bool ShowThrobber
+		{
+			get { return mThrobber.Visible; }
+			set
+			{
+				if (value != ShowThrobber)
+				{
+					if (value)
+					{
+						mThrobber.Visible = true;
+
+						// Set the margin on the textbox to allow room for the throbber
+						NativeMethods.SetTextBoxRightMargin(mSearch, mThrobber.Width + mThrobber.Margin.Right);
+					}
+					else
+					{
+						mThrobber.Visible = false;
+
+						NativeMethods.SetTextBoxRightMargin(mSearch, 0);
+					}
+				}
+			}
+		}
+		#endregion
+
+		private void mBannerImage_MouseDown(object sender, MouseEventArgs e)
+		{
+			// Allow drag by banner image
+			if (e.Button == MouseButtons.Left)
+			{
+				if (e.Clicks == 2)
+				{
+					// Re-center the form on double-click
+					CenterToScreen();
+
+					Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+				}
+				else if (!NativeLib.IsUnix())
+				{
+					NativeMethods.StartFormDrag(this);
+				}
+			}
+		}
+
+		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+		{
+			switch (keyData)
+			{
+				case Keys.Escape:
+					Close();
+					return true;
+				case Keys.Up:
+					TryChangeSelection(-1);
+					return true;
+				case Keys.Down:
+					TryChangeSelection(1);
+					return true;
+				case Keys.PageUp:
+					TryChangeSelection(-mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.PageDown:
+					TryChangeSelection(mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.Home | Keys.Control:
+					mResults.SelectedIndex = 0;
+					return true;
+				case Keys.End | Keys.Control:
+					mResults.SelectedIndex = mResults.Items.Count - 1;
+					return true;
+				case Keys.Enter:
+					PerformAction(Settings.Default.DefaultAction, mResults.SelectedItem as SearchResult);
+					break;
+				case Keys.Enter | Keys.Shift:
+					PerformAction(Settings.Default.AlternativeAction, mResults.SelectedItem as SearchResult);
+					break;
+			}
+			
+			return base.ProcessCmdKey(ref msg, keyData);
+		}
+
+		#region Selection Changing
+
+		protected override void OnMouseWheel(MouseEventArgs e)
+		{
+			mResults.TopIndex -= (e.Delta / Math.Abs(e.Delta));
+		}
+
+		private void TryChangeSelection(int delta)
+		{
+			if (mResults.Items.Count > 0)
+			{
+				mResults.SelectedIndex = Math.Max(Math.Min(mResults.Items.Count - 1, mResults.SelectedIndex + delta), 0);
+			}
+		}
+		#endregion
+
+		#region Actions
+
+		private void mResults_MouseClick(object sender, MouseEventArgs e)
+		{
+			var clickIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (clickIndex >= 0)
+			{
+				var clickedResult = mResults.Items[clickIndex] as SearchResult;
+				if (clickedResult != null)
+				{
+					PerformAction((ModifierKeys & Keys.Shift) == Keys.Shift ? Settings.Default.AlternativeAction : Settings.Default.DefaultAction, clickedResult);
+				}
+			}
+		}
+
+		private void PerformAction(Actions action, SearchResult searchResult)
+		{
+			Close();
+
+			if (searchResult != null)
+			{
+				switch (action)
+				{
+					case Actions.PerformAutoType:
+						AutoTypeEntry(searchResult);
+						break;
+					case Actions.EditEntry:
+						EditEntry(searchResult);
+						break;
+					case Actions.ShowEntry:
+						ShowEntry(searchResult);
+						break;
+					case Actions.OpenEntryUrl:
+						OpenEntryUrl(searchResult);
+						break;
+					case Actions.CopyPassword:
+						CopyPassword(searchResult);
+						break;
+					default:
+						throw new ArgumentOutOfRangeException("action");
+				}
+			}
+		}
+
+		private void AutoTypeEntry(SearchResult searchResult)
+		{
+			bool result;
+			if (ActiveForm != null)
+			{
+				result = AutoType.PerformIntoPreviousWindow(mMainForm, searchResult.Entry, searchResult.Database);
+			}
+			else
+			{
+				result = AutoType.PerformIntoCurrentWindow(searchResult.Entry, searchResult.Database);
+			}
+			if (!result)
+			{
+				SystemSounds.Beep.Play();
+
+				if (Settings.Default.AlternativeAction != Actions.PerformAutoType)
+				{
+					PerformAction(Settings.Default.AlternativeAction, searchResult);
+				}
+			}
+		}
+
+		private void EditEntry(SearchResult searchResult)
+		{
+			using (var entryForm = new PwEntryForm())
+			{
+				mMainForm.MakeDocumentActive(mMainForm.DocumentManager.FindDocument(searchResult.Database));
+				
+				entryForm.InitEx(searchResult.Entry, PwEditMode.EditExistingEntry, searchResult.Database, mMainForm.ClientIcons, false, false);
+
+				ShowForegroundDialog(entryForm);
+
+				mMainForm.UpdateUI(false, null, searchResult.Database.UINeedsIconUpdate, null, true, null, entryForm.HasModifiedEntry);
+			}
+		}
+
+// ReSharper disable once UnusedMethodReturnValue.Local - Generic helper, result may be used in future
+		private DialogResult ShowForegroundDialog(Form form)
+		{
+			mMainForm.EnsureVisibleForegroundWindow(false, false);
+			form.StartPosition = FormStartPosition.CenterScreen;
+			if (mMainForm.IsTrayed())
+			{
+				form.ShowInTaskbar = true;
+			}
+
+			form.Shown += ActivateFormOnShown;
+			return form.ShowDialog(mMainForm);
+		}
+
+		private static void ActivateFormOnShown(object sender, EventArgs eventArgs)
+		{
+			var form = (Form)sender;
+			form.Shown -= ActivateFormOnShown;
+			form.Activate();
+		}
+
+		private void ShowEntry(SearchResult searchResult)
+		{
+			// Show this entry
+			mMainForm.UpdateUI(false, mMainForm.DocumentManager.FindDocument(searchResult.Database), true, searchResult.Entry.ParentGroup, true, null, false, null);
+			mMainForm.SelectEntries(new PwObjectList { searchResult.Entry }, true, true);
+			mMainForm.EnsureVisibleEntry(searchResult.Entry.Uuid);
+			mMainForm.UpdateUI(false, null, false, null, false, null, false);
+			mMainForm.EnsureVisibleForegroundWindow(true, true);
+		}
+
+		private void OpenEntryUrl(SearchResult searchResult)
+		{
+			WinUtil.OpenEntryUrl(searchResult.Entry);
+		}
+
+		private void CopyPassword(SearchResult searchResult)
+		{
+			if (ClipboardUtil.Copy(searchResult.Entry.Strings.ReadSafe(PwDefs.PasswordField), true, true, searchResult.Entry,
+									mMainForm.DocumentManager.SafeFindContainerOf(searchResult.Entry),
+									IntPtr.Zero))
+			{
+				mMainForm.StartClipboardCountdown();
+			}
+		}
+		
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.resx b/AutoTypeSearch/SearchWindow.resx
new file mode 100755
index 0000000..8ef82f0
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.resx
@@ -0,0 +1,123 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    17, 17
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Searcher.cs b/AutoTypeSearch/Searcher.cs
new file mode 100755
index 0000000..433ae94
--- /dev/null
+++ b/AutoTypeSearch/Searcher.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class Searcher
+	{
+		private readonly PwDatabase[] mDatabases;
+		private readonly Dictionary mSearches = new Dictionary();
+
+		public Searcher(PwDatabase[] databases)
+		{
+			mDatabases = databases;
+		}
+
+		public SearchResults Search(string term)
+		{
+			if (term.Length < 2)
+			{
+				throw new ArgumentException("Search term must be at least 2 characters");
+			}
+
+			SearchResults parentResults = null;
+
+			var termParent = term;
+			while (termParent.Length >= 2)
+			{
+				if (mSearches.TryGetValue(termParent, out parentResults))
+				{
+					if (termParent == term)
+					{
+						// This is an exact duplicate search, so return it.
+						return parentResults;
+					}
+
+					// Found an existing search for a parent of the term, start from there.
+					break;
+				}
+		
+				// No existing search for termParent found, try less.
+				termParent = termParent.Remove(termParent.Length - 1, 1);
+			}
+
+			SearchResults searchResults;
+			if (parentResults == null)
+			{
+				// No parent found at all, start from scratch
+				searchResults = new SearchResults(GetCountOfAllDatabaseEntries(), term);
+
+				var rootSearchThread = new Thread(RootSearchWorker) { Name = term };
+				rootSearchThread.Start(searchResults);
+			}
+			else
+			{
+				searchResults = parentResults.CreateChildResults(term);
+
+				var childSearchThread = new Thread(ChildSearchWorker) { Name = term };
+				childSearchThread.Start(new ChildSearchWorkerState{ Source = parentResults, Results = searchResults });
+			}
+
+			mSearches.Add(term, searchResults);
+
+			return searchResults;
+		}
+
+		private int GetCountOfAllDatabaseEntries()
+		{
+			return (from database in mDatabases select (int)database.RootGroup.GetEntriesCount(true)).Sum();
+		}
+
+		private void RootSearchWorker(object stateObject)
+		{
+			var results = (SearchResults)stateObject;
+			var excludeExpired = Settings.Default.ExcludeExpired;
+			var searchStartTime = DateTime.Now;
+
+			foreach (var database in mDatabases)
+			{
+				SearchGroup(database, database.RootGroup, results, excludeExpired, searchStartTime);	
+			}
+
+			results.SetComplete();
+		}
+
+		/// 
+		/// Recursively search  and its children, adding results to 
+		/// 
+		private void SearchGroup(PwDatabase context, PwGroup group, SearchResults results, bool excludeExpired, DateTime searchStartTime)
+		{
+			if (group.EnableSearching ?? true) // Group will only be searched if it's parent enabled searching, so if it is inherit (null) or true, search it.
+			{
+				foreach (var childGroup in group.Groups)
+				{
+					SearchGroup(context, childGroup, results, excludeExpired, searchStartTime);
+				}
+
+				foreach (var entry in group.Entries)
+				{
+					if (!(excludeExpired && entry.Expires && searchStartTime > entry.ExpiryTime))
+					{
+						results.AddResultIfMatchesTerm(context, entry);
+					}
+				}
+			}
+		}
+
+		private struct ChildSearchWorkerState
+		{
+			public SearchResults Source;
+			public SearchResults Results;
+		}
+		private void ChildSearchWorker(object stateObject)
+		{
+			var state = (ChildSearchWorkerState)stateObject;
+
+			bool complete;
+			var index = 0;
+			do
+			{
+				foreach (var entry in state.Source.GetAvailableResults(ref index, out complete))
+				{
+					state.Results.AddResultIfMatchesTerm(entry);
+				}
+			} while (!complete);
+
+			state.Results.SetComplete();
+		}
+	}
+}
diff --git a/AutoTypeSearch/Throbber.gif b/AutoTypeSearch/Throbber.gif
new file mode 100755
index 0000000..494d426
--- /dev/null
+++ b/AutoTypeSearch/Throbber.gif
Binary files differ
diff --git a/AutoTypeSearch/app.config b/AutoTypeSearch/app.config
new file mode 100755
index 0000000..1370758
--- /dev/null
+++ b/AutoTypeSearch/app.config
@@ -0,0 +1,60 @@
+
+
+    
+        
+            
+        
+    
+    
+        
+            
+                True
+            
+            
+                False
+            
+            
+                True
+            
+            
+                True
+            
+            
+                True
+            
+            
+                True
+            
+            
+                False
+            
+            
+                0, 0, 0, 0
+            
+            
+                True
+            
+            
+                False
+            
+            
+                True
+            
+            
+                False
+            
+            
+                False
+            
+            
+                PerformAutoType
+            
+            
+                EditEntry
+            
+            
+                None
+            
+        
+    
+
\ No newline at end of file
diff --git a/CreatePlgX.bat b/CreatePlgX.bat
new file mode 100755
index 0000000..59b9aa0
--- /dev/null
+++ b/CreatePlgX.bat
@@ -0,0 +1,20 @@
+@echo off
+cd %~dp0
+
+echo Deleting existing PlgX folder
+rmdir /s /q PlgX
+
+echo Creating PlgX folder
+mkdir PlgX
+
+echo Copying files
+xcopy "AutoTypeSearch" PlgX /s /e /exclude:PlgXExclude.txt
+
+echo Compiling PlgX
+"../KeePass/KeePass.exe" /plgx-create "%~dp0PlgX" --plgx-prereq-kp:2.27
+
+echo Releasing PlgX
+move /y PlgX.plgx "Releases\Build Outputs\AutoTypeSearch.plgx"
+
+echo Cleaning up
+rmdir /s /q PlgX
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/AutoTypeSearch/SearchResults.cs b/AutoTypeSearch/SearchResults.cs
new file mode 100755
index 0000000..b2b0529
--- /dev/null
+++ b/AutoTypeSearch/SearchResults.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePass.Util.Spr;
+using KeePassLib;
+using KeePassLib.Utility;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResults
+	{
+		private readonly string mTerm;
+		private readonly SearchResult[] mResults;
+
+		private readonly object mLock = new object();
+		private volatile int mCount;
+		private volatile bool mComplete;
+
+		private readonly AutoResetEvent mResultsUpdated = new AutoResetEvent(false);
+
+		private readonly CompareOptions mStringComparison;
+		private readonly bool mSearchTitle;
+		private readonly bool mSearchUserName;
+		private readonly bool mSearchUrl;
+		private readonly bool mSearchNotes;
+		private readonly bool mSearchCustomFields;
+		private readonly bool mResolveReferences;
+		private readonly bool mSearchTags;
+
+		public SearchResults(int capacity, string term)
+		{
+			mTerm = term;
+			mResults = new SearchResult[capacity];
+
+			mStringComparison = Settings.Default.CaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase;
+			mStringComparison |= CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace;
+			mSearchTitle = Settings.Default.SearchTitle;
+			mSearchUserName = Settings.Default.SearchUserName;
+			mSearchUrl = Settings.Default.SearchUrl;
+			mSearchNotes = Settings.Default.SearchNotes;
+			mSearchCustomFields = Settings.Default.SearchCustomFields;
+			mSearchTags = Settings.Default.SearchTags;
+			mResolveReferences = Settings.Default.ResolveReferences;
+		}
+
+		/// 
+		/// Gets an ordered list of fields to search for the term
+		/// 
+		/// 
+		/// 
+		private IEnumerable GetFieldsToSearch(PwEntry entry)
+		{
+			var fieldsToSearch = new List((int)entry.Strings.UCount);
+			if (mSearchTitle) fieldsToSearch.Add(PwDefs.TitleField);
+			if (mSearchUserName) fieldsToSearch.Add(PwDefs.UserNameField);
+			if (mSearchUrl) fieldsToSearch.Add(PwDefs.UrlField);
+			if (mSearchNotes) fieldsToSearch.Add(PwDefs.NotesField);
+			if (mSearchCustomFields)
+			{
+				foreach (var stringEntry in entry.Strings)
+				{
+					if (!stringEntry.Value.IsProtected && !PwDefs.IsStandardField(stringEntry.Key))
+					{
+						fieldsToSearch.Add(stringEntry.Key);
+					}
+				}
+			}
+			if (mSearchTags) fieldsToSearch.Add(AutoTypeSearchExt.TagsVirtualFieldName);
+
+			return fieldsToSearch;
+		}
+
+		public void AddResultIfMatchesTerm(PwDatabase context, PwEntry entry)
+		{
+			// First try without resolving
+			var addedResult = AddResultIfMatchesTerm(context, entry, false);
+
+			if (!addedResult && mResolveReferences)
+			{
+				// Not found without resolving, so try resolving
+				AddResultIfMatchesTerm(context, entry, true);
+			}
+		}
+
+		private bool AddResultIfMatchesTerm(PwDatabase context, PwEntry entry, bool resolveReferences)
+		{
+			foreach (var fieldName in GetFieldsToSearch(entry))
+			{
+				string fieldValue;
+				if (fieldName == AutoTypeSearchExt.TagsVirtualFieldName)
+				{
+					fieldValue = StrUtil.TagsToString(entry.Tags, true);
+				}
+				else
+				{
+					fieldValue = entry.Strings.ReadSafeEx(fieldName);
+
+					if (resolveReferences)
+					{
+						fieldValue = ResolveReferences(context, entry, fieldValue);
+					}
+				}
+
+				if (!String.IsNullOrEmpty(fieldValue))
+				{
+					var foundIndex = CultureInfo.CurrentCulture.CompareInfo.IndexOf(fieldValue, mTerm, mStringComparison);
+					if (foundIndex >= 0)
+					{
+						// Found a match, create a search result and add it
+						AddResult(new SearchResult(context, entry, entry.Strings.ReadSafe(PwDefs.TitleField), fieldName, fieldValue, foundIndex, mTerm.Length));
+						return true;
+					}
+				}
+			}
+			return false;
+		}
+
+		/// 
+		/// Resolves any references in the field value and returns it. If there were no references,
+		/// returns null (to avoid duplicate searching - it is assumed that the unresolved value has already been searched)
+		/// 
+		private string ResolveReferences(PwDatabase context, PwEntry entry, string fieldValue)
+		{
+			if (fieldValue.IndexOf('{') < 0)
+			{
+				// Can't contain any references
+				return null;
+			}
+			
+			var sprContext = new SprContext(entry, context, SprCompileFlags.Deref) { ForcePlainTextPasswords = false };
+
+			var result = SprEngine.Compile(fieldValue, sprContext);
+			if (CultureInfo.CurrentCulture.CompareInfo.Compare(result,fieldValue, mStringComparison) == 0)
+			{
+				return null;
+			}
+			
+			return result;
+		}
+
+		public void AddResultIfMatchesTerm(SearchResult candidate)
+		{
+			// First see whether the existing candidate is a further match in the same place
+			var fieldValue = candidate.FieldValue;
+			if (fieldValue.Length > candidate.Start + mTerm.Length && CultureInfo.CurrentCulture.CompareInfo.Compare(fieldValue.Substring(candidate.Start, mTerm.Length), mTerm, mStringComparison) == 0)
+			{
+				// Yep, match continues, so add it.
+				AddResult(new SearchResult(candidate.Database, candidate.Entry, candidate.Title, candidate.FieldName, fieldValue, candidate.Start, mTerm.Length));
+			}
+			else
+			{
+				// Existing candidate match couldn't be extended, so search from scratch again
+				AddResultIfMatchesTerm(candidate.Database, candidate.Entry);
+			}
+		}
+
+		private void AddResult(SearchResult result)
+		{
+			lock (mLock)
+			{
+				if (mComplete)
+				{
+					throw new InvalidOperationException("Search results have been completed");
+				}
+				result.SetResultIndex(mCount);
+				mResults[mCount++] = result;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Indicates that the results are complete, and no more will be added.
+		/// 
+		public void SetComplete()
+		{
+			lock (mLock)
+			{
+				mComplete = true;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Gets all the available results so far.
+		/// 
+		/// Index to start returning from. Modified to be the first index not available yet on return.
+		/// Set to true if the results are complete, false if more results are pending but have not been returned.
+		/// 
+		public SearchResult[] GetAvailableResults(ref int index, out bool complete)
+		{
+			int count;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			if (count <= index)
+			{
+				return new SearchResult[0];
+			}
+
+			var availableResults = new SearchResult[count - index];
+			Array.Copy(mResults, index, availableResults, 0, availableResults.Length);
+			index = count;
+
+			return availableResults;
+		}
+
+		/// 
+		/// Gets all the results. Will block until complete.
+		/// 
+		/// 
+		public IEnumerable GetAllResults()
+		{
+			int count = -1;
+
+			for (var i = 0; i < mResults.Length; i++)
+			{
+				if (i > count)
+				{
+					// Reached the limit of availability so far, so see if more is available
+					do
+					{
+						bool moreAvailable, complete;
+
+						lock (mLock)
+						{
+							moreAvailable = mCount > count;
+							count = mCount;
+							complete = mComplete;
+						}
+
+						if (!moreAvailable)
+						{
+							if (complete)
+							{
+								// No more available, but the results are now complete anyway
+								yield break;
+							}
+
+							// No more available yet, not yet complete, wait until more becomes available
+							mResultsUpdated.WaitOne();
+						}
+						else
+						{
+							// More available now, so stop checking for more, continue with the loop to return them
+							break;
+						}
+					} while (true);
+
+					Debug.Assert(i <= count, "More should be available now");
+				}
+
+				yield return mResults[i];
+			}
+		}
+
+		public SearchResults CreateChildResults(string term)
+		{
+			Debug.Assert(term.StartsWith(mTerm));
+
+			int count;
+			bool complete;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			// If complete, then we know we don't need more than count. Otherwise, it can't be more than this capacity anyway
+			var childCapacity = complete ? count : mResults.Length;
+
+			return new SearchResults(childCapacity, term);
+		}
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.Designer.cs b/AutoTypeSearch/SearchWindow.Designer.cs
new file mode 100755
index 0000000..18b37d1
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.Designer.cs
@@ -0,0 +1,201 @@
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	partial class SearchWindow
+	{
+		/// 
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		#region Windows Form Designer generated code
+
+		/// 
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			this.components = new System.ComponentModel.Container();
+			this.mSearch = new System.Windows.Forms.TextBox();
+			this.mResults = new System.Windows.Forms.ListBox();
+			this.mLayout = new System.Windows.Forms.TableLayoutPanel();
+			this.mBanner = new System.Windows.Forms.PictureBox();
+			this.mInfoBanner = new System.Windows.Forms.Panel();
+			this.mInfoLabel = new System.Windows.Forms.Label();
+			this.mInfoBannerImage = new System.Windows.Forms.PictureBox();
+			this.mThrobber = new System.Windows.Forms.PictureBox();
+			this.mResultsUpdater = new System.Windows.Forms.Timer(this.components);
+			this.mNoResultsLabel = new System.Windows.Forms.Label();
+			this.mLayout.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).BeginInit();
+			this.mInfoBanner.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).BeginInit();
+			this.SuspendLayout();
+			// 
+			// mSearch
+			// 
+			this.mSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mSearch.Location = new System.Drawing.Point(1, 78);
+			this.mSearch.Margin = new System.Windows.Forms.Padding(1, 0, 1, 0);
+			this.mSearch.Name = "mSearch";
+			this.mSearch.Size = new System.Drawing.Size(521, 20);
+			this.mSearch.TabIndex = 0;
+			this.mSearch.LocationChanged += new System.EventHandler(this.mSearch_LocationChanged);
+			this.mSearch.TextChanged += new System.EventHandler(this.mSearch_TextChanged);
+			// 
+			// mResults
+			// 
+			this.mResults.BorderStyle = System.Windows.Forms.BorderStyle.None;
+			this.mResults.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mResults.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
+			this.mResults.FormattingEnabled = true;
+			this.mResults.IntegralHeight = false;
+			this.mResults.Location = new System.Drawing.Point(0, 98);
+			this.mResults.Margin = new System.Windows.Forms.Padding(0);
+			this.mResults.Name = "mResults";
+			this.mResults.Size = new System.Drawing.Size(523, 176);
+			this.mResults.TabIndex = 1;
+			this.mResults.TabStop = false;
+			this.mResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseClick);
+			this.mResults.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.mResults_DrawItem);
+			this.mResults.LocationChanged += new System.EventHandler(this.mResults_LocationChanged);
+			this.mResults.MouseEnter += new System.EventHandler(this.mResults_MouseEnter);
+			this.mResults.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseMove);
+			// 
+			// mLayout
+			// 
+			this.mLayout.ColumnCount = 1;
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+			this.mLayout.Controls.Add(this.mSearch, 0, 2);
+			this.mLayout.Controls.Add(this.mResults, 0, 3);
+			this.mLayout.Controls.Add(this.mBanner, 0, 0);
+			this.mLayout.Controls.Add(this.mInfoBanner, 0, 1);
+			this.mLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mLayout.Location = new System.Drawing.Point(0, 0);
+			this.mLayout.Name = "mLayout";
+			this.mLayout.RowCount = 4;
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.Size = new System.Drawing.Size(523, 274);
+			this.mLayout.TabIndex = 2;
+			// 
+			// mBanner
+			// 
+			this.mBanner.Dock = System.Windows.Forms.DockStyle.Top;
+			this.mBanner.Location = new System.Drawing.Point(0, 0);
+			this.mBanner.Margin = new System.Windows.Forms.Padding(0);
+			this.mBanner.Name = "mBanner";
+			this.mBanner.Size = new System.Drawing.Size(523, 60);
+			this.mBanner.TabIndex = 3;
+			this.mBanner.TabStop = false;
+			this.mBanner.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mBannerImage_MouseDown);
+			// 
+			// mInfoBanner
+			// 
+			this.mInfoBanner.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+			this.mInfoBanner.BackColor = System.Drawing.SystemColors.Info;
+			this.mInfoBanner.Controls.Add(this.mInfoLabel);
+			this.mInfoBanner.Controls.Add(this.mInfoBannerImage);
+			this.mInfoBanner.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoBanner.Location = new System.Drawing.Point(2, 61);
+			this.mInfoBanner.Margin = new System.Windows.Forms.Padding(2, 1, 1, 1);
+			this.mInfoBanner.Name = "mInfoBanner";
+			this.mInfoBanner.Size = new System.Drawing.Size(520, 16);
+			this.mInfoBanner.TabIndex = 8;
+			// 
+			// mInfoLabel
+			// 
+			this.mInfoLabel.AutoEllipsis = true;
+			this.mInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoLabel.ForeColor = System.Drawing.SystemColors.InfoText;
+			this.mInfoLabel.Location = new System.Drawing.Point(16, 0);
+			this.mInfoLabel.Name = "mInfoLabel";
+			this.mInfoLabel.Size = new System.Drawing.Size(504, 16);
+			this.mInfoLabel.TabIndex = 6;
+			this.mInfoLabel.Text = "AutoType failed to find";
+			// 
+			// mInfoBannerImage
+			// 
+			this.mInfoBannerImage.Dock = System.Windows.Forms.DockStyle.Left;
+			this.mInfoBannerImage.Image = global::AutoTypeSearch.Properties.Resources.Info;
+			this.mInfoBannerImage.Location = new System.Drawing.Point(0, 0);
+			this.mInfoBannerImage.Margin = new System.Windows.Forms.Padding(0);
+			this.mInfoBannerImage.Name = "mInfoBannerImage";
+			this.mInfoBannerImage.Size = new System.Drawing.Size(16, 16);
+			this.mInfoBannerImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mInfoBannerImage.TabIndex = 7;
+			this.mInfoBannerImage.TabStop = false;
+			// 
+			// mThrobber
+			// 
+			this.mThrobber.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.mThrobber.BackColor = System.Drawing.SystemColors.Window;
+			this.mThrobber.Location = new System.Drawing.Point(503, 81);
+			this.mThrobber.Name = "mThrobber";
+			this.mThrobber.Size = new System.Drawing.Size(16, 16);
+			this.mThrobber.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mThrobber.TabIndex = 4;
+			this.mThrobber.TabStop = false;
+			this.mThrobber.Visible = false;
+			// 
+			// mResultsUpdater
+			// 
+			this.mResultsUpdater.Interval = 250;
+			this.mResultsUpdater.Tick += new System.EventHandler(this.mResultsUpdater_Tick);
+			// 
+			// mNoResultsLabel
+			// 
+			this.mNoResultsLabel.AutoSize = true;
+			this.mNoResultsLabel.Location = new System.Drawing.Point(5, 103);
+			this.mNoResultsLabel.Name = "mNoResultsLabel";
+			this.mNoResultsLabel.Size = new System.Drawing.Size(84, 13);
+			this.mNoResultsLabel.TabIndex = 5;
+			this.mNoResultsLabel.Text = "No results found";
+			// 
+			// SearchWindow
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.BackColor = System.Drawing.SystemColors.Window;
+			this.ClientSize = new System.Drawing.Size(523, 274);
+			this.ControlBox = false;
+			this.Controls.Add(this.mNoResultsLabel);
+			this.Controls.Add(this.mThrobber);
+			this.Controls.Add(this.mLayout);
+			this.MinimumSize = new System.Drawing.Size(160, 96);
+			this.Name = "SearchWindow";
+			this.ShowInTaskbar = false;
+			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+			this.TopMost = true;
+			this.mLayout.ResumeLayout(false);
+			this.mLayout.PerformLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).EndInit();
+			this.mInfoBanner.ResumeLayout(false);
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).EndInit();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.TextBox mSearch;
+		private System.Windows.Forms.ListBox mResults;
+		private System.Windows.Forms.TableLayoutPanel mLayout;
+		private System.Windows.Forms.PictureBox mBanner;
+		private PictureBox mThrobber;
+		private Timer mResultsUpdater;
+		private Label mNoResultsLabel;
+		private Label mInfoLabel;
+		private Panel mInfoBanner;
+		private PictureBox mInfoBannerImage;
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchWindow.cs b/AutoTypeSearch/SearchWindow.cs
new file mode 100755
index 0000000..363b898
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.cs
@@ -0,0 +1,925 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Media;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Resources;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Collections;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	public partial class SearchWindow : Form
+	{
+		private const int SecondLineInset = 10;
+
+		// HACK to work around mono bug
+		private static readonly FieldInfo sMonoListBoxTopIndex = typeof(ListBox).GetField("top_index", BindingFlags.Instance | BindingFlags.NonPublic);
+
+		private readonly MainForm mMainForm;
+		private readonly Bitmap mBannerImage;
+		private readonly Searcher mSearcher;
+
+		private readonly Stream mThrobberImageStream;
+
+		private int? mWindowTopBorderHeight;
+		private int mBannerWidth = -1;
+		private int mMaximumExpandHeight;
+		private bool mManualSizeApplied;
+		private SearchResults mCurrentSearch;
+		private SearchResults mLastResultsUpdated;
+		private int mLastResultsUpdatedNextAvailableIndex;
+
+		#region Opening
+		public SearchWindow()
+		{
+			InitializeComponent();
+
+			// Mono can't load animated gifs from resx without crashing, so load it from an embedded resource instead
+			try
+			{
+				mThrobberImageStream = GetType().Assembly.GetManifestResourceStream("AutoTypeSearch.Throbber.gif");
+				if (mThrobberImageStream != null)
+				{
+					mThrobber.Image = Image.FromStream(mThrobberImageStream);
+				}
+			}
+			catch (Exception ex)
+			{
+				Debug.Fail("Failed to load Throbber.gif from embedded resource: " + ex.Message);
+			}
+
+			GlobalWindowManager.CustomizeControl(this);
+			UIUtil.SetExplorerTheme(mResults, true);
+			SetItemHeight();
+		}
+
+		public SearchWindow(MainForm mainForm, string infoBanner) : this()
+		{
+			mMainForm = mainForm;
+
+			mInfoBanner.Height = Math.Max(mInfoBannerImage.Height, mInfoLabel.Font.Height) + mInfoBanner.Margin.Vertical;
+			mInfoLabel.Padding = new Padding(0, (mInfoBanner.Height - mInfoLabel.Font.Height) / 2, 0, 0);
+			mInfoLabel.Text = infoBanner;
+
+			if (infoBanner == null)
+			{
+				mInfoBanner.Visible = false;
+				mInfoBanner.Height = 0;
+			}
+			
+			mSearcher = new Searcher(mMainForm.DocumentManager.GetOpenDatabases().ToArray());
+
+			Icon = mMainForm.Icon;
+			using (var bannerIcon = new Icon(Icon, 48, 48))
+			{
+				mBannerImage = bannerIcon.ToBitmap();
+			}
+			UpdateBanner();
+
+			ShowThrobber = false;
+
+			FontUtil.AssignDefaultItalic(mNoResultsLabel);
+		}
+
+
+		protected override void OnCreateControl()
+		{
+			base.OnCreateControl();
+
+			if (NativeMethods.IsWindows10())
+			{
+				mWindowTopBorderHeight = PointToScreen(Point.Empty).Y - this.Top;
+				NativeMethods.RefreshWindowFrame(Handle);
+			}
+
+			var windowRect = Settings.Default.WindowPosition;
+			var collapsedWindowRect = windowRect;
+			
+			collapsedWindowRect.Height = mSearch.Bottom + (Height - ClientSize.Height);
+
+			MinimumSize = new Size(MinimumSize.Width, collapsedWindowRect.Height);
+
+			if (windowRect.IsEmpty || !IsOnScreen(collapsedWindowRect))
+			{
+				windowRect = new Rectangle(0, 0, Width, Height);
+				Height = collapsedWindowRect.Height;
+
+				CenterToScreen();
+			}
+			else
+			{
+				Location = windowRect.Location;
+				Size = collapsedWindowRect.Size;
+			}
+
+			mMaximumExpandHeight = Math.Max(windowRect.Height, MinimumSize.Height + mResults.ItemHeight);
+		}
+		
+
+		private static bool IsOnScreen(Rectangle rectangle)
+		{
+			return Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(rectangle));
+		}
+
+		private void SetItemHeight()
+		{
+			mResults.ItemHeight = mResults.Font.Height * 2 + 2;
+		}
+
+		protected override void WndProc(ref Message m)
+		{
+			if (mWindowTopBorderHeight.HasValue)
+			{
+				NativeMethods.RemoveWindowFrameTopBorder(ref m, mWindowTopBorderHeight.Value);
+			}
+			base.WndProc(ref m);
+		}
+
+		#endregion
+
+		#region Closing
+		protected override void OnActivated(EventArgs e)
+		{
+			base.OnActivated(e);
+			Deactivate += OnDeactivate;
+		}
+
+		private void OnDeactivate(object sender, EventArgs eventArgs)
+		{
+			Close();
+		}
+
+		protected override void OnClosed(EventArgs e)
+		{
+			Deactivate -= OnDeactivate;
+			base.OnClosed(e);
+		}
+
+		/// 
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				if (mBannerImage != null)
+				{
+					mBannerImage.Dispose();
+				}
+				if (mThrobber.Image != null)
+				{
+					mThrobber.Image.Dispose();
+					mThrobber.Image = null;
+					mThrobberImageStream.Dispose();
+				}
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+		#endregion
+
+		#region Item Drawing
+		private void mResults_DrawItem(object sender, DrawItemEventArgs e)
+		{
+			var searchResult = mResults.Items[e.Index] as SearchResult;
+			if (searchResult == null)
+			{
+				Debug.Fail("Unexpected item in mResults");
+// ReSharper disable once HeuristicUnreachableCode - Not unreachable
+				return;
+			}
+			var drawingArea = e.Bounds;
+			drawingArea.Height--; // Leave room for a dividing line at the bottom
+			
+			if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
+			{
+				DrawBorderedRectangle(e.Graphics, drawingArea, SystemColors.Highlight);
+			}
+			else
+			{
+				e.Graphics.FillRectangle(SystemBrushes.Window, drawingArea);
+			}
+
+			var image = GetImage(searchResult.Database, searchResult.Entry.CustomIconUuid, searchResult.Entry.IconId);
+			var imageMargin = (drawingArea.Height - image.Height) / 2;
+			e.Graphics.DrawImage(image, drawingArea.Left + imageMargin, drawingArea.Top + imageMargin, image.Width, image.Height);
+
+			var textLeftMargin = drawingArea.Left + imageMargin * 2 + image.Width;
+			var textBounds = new Rectangle(textLeftMargin, drawingArea.Top + 1, drawingArea.Width - textLeftMargin - 1, drawingArea.Height - 2);
+
+			var line1Bounds = textBounds;
+			line1Bounds.Height = e.Font.Height;
+			var line2Bounds = line1Bounds;
+			line2Bounds.Y += line2Bounds.Height - 1;
+			line2Bounds.X += SecondLineInset;
+			line2Bounds.Width -= SecondLineInset;
+
+			var resultInTitleField = searchResult.FieldName == PwDefs.TitleField;
+
+			var title = (resultInTitleField ? searchResult.FieldValue : searchResult.Title).Replace('\n', ' '); // The FieldValue may have references resolved, whereas the title is always read directly.
+
+			var uniqueTitlePartWidth = 0;
+			if (!String.IsNullOrEmpty(searchResult.UniqueTitlePart))
+			{
+				var uniqueTitlePart = searchResult.UniqueTitlePart.Replace('\n', ' ');
+
+				var titleWidth = TextRenderer.MeasureText(e.Graphics, title, e.Font, line1Bounds.Size, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+
+				var availableWidthForUniqueTitlePart = line1Bounds.Width - titleWidth;
+				if (availableWidthForUniqueTitlePart > 20) // Don't bother including a unique part if there's no room for it
+				{
+					var uniqueTitlePartReversed = ReverseString(uniqueTitlePart);
+
+					uniqueTitlePartWidth = TextRenderer.MeasureText(e.Graphics, uniqueTitlePartReversed, e.Font, new Size(availableWidthForUniqueTitlePart, line1Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+					uniqueTitlePart = ReverseString(uniqueTitlePartReversed);
+
+					TextRenderer.DrawText(e.Graphics, uniqueTitlePart, e.Font, new Rectangle(line1Bounds.X, line1Bounds.Y, uniqueTitlePartWidth, line1Bounds.Height), SystemColors.GrayText, TextFormatFlags.NoPadding);
+				}
+			}
+
+			var titleBounds = new Rectangle(line1Bounds.X + uniqueTitlePartWidth, line1Bounds.Y, line1Bounds.Width - uniqueTitlePartWidth, line1Bounds.Height);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Highlight title in first line.
+				DrawHighlight(e, titleBounds, title, searchResult.Start, searchResult.Length);
+			}
+
+			TextRenderer.DrawText(e.Graphics, searchResult.Title, e.Font, titleBounds, SystemColors.WindowText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Use Username for second line.
+				TextRenderer.DrawText(e.Graphics, KPRes.UserName + ": " + searchResult.Entry.Strings.ReadSafeEx(PwDefs.UserNameField), e.Font, line2Bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+			}
+			else
+			{
+				// Found the result in not title field. Show the matching result on second line
+				
+				var fieldValue = searchResult.FieldValue.Replace('\n',' ');
+				var fieldNamePrefix = GetDisplayFieldName(searchResult.FieldName) + ": ";
+
+				var remainingSpace = line2Bounds.Width;
+				var fieldNamePrefixWidth = TextRenderer.MeasureText(e.Graphics, fieldNamePrefix, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+				remainingSpace -= fieldNamePrefixWidth;
+
+				int fieldValueHighlightWidth = 0, fieldValueLeftContextWidth = 0, fieldValueRightContextWidth = 0;
+
+				var leftContext = fieldValue.Substring(0, searchResult.Start);
+				var highlight = fieldValue.Substring(searchResult.Start, searchResult.Length);
+				var rightContext = fieldValue.Substring(searchResult.Start + searchResult.Length);
+
+				if (searchResult.Length == 0)
+				{
+					fieldValueHighlightWidth = remainingSpace;
+				}
+				else
+				{
+					if (remainingSpace > 0)
+					{
+						var availableSpace = remainingSpace;
+						fieldValueHighlightWidth = TextRenderer.MeasureText(e.Graphics, highlight, e.Font, new Size(availableSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						remainingSpace -= fieldValueHighlightWidth;
+					}
+
+					// Of the space remaining, divide it equally between that which comes before, and that which comes after
+					if (!String.IsNullOrEmpty(leftContext))
+					{
+						var leftContextReversed = ReverseString(leftContext);
+						fieldValueLeftContextWidth = TextRenderer.MeasureText(e.Graphics, leftContextReversed, e.Font, new Size(remainingSpace / 2, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+						if (fieldValueLeftContextWidth > remainingSpace)
+						{
+							// Always allow space for the minimal left context
+							fieldValueHighlightWidth -= (fieldValueLeftContextWidth - remainingSpace);
+							remainingSpace = 0;
+						}
+						else
+						{
+							remainingSpace -= fieldValueLeftContextWidth;							
+						}
+						
+						// Replace left context with the truncated reversed left context.
+						leftContext = ReverseString(leftContextReversed);
+					}
+
+					if (remainingSpace > 0 && !String.IsNullOrEmpty(rightContext))
+					{
+						fieldValueRightContextWidth = TextRenderer.MeasureText(e.Graphics, rightContext, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						if (fieldValueRightContextWidth > remainingSpace)
+						{
+							fieldValueRightContextWidth = 0;
+						}
+					}
+				}
+
+				// Now draw it all
+				var bounds = line2Bounds;
+				bounds.Width = fieldNamePrefixWidth;
+				TextRenderer.DrawText(e.Graphics, fieldNamePrefix, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				if (fieldValueLeftContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueLeftContextWidth;
+					TextRenderer.DrawText(e.Graphics, leftContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding); // No ellipsis as the leftContext string has already been truncated appropriately
+				}
+				if (fieldValueHighlightWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueHighlightWidth;
+
+					if (searchResult.Length > 0)
+					{
+						DrawHighlightRectangle(e, bounds);
+					}
+					TextRenderer.DrawText(e.Graphics, highlight, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+				if (fieldValueRightContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueRightContextWidth;
+					TextRenderer.DrawText(e.Graphics, rightContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+			}
+
+			e.Graphics.DrawLine(SystemPens.ButtonFace, drawingArea.Left, drawingArea.Bottom, drawingArea.Right, drawingArea.Bottom);
+		}
+
+		private static string ReverseString(string value)
+		{
+			return new String(value.ToCharArray().TakeWhile(c => c != '\0').Reverse().ToArray());
+		}
+
+		private static void DrawHighlight(DrawItemEventArgs e, Rectangle lineBounds, string text, int highlightFrom, int highlightLength)
+		{
+			var highlightX = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width;
+			var highlightWidth = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom + highlightLength), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width - highlightX;
+
+			DrawHighlightRectangle(e, new Rectangle(lineBounds.Left + highlightX, lineBounds.Top, highlightWidth, lineBounds.Height));
+		}
+
+		private static void DrawHighlightRectangle(DrawItemEventArgs e, Rectangle rectangle)
+		{
+			DrawBorderedRectangle(e.Graphics, rectangle, Color.PaleTurquoise);
+		}
+
+		private static void DrawBorderedRectangle(Graphics graphics, Rectangle rectangle, Color colour)
+		{
+			var border = rectangle;
+			border.Width--;
+			border.Height--;
+
+			using (var brush = new SolidBrush(MergeColors(colour, SystemColors.Window, 0.2)))
+			{
+				graphics.FillRectangle(brush, rectangle);
+			}
+			using (var pen = new Pen(colour, 1f))
+			{
+				graphics.DrawRectangle(pen, border);
+			}
+		}
+
+		private Image GetImage(PwDatabase database, PwUuid customIconId, PwIcon iconId)
+		{
+			Image image = null;
+			if (!customIconId.Equals(PwUuid.Zero))
+			{
+				image = database.GetCustomIcon(customIconId, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16));
+			}
+			if (image == null)
+			{
+				try { image = mMainForm.ClientIcons.Images[(int)iconId]; }
+				catch (Exception) { Debug.Assert(false); }
+			}
+
+			return image;
+		}
+
+		private static string GetDisplayFieldName(string fieldName)
+		{
+			switch (fieldName)
+			{
+				case PwDefs.TitleField:
+					return KPRes.Title;
+				case PwDefs.UserNameField:
+					return KPRes.UserName;
+				case PwDefs.PasswordField:
+					return KPRes.Password;
+				case PwDefs.UrlField:
+					return KPRes.Url;
+				case PwDefs.NotesField:
+					return KPRes.Notes;
+				case AutoTypeSearchExt.TagsVirtualFieldName:
+					return KPRes.Tags;
+				default:
+					return fieldName;
+			}
+		}
+
+		public static Color MergeColors(Color from, Color to, double amount)
+		{
+			var r = (byte)((from.R * amount) + to.R * (1 - amount));
+			var g = (byte)((from.G * amount) + to.G * (1 - amount));
+			var b = (byte)((from.B * amount) + to.B * (1 - amount));
+			return Color.FromArgb(r, g, b);
+		}
+		#endregion
+
+		#region Mouse tracking
+		private Point mMouseEntryPosition;
+		
+		private void mResults_MouseEnter(object sender, EventArgs e)
+		{
+			mMouseEntryPosition = MousePosition;
+		}
+
+		private void mResults_MouseMove(object sender, MouseEventArgs e)
+		{
+			// Discard the location the mouse has on entering the control (as it may be that the control has just moved under the mouse, not the other way around)
+			if (MousePosition == mMouseEntryPosition)
+			{
+				return;
+			}
+
+			// Hot tracking
+			var hoverIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (hoverIndex >= 0 && mResults.SelectedIndex != hoverIndex)
+			{
+				if (mResults.GetItemRectangle(hoverIndex).Bottom <= mResults.ClientRectangle.Bottom)
+				{
+					mResults.SelectedIndex = hoverIndex;
+				}
+				else
+				{
+					// Avoid the control scrolling
+					mResults.BeginUpdate();
+					var topIndex = mResults.TopIndex;
+					mResults.SelectedIndex = hoverIndex;
+					mResults.TopIndex = topIndex;
+					mResults.EndUpdate();
+				}
+			}
+		}
+		#endregion
+
+		#region Resizing
+		protected override void OnResizeBegin(EventArgs e)
+		{
+			// Stop automatically sizing - the user is picking a size they want.
+			mManualSizeApplied = true;
+			base.OnResizeBegin(e);
+		}
+
+		protected override void OnResize(EventArgs e)
+		{
+			base.OnResize(e);
+
+			UpdateBanner();
+
+			mResults.Invalidate();
+		}
+
+		protected override void OnResizeEnd(EventArgs e)
+		{
+			base.OnResizeEnd(e);
+
+			if (Height > MinimumSize.Height && Height != mMaximumExpandHeight)
+			{
+				mMaximumExpandHeight = Math.Max(Height, MinimumSize.Height + mResults.ItemHeight);
+			}
+			else
+			{
+				mManualSizeApplied = false;
+			}
+
+			Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+		}
+
+		private void UpdateBanner()
+		{
+			if (mBannerImage != null)
+			{
+				BannerFactory.UpdateBanner(this, mBanner, mBannerImage, PwDefs.ProductName, Resources.BannerText, ref mBannerWidth);
+			}
+		}
+
+		private void mSearch_LocationChanged(object sender, EventArgs e)
+		{
+			mThrobber.Location = new Point(mSearch.Right - mThrobber.Width - mThrobber.Margin.Right, mSearch.Top + (mSearch.Height - mThrobber.Height) / 2);
+		}
+
+		private void mResults_LocationChanged(object sender, EventArgs e)
+		{
+			mNoResultsLabel.Top = mResults.Top + (mResults.ItemHeight - mNoResultsLabel.Height) / 2;
+		}
+		#endregion
+
+		#region Searching
+		private static readonly SearchResultPrecedence SearchResultPrecedenceComparer = new SearchResultPrecedence();
+		private void mSearch_TextChanged(object sender, EventArgs e)
+		{
+			if (mSearch.Text.Length < 2)
+			{
+				// Stop searching
+				mResultsUpdater.Enabled = false;
+				ShowThrobber = false;
+				Height = MinimumSize.Height;
+				mManualSizeApplied = false;
+				mResults.Items.Clear();
+				mLastResultsUpdated = null;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			else
+			{
+				// Start searching
+				mNoResultsLabel.Visible = false;
+				mCurrentSearch = mSearcher.Search(mSearch.Text);
+				mResultsUpdater.Enabled = true;
+				ShowThrobber = true;
+				mResultsUpdater_Tick(null, EventArgs.Empty); // Quick poke just in case the results are already done.
+			}
+		}
+
+		[SuppressMessage("ReSharper", "CoVariantArrayConversion", Justification = "Object arrays for Listbox.Items, known to be of correct type")]
+		private void mResultsUpdater_Tick(object sender, EventArgs e)
+		{
+			if (mLastResultsUpdated != mCurrentSearch)
+			{
+				// Clear out old results and replace with new ones
+				mResults.Items.Clear();
+				mLastResultsUpdated = mCurrentSearch;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			var existingResultsCount = mResults.Items.Count;
+			
+			bool complete;
+			var newResults = mLastResultsUpdated.GetAvailableResults(ref mLastResultsUpdatedNextAvailableIndex, out complete);
+			if (newResults.Length > 0)
+			{
+				mResults.BeginUpdate();
+				
+				SearchResult[] allResults;
+				if (existingResultsCount > 0)
+				{
+					allResults = new SearchResult[existingResultsCount + newResults.Length];
+					mResults.Items.CopyTo(allResults, 0);
+					newResults.CopyTo(allResults, existingResultsCount);
+
+					mResults.Items.Clear();
+				}
+				else
+				{
+					allResults = newResults;
+				}
+
+				CalculateUniqueTitles(allResults);
+
+				Array.Sort(allResults, SearchResultPrecedenceComparer);
+				mResults.Items.AddRange(allResults);
+				
+				mResults.EndUpdate();
+
+				if (allResults.Length > 0)
+				{
+					if (mResults.SelectedIndex == -1)
+					{
+						try
+						{
+							// HACK to work around mono bug
+							if (sMonoListBoxTopIndex != null)
+							{
+								sMonoListBoxTopIndex.SetValue(mResults, 1); // Set the top_index to 1 so that when selected index is set to 0, and calls EnsureVisible(0), it follows the index < top_index pass and not the broken index >= top_index + rows path. 
+							}
+
+							mResults.SelectedIndex = 0;
+							mResults.TopIndex = 0;
+						}
+						catch (Exception ex)
+						{
+							Debug.Fail("Failed to set selection on count of " + allResults.Length + ": " + ex.Message);
+						}
+					}
+
+					if (!mManualSizeApplied)
+					{
+						Height = Math.Min(mMaximumExpandHeight, MinimumSize.Height + (allResults.Length * mResults.ItemHeight));
+					}
+				}
+			}
+
+			if (complete)
+			{
+				ShowThrobber = false;
+				mResultsUpdater.Enabled = false;
+
+				if (mResults.Items.Count == 0)
+				{
+					mNoResultsLabel.Visible = true;
+					Height = MinimumSize.Height + mResults.ItemHeight;
+					mManualSizeApplied = false;
+				}
+			}
+		}
+
+		private void CalculateUniqueTitles(IEnumerable results, int depth = 0)
+		{
+			// Where results have identical titles, include group titles to make them unique
+			depth += 1;
+
+			// First create a lookup by title
+			var titles = new Dictionary>();
+			foreach (var searchResult in results)
+			{
+				List resultsWithSameTitle;
+				if (titles.TryGetValue(searchResult.UniqueTitle, out resultsWithSameTitle))
+				{
+					resultsWithSameTitle.Add(searchResult);
+				}
+				else
+				{
+					titles.Add(searchResult.UniqueTitle, new List { searchResult });
+				}
+			}
+
+			// Attempt to unique-ify any non-unique titles
+			foreach (var resultsSharingTitle in titles.Values)
+			{
+				if (resultsSharingTitle.Count > 1)
+				{
+					var titlesModified = false;
+					foreach (var searchResult in resultsSharingTitle)
+					{
+						titlesModified |= searchResult.SetUniqueTitleDepth(depth);
+					}
+
+					if (titlesModified)
+					{
+						// Recurse in case of continuing non-uniqueness
+						CalculateUniqueTitles(resultsSharingTitle, depth);
+					}
+				}
+			}
+		}
+
+		private class SearchResultPrecedence : IComparer
+		{
+			public int Compare(SearchResult x, SearchResult y)
+			{
+				// First precedence is that if the result is the start of the field value, it's higher precedence than if it doesn't.
+				var result = -(x.Start == 0).CompareTo(y.Start == 0);
+
+				// Second precedence is that the start of the title field is higher precedence than the start of any other field
+				if (result == 0)
+				{
+					result = -(x.FieldName == PwDefs.TitleField).CompareTo(y.FieldName == PwDefs.TitleField);
+				}
+
+				// Both start the title field, so both equal. Have to have consistent ordering, so return final precedence based search index
+				if (result == 0)
+				{
+					result = x.ResultIndex.CompareTo(y.ResultIndex);
+				}
+				
+				return result;
+			}
+		}
+
+		private bool ShowThrobber
+		{
+			get { return mThrobber.Visible; }
+			set
+			{
+				if (value != ShowThrobber)
+				{
+					if (value)
+					{
+						mThrobber.Visible = true;
+
+						// Set the margin on the textbox to allow room for the throbber
+						NativeMethods.SetTextBoxRightMargin(mSearch, mThrobber.Width + mThrobber.Margin.Right);
+					}
+					else
+					{
+						mThrobber.Visible = false;
+
+						NativeMethods.SetTextBoxRightMargin(mSearch, 0);
+					}
+				}
+			}
+		}
+		#endregion
+
+		private void mBannerImage_MouseDown(object sender, MouseEventArgs e)
+		{
+			// Allow drag by banner image
+			if (e.Button == MouseButtons.Left)
+			{
+				if (e.Clicks == 2)
+				{
+					// Re-center the form on double-click
+					CenterToScreen();
+
+					Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+				}
+				else if (!NativeLib.IsUnix())
+				{
+					NativeMethods.StartFormDrag(this);
+				}
+			}
+		}
+
+		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+		{
+			switch (keyData)
+			{
+				case Keys.Escape:
+					Close();
+					return true;
+				case Keys.Up:
+					TryChangeSelection(-1);
+					return true;
+				case Keys.Down:
+					TryChangeSelection(1);
+					return true;
+				case Keys.PageUp:
+					TryChangeSelection(-mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.PageDown:
+					TryChangeSelection(mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.Home | Keys.Control:
+					mResults.SelectedIndex = 0;
+					return true;
+				case Keys.End | Keys.Control:
+					mResults.SelectedIndex = mResults.Items.Count - 1;
+					return true;
+				case Keys.Enter:
+					PerformAction(Settings.Default.DefaultAction, mResults.SelectedItem as SearchResult);
+					break;
+				case Keys.Enter | Keys.Shift:
+					PerformAction(Settings.Default.AlternativeAction, mResults.SelectedItem as SearchResult);
+					break;
+			}
+			
+			return base.ProcessCmdKey(ref msg, keyData);
+		}
+
+		#region Selection Changing
+
+		protected override void OnMouseWheel(MouseEventArgs e)
+		{
+			mResults.TopIndex -= (e.Delta / Math.Abs(e.Delta));
+		}
+
+		private void TryChangeSelection(int delta)
+		{
+			if (mResults.Items.Count > 0)
+			{
+				mResults.SelectedIndex = Math.Max(Math.Min(mResults.Items.Count - 1, mResults.SelectedIndex + delta), 0);
+			}
+		}
+		#endregion
+
+		#region Actions
+
+		private void mResults_MouseClick(object sender, MouseEventArgs e)
+		{
+			var clickIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (clickIndex >= 0)
+			{
+				var clickedResult = mResults.Items[clickIndex] as SearchResult;
+				if (clickedResult != null)
+				{
+					PerformAction((ModifierKeys & Keys.Shift) == Keys.Shift ? Settings.Default.AlternativeAction : Settings.Default.DefaultAction, clickedResult);
+				}
+			}
+		}
+
+		private void PerformAction(Actions action, SearchResult searchResult)
+		{
+			Close();
+
+			if (searchResult != null)
+			{
+				switch (action)
+				{
+					case Actions.PerformAutoType:
+						AutoTypeEntry(searchResult);
+						break;
+					case Actions.EditEntry:
+						EditEntry(searchResult);
+						break;
+					case Actions.ShowEntry:
+						ShowEntry(searchResult);
+						break;
+					case Actions.OpenEntryUrl:
+						OpenEntryUrl(searchResult);
+						break;
+					case Actions.CopyPassword:
+						CopyPassword(searchResult);
+						break;
+					default:
+						throw new ArgumentOutOfRangeException("action");
+				}
+			}
+		}
+
+		private void AutoTypeEntry(SearchResult searchResult)
+		{
+			bool result;
+			if (ActiveForm != null)
+			{
+				result = AutoType.PerformIntoPreviousWindow(mMainForm, searchResult.Entry, searchResult.Database);
+			}
+			else
+			{
+				result = AutoType.PerformIntoCurrentWindow(searchResult.Entry, searchResult.Database);
+			}
+			if (!result)
+			{
+				SystemSounds.Beep.Play();
+
+				if (Settings.Default.AlternativeAction != Actions.PerformAutoType)
+				{
+					PerformAction(Settings.Default.AlternativeAction, searchResult);
+				}
+			}
+		}
+
+		private void EditEntry(SearchResult searchResult)
+		{
+			using (var entryForm = new PwEntryForm())
+			{
+				mMainForm.MakeDocumentActive(mMainForm.DocumentManager.FindDocument(searchResult.Database));
+				
+				entryForm.InitEx(searchResult.Entry, PwEditMode.EditExistingEntry, searchResult.Database, mMainForm.ClientIcons, false, false);
+
+				ShowForegroundDialog(entryForm);
+
+				mMainForm.UpdateUI(false, null, searchResult.Database.UINeedsIconUpdate, null, true, null, entryForm.HasModifiedEntry);
+			}
+		}
+
+// ReSharper disable once UnusedMethodReturnValue.Local - Generic helper, result may be used in future
+		private DialogResult ShowForegroundDialog(Form form)
+		{
+			mMainForm.EnsureVisibleForegroundWindow(false, false);
+			form.StartPosition = FormStartPosition.CenterScreen;
+			if (mMainForm.IsTrayed())
+			{
+				form.ShowInTaskbar = true;
+			}
+
+			form.Shown += ActivateFormOnShown;
+			return form.ShowDialog(mMainForm);
+		}
+
+		private static void ActivateFormOnShown(object sender, EventArgs eventArgs)
+		{
+			var form = (Form)sender;
+			form.Shown -= ActivateFormOnShown;
+			form.Activate();
+		}
+
+		private void ShowEntry(SearchResult searchResult)
+		{
+			// Show this entry
+			mMainForm.UpdateUI(false, mMainForm.DocumentManager.FindDocument(searchResult.Database), true, searchResult.Entry.ParentGroup, true, null, false, null);
+			mMainForm.SelectEntries(new PwObjectList { searchResult.Entry }, true, true);
+			mMainForm.EnsureVisibleEntry(searchResult.Entry.Uuid);
+			mMainForm.UpdateUI(false, null, false, null, false, null, false);
+			mMainForm.EnsureVisibleForegroundWindow(true, true);
+		}
+
+		private void OpenEntryUrl(SearchResult searchResult)
+		{
+			WinUtil.OpenEntryUrl(searchResult.Entry);
+		}
+
+		private void CopyPassword(SearchResult searchResult)
+		{
+			if (ClipboardUtil.Copy(searchResult.Entry.Strings.ReadSafe(PwDefs.PasswordField), true, true, searchResult.Entry,
+									mMainForm.DocumentManager.SafeFindContainerOf(searchResult.Entry),
+									IntPtr.Zero))
+			{
+				mMainForm.StartClipboardCountdown();
+			}
+		}
+		
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.resx b/AutoTypeSearch/SearchWindow.resx
new file mode 100755
index 0000000..8ef82f0
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.resx
@@ -0,0 +1,123 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    17, 17
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Searcher.cs b/AutoTypeSearch/Searcher.cs
new file mode 100755
index 0000000..433ae94
--- /dev/null
+++ b/AutoTypeSearch/Searcher.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class Searcher
+	{
+		private readonly PwDatabase[] mDatabases;
+		private readonly Dictionary mSearches = new Dictionary();
+
+		public Searcher(PwDatabase[] databases)
+		{
+			mDatabases = databases;
+		}
+
+		public SearchResults Search(string term)
+		{
+			if (term.Length < 2)
+			{
+				throw new ArgumentException("Search term must be at least 2 characters");
+			}
+
+			SearchResults parentResults = null;
+
+			var termParent = term;
+			while (termParent.Length >= 2)
+			{
+				if (mSearches.TryGetValue(termParent, out parentResults))
+				{
+					if (termParent == term)
+					{
+						// This is an exact duplicate search, so return it.
+						return parentResults;
+					}
+
+					// Found an existing search for a parent of the term, start from there.
+					break;
+				}
+		
+				// No existing search for termParent found, try less.
+				termParent = termParent.Remove(termParent.Length - 1, 1);
+			}
+
+			SearchResults searchResults;
+			if (parentResults == null)
+			{
+				// No parent found at all, start from scratch
+				searchResults = new SearchResults(GetCountOfAllDatabaseEntries(), term);
+
+				var rootSearchThread = new Thread(RootSearchWorker) { Name = term };
+				rootSearchThread.Start(searchResults);
+			}
+			else
+			{
+				searchResults = parentResults.CreateChildResults(term);
+
+				var childSearchThread = new Thread(ChildSearchWorker) { Name = term };
+				childSearchThread.Start(new ChildSearchWorkerState{ Source = parentResults, Results = searchResults });
+			}
+
+			mSearches.Add(term, searchResults);
+
+			return searchResults;
+		}
+
+		private int GetCountOfAllDatabaseEntries()
+		{
+			return (from database in mDatabases select (int)database.RootGroup.GetEntriesCount(true)).Sum();
+		}
+
+		private void RootSearchWorker(object stateObject)
+		{
+			var results = (SearchResults)stateObject;
+			var excludeExpired = Settings.Default.ExcludeExpired;
+			var searchStartTime = DateTime.Now;
+
+			foreach (var database in mDatabases)
+			{
+				SearchGroup(database, database.RootGroup, results, excludeExpired, searchStartTime);	
+			}
+
+			results.SetComplete();
+		}
+
+		/// 
+		/// Recursively search  and its children, adding results to 
+		/// 
+		private void SearchGroup(PwDatabase context, PwGroup group, SearchResults results, bool excludeExpired, DateTime searchStartTime)
+		{
+			if (group.EnableSearching ?? true) // Group will only be searched if it's parent enabled searching, so if it is inherit (null) or true, search it.
+			{
+				foreach (var childGroup in group.Groups)
+				{
+					SearchGroup(context, childGroup, results, excludeExpired, searchStartTime);
+				}
+
+				foreach (var entry in group.Entries)
+				{
+					if (!(excludeExpired && entry.Expires && searchStartTime > entry.ExpiryTime))
+					{
+						results.AddResultIfMatchesTerm(context, entry);
+					}
+				}
+			}
+		}
+
+		private struct ChildSearchWorkerState
+		{
+			public SearchResults Source;
+			public SearchResults Results;
+		}
+		private void ChildSearchWorker(object stateObject)
+		{
+			var state = (ChildSearchWorkerState)stateObject;
+
+			bool complete;
+			var index = 0;
+			do
+			{
+				foreach (var entry in state.Source.GetAvailableResults(ref index, out complete))
+				{
+					state.Results.AddResultIfMatchesTerm(entry);
+				}
+			} while (!complete);
+
+			state.Results.SetComplete();
+		}
+	}
+}
diff --git a/AutoTypeSearch/Throbber.gif b/AutoTypeSearch/Throbber.gif
new file mode 100755
index 0000000..494d426
--- /dev/null
+++ b/AutoTypeSearch/Throbber.gif
Binary files differ
diff --git a/AutoTypeSearch/app.config b/AutoTypeSearch/app.config
new file mode 100755
index 0000000..1370758
--- /dev/null
+++ b/AutoTypeSearch/app.config
@@ -0,0 +1,60 @@
+
+
+    
+        
+            
+        
+    
+    
+        
+            
+                True
+            
+            
+                False
+            
+            
+                True
+            
+            
+                True
+            
+            
+                True
+            
+            
+                True
+            
+            
+                False
+            
+            
+                0, 0, 0, 0
+            
+            
+                True
+            
+            
+                False
+            
+            
+                True
+            
+            
+                False
+            
+            
+                False
+            
+            
+                PerformAutoType
+            
+            
+                EditEntry
+            
+            
+                None
+            
+        
+    
+
\ No newline at end of file
diff --git a/CreatePlgX.bat b/CreatePlgX.bat
new file mode 100755
index 0000000..59b9aa0
--- /dev/null
+++ b/CreatePlgX.bat
@@ -0,0 +1,20 @@
+@echo off
+cd %~dp0
+
+echo Deleting existing PlgX folder
+rmdir /s /q PlgX
+
+echo Creating PlgX folder
+mkdir PlgX
+
+echo Copying files
+xcopy "AutoTypeSearch" PlgX /s /e /exclude:PlgXExclude.txt
+
+echo Compiling PlgX
+"../KeePass/KeePass.exe" /plgx-create "%~dp0PlgX" --plgx-prereq-kp:2.27
+
+echo Releasing PlgX
+move /y PlgX.plgx "Releases\Build Outputs\AutoTypeSearch.plgx"
+
+echo Cleaning up
+rmdir /s /q PlgX
diff --git a/PlgXExclude.txt b/PlgXExclude.txt
new file mode 100755
index 0000000..f626d58
--- /dev/null
+++ b/PlgXExclude.txt
@@ -0,0 +1,7 @@
+\bin\
+\obj\
+.user
+.sln
+.suo
+.pdb
+.xml
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/AutoTypeSearch/SearchResults.cs b/AutoTypeSearch/SearchResults.cs
new file mode 100755
index 0000000..b2b0529
--- /dev/null
+++ b/AutoTypeSearch/SearchResults.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePass.Util.Spr;
+using KeePassLib;
+using KeePassLib.Utility;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResults
+	{
+		private readonly string mTerm;
+		private readonly SearchResult[] mResults;
+
+		private readonly object mLock = new object();
+		private volatile int mCount;
+		private volatile bool mComplete;
+
+		private readonly AutoResetEvent mResultsUpdated = new AutoResetEvent(false);
+
+		private readonly CompareOptions mStringComparison;
+		private readonly bool mSearchTitle;
+		private readonly bool mSearchUserName;
+		private readonly bool mSearchUrl;
+		private readonly bool mSearchNotes;
+		private readonly bool mSearchCustomFields;
+		private readonly bool mResolveReferences;
+		private readonly bool mSearchTags;
+
+		public SearchResults(int capacity, string term)
+		{
+			mTerm = term;
+			mResults = new SearchResult[capacity];
+
+			mStringComparison = Settings.Default.CaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase;
+			mStringComparison |= CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace;
+			mSearchTitle = Settings.Default.SearchTitle;
+			mSearchUserName = Settings.Default.SearchUserName;
+			mSearchUrl = Settings.Default.SearchUrl;
+			mSearchNotes = Settings.Default.SearchNotes;
+			mSearchCustomFields = Settings.Default.SearchCustomFields;
+			mSearchTags = Settings.Default.SearchTags;
+			mResolveReferences = Settings.Default.ResolveReferences;
+		}
+
+		/// 
+		/// Gets an ordered list of fields to search for the term
+		/// 
+		/// 
+		/// 
+		private IEnumerable GetFieldsToSearch(PwEntry entry)
+		{
+			var fieldsToSearch = new List((int)entry.Strings.UCount);
+			if (mSearchTitle) fieldsToSearch.Add(PwDefs.TitleField);
+			if (mSearchUserName) fieldsToSearch.Add(PwDefs.UserNameField);
+			if (mSearchUrl) fieldsToSearch.Add(PwDefs.UrlField);
+			if (mSearchNotes) fieldsToSearch.Add(PwDefs.NotesField);
+			if (mSearchCustomFields)
+			{
+				foreach (var stringEntry in entry.Strings)
+				{
+					if (!stringEntry.Value.IsProtected && !PwDefs.IsStandardField(stringEntry.Key))
+					{
+						fieldsToSearch.Add(stringEntry.Key);
+					}
+				}
+			}
+			if (mSearchTags) fieldsToSearch.Add(AutoTypeSearchExt.TagsVirtualFieldName);
+
+			return fieldsToSearch;
+		}
+
+		public void AddResultIfMatchesTerm(PwDatabase context, PwEntry entry)
+		{
+			// First try without resolving
+			var addedResult = AddResultIfMatchesTerm(context, entry, false);
+
+			if (!addedResult && mResolveReferences)
+			{
+				// Not found without resolving, so try resolving
+				AddResultIfMatchesTerm(context, entry, true);
+			}
+		}
+
+		private bool AddResultIfMatchesTerm(PwDatabase context, PwEntry entry, bool resolveReferences)
+		{
+			foreach (var fieldName in GetFieldsToSearch(entry))
+			{
+				string fieldValue;
+				if (fieldName == AutoTypeSearchExt.TagsVirtualFieldName)
+				{
+					fieldValue = StrUtil.TagsToString(entry.Tags, true);
+				}
+				else
+				{
+					fieldValue = entry.Strings.ReadSafeEx(fieldName);
+
+					if (resolveReferences)
+					{
+						fieldValue = ResolveReferences(context, entry, fieldValue);
+					}
+				}
+
+				if (!String.IsNullOrEmpty(fieldValue))
+				{
+					var foundIndex = CultureInfo.CurrentCulture.CompareInfo.IndexOf(fieldValue, mTerm, mStringComparison);
+					if (foundIndex >= 0)
+					{
+						// Found a match, create a search result and add it
+						AddResult(new SearchResult(context, entry, entry.Strings.ReadSafe(PwDefs.TitleField), fieldName, fieldValue, foundIndex, mTerm.Length));
+						return true;
+					}
+				}
+			}
+			return false;
+		}
+
+		/// 
+		/// Resolves any references in the field value and returns it. If there were no references,
+		/// returns null (to avoid duplicate searching - it is assumed that the unresolved value has already been searched)
+		/// 
+		private string ResolveReferences(PwDatabase context, PwEntry entry, string fieldValue)
+		{
+			if (fieldValue.IndexOf('{') < 0)
+			{
+				// Can't contain any references
+				return null;
+			}
+			
+			var sprContext = new SprContext(entry, context, SprCompileFlags.Deref) { ForcePlainTextPasswords = false };
+
+			var result = SprEngine.Compile(fieldValue, sprContext);
+			if (CultureInfo.CurrentCulture.CompareInfo.Compare(result,fieldValue, mStringComparison) == 0)
+			{
+				return null;
+			}
+			
+			return result;
+		}
+
+		public void AddResultIfMatchesTerm(SearchResult candidate)
+		{
+			// First see whether the existing candidate is a further match in the same place
+			var fieldValue = candidate.FieldValue;
+			if (fieldValue.Length > candidate.Start + mTerm.Length && CultureInfo.CurrentCulture.CompareInfo.Compare(fieldValue.Substring(candidate.Start, mTerm.Length), mTerm, mStringComparison) == 0)
+			{
+				// Yep, match continues, so add it.
+				AddResult(new SearchResult(candidate.Database, candidate.Entry, candidate.Title, candidate.FieldName, fieldValue, candidate.Start, mTerm.Length));
+			}
+			else
+			{
+				// Existing candidate match couldn't be extended, so search from scratch again
+				AddResultIfMatchesTerm(candidate.Database, candidate.Entry);
+			}
+		}
+
+		private void AddResult(SearchResult result)
+		{
+			lock (mLock)
+			{
+				if (mComplete)
+				{
+					throw new InvalidOperationException("Search results have been completed");
+				}
+				result.SetResultIndex(mCount);
+				mResults[mCount++] = result;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Indicates that the results are complete, and no more will be added.
+		/// 
+		public void SetComplete()
+		{
+			lock (mLock)
+			{
+				mComplete = true;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Gets all the available results so far.
+		/// 
+		/// Index to start returning from. Modified to be the first index not available yet on return.
+		/// Set to true if the results are complete, false if more results are pending but have not been returned.
+		/// 
+		public SearchResult[] GetAvailableResults(ref int index, out bool complete)
+		{
+			int count;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			if (count <= index)
+			{
+				return new SearchResult[0];
+			}
+
+			var availableResults = new SearchResult[count - index];
+			Array.Copy(mResults, index, availableResults, 0, availableResults.Length);
+			index = count;
+
+			return availableResults;
+		}
+
+		/// 
+		/// Gets all the results. Will block until complete.
+		/// 
+		/// 
+		public IEnumerable GetAllResults()
+		{
+			int count = -1;
+
+			for (var i = 0; i < mResults.Length; i++)
+			{
+				if (i > count)
+				{
+					// Reached the limit of availability so far, so see if more is available
+					do
+					{
+						bool moreAvailable, complete;
+
+						lock (mLock)
+						{
+							moreAvailable = mCount > count;
+							count = mCount;
+							complete = mComplete;
+						}
+
+						if (!moreAvailable)
+						{
+							if (complete)
+							{
+								// No more available, but the results are now complete anyway
+								yield break;
+							}
+
+							// No more available yet, not yet complete, wait until more becomes available
+							mResultsUpdated.WaitOne();
+						}
+						else
+						{
+							// More available now, so stop checking for more, continue with the loop to return them
+							break;
+						}
+					} while (true);
+
+					Debug.Assert(i <= count, "More should be available now");
+				}
+
+				yield return mResults[i];
+			}
+		}
+
+		public SearchResults CreateChildResults(string term)
+		{
+			Debug.Assert(term.StartsWith(mTerm));
+
+			int count;
+			bool complete;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			// If complete, then we know we don't need more than count. Otherwise, it can't be more than this capacity anyway
+			var childCapacity = complete ? count : mResults.Length;
+
+			return new SearchResults(childCapacity, term);
+		}
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.Designer.cs b/AutoTypeSearch/SearchWindow.Designer.cs
new file mode 100755
index 0000000..18b37d1
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.Designer.cs
@@ -0,0 +1,201 @@
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	partial class SearchWindow
+	{
+		/// 
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		#region Windows Form Designer generated code
+
+		/// 
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			this.components = new System.ComponentModel.Container();
+			this.mSearch = new System.Windows.Forms.TextBox();
+			this.mResults = new System.Windows.Forms.ListBox();
+			this.mLayout = new System.Windows.Forms.TableLayoutPanel();
+			this.mBanner = new System.Windows.Forms.PictureBox();
+			this.mInfoBanner = new System.Windows.Forms.Panel();
+			this.mInfoLabel = new System.Windows.Forms.Label();
+			this.mInfoBannerImage = new System.Windows.Forms.PictureBox();
+			this.mThrobber = new System.Windows.Forms.PictureBox();
+			this.mResultsUpdater = new System.Windows.Forms.Timer(this.components);
+			this.mNoResultsLabel = new System.Windows.Forms.Label();
+			this.mLayout.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).BeginInit();
+			this.mInfoBanner.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).BeginInit();
+			this.SuspendLayout();
+			// 
+			// mSearch
+			// 
+			this.mSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mSearch.Location = new System.Drawing.Point(1, 78);
+			this.mSearch.Margin = new System.Windows.Forms.Padding(1, 0, 1, 0);
+			this.mSearch.Name = "mSearch";
+			this.mSearch.Size = new System.Drawing.Size(521, 20);
+			this.mSearch.TabIndex = 0;
+			this.mSearch.LocationChanged += new System.EventHandler(this.mSearch_LocationChanged);
+			this.mSearch.TextChanged += new System.EventHandler(this.mSearch_TextChanged);
+			// 
+			// mResults
+			// 
+			this.mResults.BorderStyle = System.Windows.Forms.BorderStyle.None;
+			this.mResults.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mResults.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
+			this.mResults.FormattingEnabled = true;
+			this.mResults.IntegralHeight = false;
+			this.mResults.Location = new System.Drawing.Point(0, 98);
+			this.mResults.Margin = new System.Windows.Forms.Padding(0);
+			this.mResults.Name = "mResults";
+			this.mResults.Size = new System.Drawing.Size(523, 176);
+			this.mResults.TabIndex = 1;
+			this.mResults.TabStop = false;
+			this.mResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseClick);
+			this.mResults.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.mResults_DrawItem);
+			this.mResults.LocationChanged += new System.EventHandler(this.mResults_LocationChanged);
+			this.mResults.MouseEnter += new System.EventHandler(this.mResults_MouseEnter);
+			this.mResults.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseMove);
+			// 
+			// mLayout
+			// 
+			this.mLayout.ColumnCount = 1;
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+			this.mLayout.Controls.Add(this.mSearch, 0, 2);
+			this.mLayout.Controls.Add(this.mResults, 0, 3);
+			this.mLayout.Controls.Add(this.mBanner, 0, 0);
+			this.mLayout.Controls.Add(this.mInfoBanner, 0, 1);
+			this.mLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mLayout.Location = new System.Drawing.Point(0, 0);
+			this.mLayout.Name = "mLayout";
+			this.mLayout.RowCount = 4;
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.Size = new System.Drawing.Size(523, 274);
+			this.mLayout.TabIndex = 2;
+			// 
+			// mBanner
+			// 
+			this.mBanner.Dock = System.Windows.Forms.DockStyle.Top;
+			this.mBanner.Location = new System.Drawing.Point(0, 0);
+			this.mBanner.Margin = new System.Windows.Forms.Padding(0);
+			this.mBanner.Name = "mBanner";
+			this.mBanner.Size = new System.Drawing.Size(523, 60);
+			this.mBanner.TabIndex = 3;
+			this.mBanner.TabStop = false;
+			this.mBanner.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mBannerImage_MouseDown);
+			// 
+			// mInfoBanner
+			// 
+			this.mInfoBanner.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+			this.mInfoBanner.BackColor = System.Drawing.SystemColors.Info;
+			this.mInfoBanner.Controls.Add(this.mInfoLabel);
+			this.mInfoBanner.Controls.Add(this.mInfoBannerImage);
+			this.mInfoBanner.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoBanner.Location = new System.Drawing.Point(2, 61);
+			this.mInfoBanner.Margin = new System.Windows.Forms.Padding(2, 1, 1, 1);
+			this.mInfoBanner.Name = "mInfoBanner";
+			this.mInfoBanner.Size = new System.Drawing.Size(520, 16);
+			this.mInfoBanner.TabIndex = 8;
+			// 
+			// mInfoLabel
+			// 
+			this.mInfoLabel.AutoEllipsis = true;
+			this.mInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoLabel.ForeColor = System.Drawing.SystemColors.InfoText;
+			this.mInfoLabel.Location = new System.Drawing.Point(16, 0);
+			this.mInfoLabel.Name = "mInfoLabel";
+			this.mInfoLabel.Size = new System.Drawing.Size(504, 16);
+			this.mInfoLabel.TabIndex = 6;
+			this.mInfoLabel.Text = "AutoType failed to find";
+			// 
+			// mInfoBannerImage
+			// 
+			this.mInfoBannerImage.Dock = System.Windows.Forms.DockStyle.Left;
+			this.mInfoBannerImage.Image = global::AutoTypeSearch.Properties.Resources.Info;
+			this.mInfoBannerImage.Location = new System.Drawing.Point(0, 0);
+			this.mInfoBannerImage.Margin = new System.Windows.Forms.Padding(0);
+			this.mInfoBannerImage.Name = "mInfoBannerImage";
+			this.mInfoBannerImage.Size = new System.Drawing.Size(16, 16);
+			this.mInfoBannerImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mInfoBannerImage.TabIndex = 7;
+			this.mInfoBannerImage.TabStop = false;
+			// 
+			// mThrobber
+			// 
+			this.mThrobber.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.mThrobber.BackColor = System.Drawing.SystemColors.Window;
+			this.mThrobber.Location = new System.Drawing.Point(503, 81);
+			this.mThrobber.Name = "mThrobber";
+			this.mThrobber.Size = new System.Drawing.Size(16, 16);
+			this.mThrobber.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mThrobber.TabIndex = 4;
+			this.mThrobber.TabStop = false;
+			this.mThrobber.Visible = false;
+			// 
+			// mResultsUpdater
+			// 
+			this.mResultsUpdater.Interval = 250;
+			this.mResultsUpdater.Tick += new System.EventHandler(this.mResultsUpdater_Tick);
+			// 
+			// mNoResultsLabel
+			// 
+			this.mNoResultsLabel.AutoSize = true;
+			this.mNoResultsLabel.Location = new System.Drawing.Point(5, 103);
+			this.mNoResultsLabel.Name = "mNoResultsLabel";
+			this.mNoResultsLabel.Size = new System.Drawing.Size(84, 13);
+			this.mNoResultsLabel.TabIndex = 5;
+			this.mNoResultsLabel.Text = "No results found";
+			// 
+			// SearchWindow
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.BackColor = System.Drawing.SystemColors.Window;
+			this.ClientSize = new System.Drawing.Size(523, 274);
+			this.ControlBox = false;
+			this.Controls.Add(this.mNoResultsLabel);
+			this.Controls.Add(this.mThrobber);
+			this.Controls.Add(this.mLayout);
+			this.MinimumSize = new System.Drawing.Size(160, 96);
+			this.Name = "SearchWindow";
+			this.ShowInTaskbar = false;
+			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+			this.TopMost = true;
+			this.mLayout.ResumeLayout(false);
+			this.mLayout.PerformLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).EndInit();
+			this.mInfoBanner.ResumeLayout(false);
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).EndInit();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.TextBox mSearch;
+		private System.Windows.Forms.ListBox mResults;
+		private System.Windows.Forms.TableLayoutPanel mLayout;
+		private System.Windows.Forms.PictureBox mBanner;
+		private PictureBox mThrobber;
+		private Timer mResultsUpdater;
+		private Label mNoResultsLabel;
+		private Label mInfoLabel;
+		private Panel mInfoBanner;
+		private PictureBox mInfoBannerImage;
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchWindow.cs b/AutoTypeSearch/SearchWindow.cs
new file mode 100755
index 0000000..363b898
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.cs
@@ -0,0 +1,925 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Media;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Resources;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Collections;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	public partial class SearchWindow : Form
+	{
+		private const int SecondLineInset = 10;
+
+		// HACK to work around mono bug
+		private static readonly FieldInfo sMonoListBoxTopIndex = typeof(ListBox).GetField("top_index", BindingFlags.Instance | BindingFlags.NonPublic);
+
+		private readonly MainForm mMainForm;
+		private readonly Bitmap mBannerImage;
+		private readonly Searcher mSearcher;
+
+		private readonly Stream mThrobberImageStream;
+
+		private int? mWindowTopBorderHeight;
+		private int mBannerWidth = -1;
+		private int mMaximumExpandHeight;
+		private bool mManualSizeApplied;
+		private SearchResults mCurrentSearch;
+		private SearchResults mLastResultsUpdated;
+		private int mLastResultsUpdatedNextAvailableIndex;
+
+		#region Opening
+		public SearchWindow()
+		{
+			InitializeComponent();
+
+			// Mono can't load animated gifs from resx without crashing, so load it from an embedded resource instead
+			try
+			{
+				mThrobberImageStream = GetType().Assembly.GetManifestResourceStream("AutoTypeSearch.Throbber.gif");
+				if (mThrobberImageStream != null)
+				{
+					mThrobber.Image = Image.FromStream(mThrobberImageStream);
+				}
+			}
+			catch (Exception ex)
+			{
+				Debug.Fail("Failed to load Throbber.gif from embedded resource: " + ex.Message);
+			}
+
+			GlobalWindowManager.CustomizeControl(this);
+			UIUtil.SetExplorerTheme(mResults, true);
+			SetItemHeight();
+		}
+
+		public SearchWindow(MainForm mainForm, string infoBanner) : this()
+		{
+			mMainForm = mainForm;
+
+			mInfoBanner.Height = Math.Max(mInfoBannerImage.Height, mInfoLabel.Font.Height) + mInfoBanner.Margin.Vertical;
+			mInfoLabel.Padding = new Padding(0, (mInfoBanner.Height - mInfoLabel.Font.Height) / 2, 0, 0);
+			mInfoLabel.Text = infoBanner;
+
+			if (infoBanner == null)
+			{
+				mInfoBanner.Visible = false;
+				mInfoBanner.Height = 0;
+			}
+			
+			mSearcher = new Searcher(mMainForm.DocumentManager.GetOpenDatabases().ToArray());
+
+			Icon = mMainForm.Icon;
+			using (var bannerIcon = new Icon(Icon, 48, 48))
+			{
+				mBannerImage = bannerIcon.ToBitmap();
+			}
+			UpdateBanner();
+
+			ShowThrobber = false;
+
+			FontUtil.AssignDefaultItalic(mNoResultsLabel);
+		}
+
+
+		protected override void OnCreateControl()
+		{
+			base.OnCreateControl();
+
+			if (NativeMethods.IsWindows10())
+			{
+				mWindowTopBorderHeight = PointToScreen(Point.Empty).Y - this.Top;
+				NativeMethods.RefreshWindowFrame(Handle);
+			}
+
+			var windowRect = Settings.Default.WindowPosition;
+			var collapsedWindowRect = windowRect;
+			
+			collapsedWindowRect.Height = mSearch.Bottom + (Height - ClientSize.Height);
+
+			MinimumSize = new Size(MinimumSize.Width, collapsedWindowRect.Height);
+
+			if (windowRect.IsEmpty || !IsOnScreen(collapsedWindowRect))
+			{
+				windowRect = new Rectangle(0, 0, Width, Height);
+				Height = collapsedWindowRect.Height;
+
+				CenterToScreen();
+			}
+			else
+			{
+				Location = windowRect.Location;
+				Size = collapsedWindowRect.Size;
+			}
+
+			mMaximumExpandHeight = Math.Max(windowRect.Height, MinimumSize.Height + mResults.ItemHeight);
+		}
+		
+
+		private static bool IsOnScreen(Rectangle rectangle)
+		{
+			return Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(rectangle));
+		}
+
+		private void SetItemHeight()
+		{
+			mResults.ItemHeight = mResults.Font.Height * 2 + 2;
+		}
+
+		protected override void WndProc(ref Message m)
+		{
+			if (mWindowTopBorderHeight.HasValue)
+			{
+				NativeMethods.RemoveWindowFrameTopBorder(ref m, mWindowTopBorderHeight.Value);
+			}
+			base.WndProc(ref m);
+		}
+
+		#endregion
+
+		#region Closing
+		protected override void OnActivated(EventArgs e)
+		{
+			base.OnActivated(e);
+			Deactivate += OnDeactivate;
+		}
+
+		private void OnDeactivate(object sender, EventArgs eventArgs)
+		{
+			Close();
+		}
+
+		protected override void OnClosed(EventArgs e)
+		{
+			Deactivate -= OnDeactivate;
+			base.OnClosed(e);
+		}
+
+		/// 
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				if (mBannerImage != null)
+				{
+					mBannerImage.Dispose();
+				}
+				if (mThrobber.Image != null)
+				{
+					mThrobber.Image.Dispose();
+					mThrobber.Image = null;
+					mThrobberImageStream.Dispose();
+				}
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+		#endregion
+
+		#region Item Drawing
+		private void mResults_DrawItem(object sender, DrawItemEventArgs e)
+		{
+			var searchResult = mResults.Items[e.Index] as SearchResult;
+			if (searchResult == null)
+			{
+				Debug.Fail("Unexpected item in mResults");
+// ReSharper disable once HeuristicUnreachableCode - Not unreachable
+				return;
+			}
+			var drawingArea = e.Bounds;
+			drawingArea.Height--; // Leave room for a dividing line at the bottom
+			
+			if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
+			{
+				DrawBorderedRectangle(e.Graphics, drawingArea, SystemColors.Highlight);
+			}
+			else
+			{
+				e.Graphics.FillRectangle(SystemBrushes.Window, drawingArea);
+			}
+
+			var image = GetImage(searchResult.Database, searchResult.Entry.CustomIconUuid, searchResult.Entry.IconId);
+			var imageMargin = (drawingArea.Height - image.Height) / 2;
+			e.Graphics.DrawImage(image, drawingArea.Left + imageMargin, drawingArea.Top + imageMargin, image.Width, image.Height);
+
+			var textLeftMargin = drawingArea.Left + imageMargin * 2 + image.Width;
+			var textBounds = new Rectangle(textLeftMargin, drawingArea.Top + 1, drawingArea.Width - textLeftMargin - 1, drawingArea.Height - 2);
+
+			var line1Bounds = textBounds;
+			line1Bounds.Height = e.Font.Height;
+			var line2Bounds = line1Bounds;
+			line2Bounds.Y += line2Bounds.Height - 1;
+			line2Bounds.X += SecondLineInset;
+			line2Bounds.Width -= SecondLineInset;
+
+			var resultInTitleField = searchResult.FieldName == PwDefs.TitleField;
+
+			var title = (resultInTitleField ? searchResult.FieldValue : searchResult.Title).Replace('\n', ' '); // The FieldValue may have references resolved, whereas the title is always read directly.
+
+			var uniqueTitlePartWidth = 0;
+			if (!String.IsNullOrEmpty(searchResult.UniqueTitlePart))
+			{
+				var uniqueTitlePart = searchResult.UniqueTitlePart.Replace('\n', ' ');
+
+				var titleWidth = TextRenderer.MeasureText(e.Graphics, title, e.Font, line1Bounds.Size, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+
+				var availableWidthForUniqueTitlePart = line1Bounds.Width - titleWidth;
+				if (availableWidthForUniqueTitlePart > 20) // Don't bother including a unique part if there's no room for it
+				{
+					var uniqueTitlePartReversed = ReverseString(uniqueTitlePart);
+
+					uniqueTitlePartWidth = TextRenderer.MeasureText(e.Graphics, uniqueTitlePartReversed, e.Font, new Size(availableWidthForUniqueTitlePart, line1Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+					uniqueTitlePart = ReverseString(uniqueTitlePartReversed);
+
+					TextRenderer.DrawText(e.Graphics, uniqueTitlePart, e.Font, new Rectangle(line1Bounds.X, line1Bounds.Y, uniqueTitlePartWidth, line1Bounds.Height), SystemColors.GrayText, TextFormatFlags.NoPadding);
+				}
+			}
+
+			var titleBounds = new Rectangle(line1Bounds.X + uniqueTitlePartWidth, line1Bounds.Y, line1Bounds.Width - uniqueTitlePartWidth, line1Bounds.Height);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Highlight title in first line.
+				DrawHighlight(e, titleBounds, title, searchResult.Start, searchResult.Length);
+			}
+
+			TextRenderer.DrawText(e.Graphics, searchResult.Title, e.Font, titleBounds, SystemColors.WindowText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Use Username for second line.
+				TextRenderer.DrawText(e.Graphics, KPRes.UserName + ": " + searchResult.Entry.Strings.ReadSafeEx(PwDefs.UserNameField), e.Font, line2Bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+			}
+			else
+			{
+				// Found the result in not title field. Show the matching result on second line
+				
+				var fieldValue = searchResult.FieldValue.Replace('\n',' ');
+				var fieldNamePrefix = GetDisplayFieldName(searchResult.FieldName) + ": ";
+
+				var remainingSpace = line2Bounds.Width;
+				var fieldNamePrefixWidth = TextRenderer.MeasureText(e.Graphics, fieldNamePrefix, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+				remainingSpace -= fieldNamePrefixWidth;
+
+				int fieldValueHighlightWidth = 0, fieldValueLeftContextWidth = 0, fieldValueRightContextWidth = 0;
+
+				var leftContext = fieldValue.Substring(0, searchResult.Start);
+				var highlight = fieldValue.Substring(searchResult.Start, searchResult.Length);
+				var rightContext = fieldValue.Substring(searchResult.Start + searchResult.Length);
+
+				if (searchResult.Length == 0)
+				{
+					fieldValueHighlightWidth = remainingSpace;
+				}
+				else
+				{
+					if (remainingSpace > 0)
+					{
+						var availableSpace = remainingSpace;
+						fieldValueHighlightWidth = TextRenderer.MeasureText(e.Graphics, highlight, e.Font, new Size(availableSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						remainingSpace -= fieldValueHighlightWidth;
+					}
+
+					// Of the space remaining, divide it equally between that which comes before, and that which comes after
+					if (!String.IsNullOrEmpty(leftContext))
+					{
+						var leftContextReversed = ReverseString(leftContext);
+						fieldValueLeftContextWidth = TextRenderer.MeasureText(e.Graphics, leftContextReversed, e.Font, new Size(remainingSpace / 2, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+						if (fieldValueLeftContextWidth > remainingSpace)
+						{
+							// Always allow space for the minimal left context
+							fieldValueHighlightWidth -= (fieldValueLeftContextWidth - remainingSpace);
+							remainingSpace = 0;
+						}
+						else
+						{
+							remainingSpace -= fieldValueLeftContextWidth;							
+						}
+						
+						// Replace left context with the truncated reversed left context.
+						leftContext = ReverseString(leftContextReversed);
+					}
+
+					if (remainingSpace > 0 && !String.IsNullOrEmpty(rightContext))
+					{
+						fieldValueRightContextWidth = TextRenderer.MeasureText(e.Graphics, rightContext, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						if (fieldValueRightContextWidth > remainingSpace)
+						{
+							fieldValueRightContextWidth = 0;
+						}
+					}
+				}
+
+				// Now draw it all
+				var bounds = line2Bounds;
+				bounds.Width = fieldNamePrefixWidth;
+				TextRenderer.DrawText(e.Graphics, fieldNamePrefix, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				if (fieldValueLeftContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueLeftContextWidth;
+					TextRenderer.DrawText(e.Graphics, leftContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding); // No ellipsis as the leftContext string has already been truncated appropriately
+				}
+				if (fieldValueHighlightWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueHighlightWidth;
+
+					if (searchResult.Length > 0)
+					{
+						DrawHighlightRectangle(e, bounds);
+					}
+					TextRenderer.DrawText(e.Graphics, highlight, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+				if (fieldValueRightContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueRightContextWidth;
+					TextRenderer.DrawText(e.Graphics, rightContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+			}
+
+			e.Graphics.DrawLine(SystemPens.ButtonFace, drawingArea.Left, drawingArea.Bottom, drawingArea.Right, drawingArea.Bottom);
+		}
+
+		private static string ReverseString(string value)
+		{
+			return new String(value.ToCharArray().TakeWhile(c => c != '\0').Reverse().ToArray());
+		}
+
+		private static void DrawHighlight(DrawItemEventArgs e, Rectangle lineBounds, string text, int highlightFrom, int highlightLength)
+		{
+			var highlightX = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width;
+			var highlightWidth = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom + highlightLength), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width - highlightX;
+
+			DrawHighlightRectangle(e, new Rectangle(lineBounds.Left + highlightX, lineBounds.Top, highlightWidth, lineBounds.Height));
+		}
+
+		private static void DrawHighlightRectangle(DrawItemEventArgs e, Rectangle rectangle)
+		{
+			DrawBorderedRectangle(e.Graphics, rectangle, Color.PaleTurquoise);
+		}
+
+		private static void DrawBorderedRectangle(Graphics graphics, Rectangle rectangle, Color colour)
+		{
+			var border = rectangle;
+			border.Width--;
+			border.Height--;
+
+			using (var brush = new SolidBrush(MergeColors(colour, SystemColors.Window, 0.2)))
+			{
+				graphics.FillRectangle(brush, rectangle);
+			}
+			using (var pen = new Pen(colour, 1f))
+			{
+				graphics.DrawRectangle(pen, border);
+			}
+		}
+
+		private Image GetImage(PwDatabase database, PwUuid customIconId, PwIcon iconId)
+		{
+			Image image = null;
+			if (!customIconId.Equals(PwUuid.Zero))
+			{
+				image = database.GetCustomIcon(customIconId, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16));
+			}
+			if (image == null)
+			{
+				try { image = mMainForm.ClientIcons.Images[(int)iconId]; }
+				catch (Exception) { Debug.Assert(false); }
+			}
+
+			return image;
+		}
+
+		private static string GetDisplayFieldName(string fieldName)
+		{
+			switch (fieldName)
+			{
+				case PwDefs.TitleField:
+					return KPRes.Title;
+				case PwDefs.UserNameField:
+					return KPRes.UserName;
+				case PwDefs.PasswordField:
+					return KPRes.Password;
+				case PwDefs.UrlField:
+					return KPRes.Url;
+				case PwDefs.NotesField:
+					return KPRes.Notes;
+				case AutoTypeSearchExt.TagsVirtualFieldName:
+					return KPRes.Tags;
+				default:
+					return fieldName;
+			}
+		}
+
+		public static Color MergeColors(Color from, Color to, double amount)
+		{
+			var r = (byte)((from.R * amount) + to.R * (1 - amount));
+			var g = (byte)((from.G * amount) + to.G * (1 - amount));
+			var b = (byte)((from.B * amount) + to.B * (1 - amount));
+			return Color.FromArgb(r, g, b);
+		}
+		#endregion
+
+		#region Mouse tracking
+		private Point mMouseEntryPosition;
+		
+		private void mResults_MouseEnter(object sender, EventArgs e)
+		{
+			mMouseEntryPosition = MousePosition;
+		}
+
+		private void mResults_MouseMove(object sender, MouseEventArgs e)
+		{
+			// Discard the location the mouse has on entering the control (as it may be that the control has just moved under the mouse, not the other way around)
+			if (MousePosition == mMouseEntryPosition)
+			{
+				return;
+			}
+
+			// Hot tracking
+			var hoverIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (hoverIndex >= 0 && mResults.SelectedIndex != hoverIndex)
+			{
+				if (mResults.GetItemRectangle(hoverIndex).Bottom <= mResults.ClientRectangle.Bottom)
+				{
+					mResults.SelectedIndex = hoverIndex;
+				}
+				else
+				{
+					// Avoid the control scrolling
+					mResults.BeginUpdate();
+					var topIndex = mResults.TopIndex;
+					mResults.SelectedIndex = hoverIndex;
+					mResults.TopIndex = topIndex;
+					mResults.EndUpdate();
+				}
+			}
+		}
+		#endregion
+
+		#region Resizing
+		protected override void OnResizeBegin(EventArgs e)
+		{
+			// Stop automatically sizing - the user is picking a size they want.
+			mManualSizeApplied = true;
+			base.OnResizeBegin(e);
+		}
+
+		protected override void OnResize(EventArgs e)
+		{
+			base.OnResize(e);
+
+			UpdateBanner();
+
+			mResults.Invalidate();
+		}
+
+		protected override void OnResizeEnd(EventArgs e)
+		{
+			base.OnResizeEnd(e);
+
+			if (Height > MinimumSize.Height && Height != mMaximumExpandHeight)
+			{
+				mMaximumExpandHeight = Math.Max(Height, MinimumSize.Height + mResults.ItemHeight);
+			}
+			else
+			{
+				mManualSizeApplied = false;
+			}
+
+			Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+		}
+
+		private void UpdateBanner()
+		{
+			if (mBannerImage != null)
+			{
+				BannerFactory.UpdateBanner(this, mBanner, mBannerImage, PwDefs.ProductName, Resources.BannerText, ref mBannerWidth);
+			}
+		}
+
+		private void mSearch_LocationChanged(object sender, EventArgs e)
+		{
+			mThrobber.Location = new Point(mSearch.Right - mThrobber.Width - mThrobber.Margin.Right, mSearch.Top + (mSearch.Height - mThrobber.Height) / 2);
+		}
+
+		private void mResults_LocationChanged(object sender, EventArgs e)
+		{
+			mNoResultsLabel.Top = mResults.Top + (mResults.ItemHeight - mNoResultsLabel.Height) / 2;
+		}
+		#endregion
+
+		#region Searching
+		private static readonly SearchResultPrecedence SearchResultPrecedenceComparer = new SearchResultPrecedence();
+		private void mSearch_TextChanged(object sender, EventArgs e)
+		{
+			if (mSearch.Text.Length < 2)
+			{
+				// Stop searching
+				mResultsUpdater.Enabled = false;
+				ShowThrobber = false;
+				Height = MinimumSize.Height;
+				mManualSizeApplied = false;
+				mResults.Items.Clear();
+				mLastResultsUpdated = null;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			else
+			{
+				// Start searching
+				mNoResultsLabel.Visible = false;
+				mCurrentSearch = mSearcher.Search(mSearch.Text);
+				mResultsUpdater.Enabled = true;
+				ShowThrobber = true;
+				mResultsUpdater_Tick(null, EventArgs.Empty); // Quick poke just in case the results are already done.
+			}
+		}
+
+		[SuppressMessage("ReSharper", "CoVariantArrayConversion", Justification = "Object arrays for Listbox.Items, known to be of correct type")]
+		private void mResultsUpdater_Tick(object sender, EventArgs e)
+		{
+			if (mLastResultsUpdated != mCurrentSearch)
+			{
+				// Clear out old results and replace with new ones
+				mResults.Items.Clear();
+				mLastResultsUpdated = mCurrentSearch;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			var existingResultsCount = mResults.Items.Count;
+			
+			bool complete;
+			var newResults = mLastResultsUpdated.GetAvailableResults(ref mLastResultsUpdatedNextAvailableIndex, out complete);
+			if (newResults.Length > 0)
+			{
+				mResults.BeginUpdate();
+				
+				SearchResult[] allResults;
+				if (existingResultsCount > 0)
+				{
+					allResults = new SearchResult[existingResultsCount + newResults.Length];
+					mResults.Items.CopyTo(allResults, 0);
+					newResults.CopyTo(allResults, existingResultsCount);
+
+					mResults.Items.Clear();
+				}
+				else
+				{
+					allResults = newResults;
+				}
+
+				CalculateUniqueTitles(allResults);
+
+				Array.Sort(allResults, SearchResultPrecedenceComparer);
+				mResults.Items.AddRange(allResults);
+				
+				mResults.EndUpdate();
+
+				if (allResults.Length > 0)
+				{
+					if (mResults.SelectedIndex == -1)
+					{
+						try
+						{
+							// HACK to work around mono bug
+							if (sMonoListBoxTopIndex != null)
+							{
+								sMonoListBoxTopIndex.SetValue(mResults, 1); // Set the top_index to 1 so that when selected index is set to 0, and calls EnsureVisible(0), it follows the index < top_index pass and not the broken index >= top_index + rows path. 
+							}
+
+							mResults.SelectedIndex = 0;
+							mResults.TopIndex = 0;
+						}
+						catch (Exception ex)
+						{
+							Debug.Fail("Failed to set selection on count of " + allResults.Length + ": " + ex.Message);
+						}
+					}
+
+					if (!mManualSizeApplied)
+					{
+						Height = Math.Min(mMaximumExpandHeight, MinimumSize.Height + (allResults.Length * mResults.ItemHeight));
+					}
+				}
+			}
+
+			if (complete)
+			{
+				ShowThrobber = false;
+				mResultsUpdater.Enabled = false;
+
+				if (mResults.Items.Count == 0)
+				{
+					mNoResultsLabel.Visible = true;
+					Height = MinimumSize.Height + mResults.ItemHeight;
+					mManualSizeApplied = false;
+				}
+			}
+		}
+
+		private void CalculateUniqueTitles(IEnumerable results, int depth = 0)
+		{
+			// Where results have identical titles, include group titles to make them unique
+			depth += 1;
+
+			// First create a lookup by title
+			var titles = new Dictionary>();
+			foreach (var searchResult in results)
+			{
+				List resultsWithSameTitle;
+				if (titles.TryGetValue(searchResult.UniqueTitle, out resultsWithSameTitle))
+				{
+					resultsWithSameTitle.Add(searchResult);
+				}
+				else
+				{
+					titles.Add(searchResult.UniqueTitle, new List { searchResult });
+				}
+			}
+
+			// Attempt to unique-ify any non-unique titles
+			foreach (var resultsSharingTitle in titles.Values)
+			{
+				if (resultsSharingTitle.Count > 1)
+				{
+					var titlesModified = false;
+					foreach (var searchResult in resultsSharingTitle)
+					{
+						titlesModified |= searchResult.SetUniqueTitleDepth(depth);
+					}
+
+					if (titlesModified)
+					{
+						// Recurse in case of continuing non-uniqueness
+						CalculateUniqueTitles(resultsSharingTitle, depth);
+					}
+				}
+			}
+		}
+
+		private class SearchResultPrecedence : IComparer
+		{
+			public int Compare(SearchResult x, SearchResult y)
+			{
+				// First precedence is that if the result is the start of the field value, it's higher precedence than if it doesn't.
+				var result = -(x.Start == 0).CompareTo(y.Start == 0);
+
+				// Second precedence is that the start of the title field is higher precedence than the start of any other field
+				if (result == 0)
+				{
+					result = -(x.FieldName == PwDefs.TitleField).CompareTo(y.FieldName == PwDefs.TitleField);
+				}
+
+				// Both start the title field, so both equal. Have to have consistent ordering, so return final precedence based search index
+				if (result == 0)
+				{
+					result = x.ResultIndex.CompareTo(y.ResultIndex);
+				}
+				
+				return result;
+			}
+		}
+
+		private bool ShowThrobber
+		{
+			get { return mThrobber.Visible; }
+			set
+			{
+				if (value != ShowThrobber)
+				{
+					if (value)
+					{
+						mThrobber.Visible = true;
+
+						// Set the margin on the textbox to allow room for the throbber
+						NativeMethods.SetTextBoxRightMargin(mSearch, mThrobber.Width + mThrobber.Margin.Right);
+					}
+					else
+					{
+						mThrobber.Visible = false;
+
+						NativeMethods.SetTextBoxRightMargin(mSearch, 0);
+					}
+				}
+			}
+		}
+		#endregion
+
+		private void mBannerImage_MouseDown(object sender, MouseEventArgs e)
+		{
+			// Allow drag by banner image
+			if (e.Button == MouseButtons.Left)
+			{
+				if (e.Clicks == 2)
+				{
+					// Re-center the form on double-click
+					CenterToScreen();
+
+					Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+				}
+				else if (!NativeLib.IsUnix())
+				{
+					NativeMethods.StartFormDrag(this);
+				}
+			}
+		}
+
+		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+		{
+			switch (keyData)
+			{
+				case Keys.Escape:
+					Close();
+					return true;
+				case Keys.Up:
+					TryChangeSelection(-1);
+					return true;
+				case Keys.Down:
+					TryChangeSelection(1);
+					return true;
+				case Keys.PageUp:
+					TryChangeSelection(-mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.PageDown:
+					TryChangeSelection(mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.Home | Keys.Control:
+					mResults.SelectedIndex = 0;
+					return true;
+				case Keys.End | Keys.Control:
+					mResults.SelectedIndex = mResults.Items.Count - 1;
+					return true;
+				case Keys.Enter:
+					PerformAction(Settings.Default.DefaultAction, mResults.SelectedItem as SearchResult);
+					break;
+				case Keys.Enter | Keys.Shift:
+					PerformAction(Settings.Default.AlternativeAction, mResults.SelectedItem as SearchResult);
+					break;
+			}
+			
+			return base.ProcessCmdKey(ref msg, keyData);
+		}
+
+		#region Selection Changing
+
+		protected override void OnMouseWheel(MouseEventArgs e)
+		{
+			mResults.TopIndex -= (e.Delta / Math.Abs(e.Delta));
+		}
+
+		private void TryChangeSelection(int delta)
+		{
+			if (mResults.Items.Count > 0)
+			{
+				mResults.SelectedIndex = Math.Max(Math.Min(mResults.Items.Count - 1, mResults.SelectedIndex + delta), 0);
+			}
+		}
+		#endregion
+
+		#region Actions
+
+		private void mResults_MouseClick(object sender, MouseEventArgs e)
+		{
+			var clickIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (clickIndex >= 0)
+			{
+				var clickedResult = mResults.Items[clickIndex] as SearchResult;
+				if (clickedResult != null)
+				{
+					PerformAction((ModifierKeys & Keys.Shift) == Keys.Shift ? Settings.Default.AlternativeAction : Settings.Default.DefaultAction, clickedResult);
+				}
+			}
+		}
+
+		private void PerformAction(Actions action, SearchResult searchResult)
+		{
+			Close();
+
+			if (searchResult != null)
+			{
+				switch (action)
+				{
+					case Actions.PerformAutoType:
+						AutoTypeEntry(searchResult);
+						break;
+					case Actions.EditEntry:
+						EditEntry(searchResult);
+						break;
+					case Actions.ShowEntry:
+						ShowEntry(searchResult);
+						break;
+					case Actions.OpenEntryUrl:
+						OpenEntryUrl(searchResult);
+						break;
+					case Actions.CopyPassword:
+						CopyPassword(searchResult);
+						break;
+					default:
+						throw new ArgumentOutOfRangeException("action");
+				}
+			}
+		}
+
+		private void AutoTypeEntry(SearchResult searchResult)
+		{
+			bool result;
+			if (ActiveForm != null)
+			{
+				result = AutoType.PerformIntoPreviousWindow(mMainForm, searchResult.Entry, searchResult.Database);
+			}
+			else
+			{
+				result = AutoType.PerformIntoCurrentWindow(searchResult.Entry, searchResult.Database);
+			}
+			if (!result)
+			{
+				SystemSounds.Beep.Play();
+
+				if (Settings.Default.AlternativeAction != Actions.PerformAutoType)
+				{
+					PerformAction(Settings.Default.AlternativeAction, searchResult);
+				}
+			}
+		}
+
+		private void EditEntry(SearchResult searchResult)
+		{
+			using (var entryForm = new PwEntryForm())
+			{
+				mMainForm.MakeDocumentActive(mMainForm.DocumentManager.FindDocument(searchResult.Database));
+				
+				entryForm.InitEx(searchResult.Entry, PwEditMode.EditExistingEntry, searchResult.Database, mMainForm.ClientIcons, false, false);
+
+				ShowForegroundDialog(entryForm);
+
+				mMainForm.UpdateUI(false, null, searchResult.Database.UINeedsIconUpdate, null, true, null, entryForm.HasModifiedEntry);
+			}
+		}
+
+// ReSharper disable once UnusedMethodReturnValue.Local - Generic helper, result may be used in future
+		private DialogResult ShowForegroundDialog(Form form)
+		{
+			mMainForm.EnsureVisibleForegroundWindow(false, false);
+			form.StartPosition = FormStartPosition.CenterScreen;
+			if (mMainForm.IsTrayed())
+			{
+				form.ShowInTaskbar = true;
+			}
+
+			form.Shown += ActivateFormOnShown;
+			return form.ShowDialog(mMainForm);
+		}
+
+		private static void ActivateFormOnShown(object sender, EventArgs eventArgs)
+		{
+			var form = (Form)sender;
+			form.Shown -= ActivateFormOnShown;
+			form.Activate();
+		}
+
+		private void ShowEntry(SearchResult searchResult)
+		{
+			// Show this entry
+			mMainForm.UpdateUI(false, mMainForm.DocumentManager.FindDocument(searchResult.Database), true, searchResult.Entry.ParentGroup, true, null, false, null);
+			mMainForm.SelectEntries(new PwObjectList { searchResult.Entry }, true, true);
+			mMainForm.EnsureVisibleEntry(searchResult.Entry.Uuid);
+			mMainForm.UpdateUI(false, null, false, null, false, null, false);
+			mMainForm.EnsureVisibleForegroundWindow(true, true);
+		}
+
+		private void OpenEntryUrl(SearchResult searchResult)
+		{
+			WinUtil.OpenEntryUrl(searchResult.Entry);
+		}
+
+		private void CopyPassword(SearchResult searchResult)
+		{
+			if (ClipboardUtil.Copy(searchResult.Entry.Strings.ReadSafe(PwDefs.PasswordField), true, true, searchResult.Entry,
+									mMainForm.DocumentManager.SafeFindContainerOf(searchResult.Entry),
+									IntPtr.Zero))
+			{
+				mMainForm.StartClipboardCountdown();
+			}
+		}
+		
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.resx b/AutoTypeSearch/SearchWindow.resx
new file mode 100755
index 0000000..8ef82f0
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.resx
@@ -0,0 +1,123 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    17, 17
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Searcher.cs b/AutoTypeSearch/Searcher.cs
new file mode 100755
index 0000000..433ae94
--- /dev/null
+++ b/AutoTypeSearch/Searcher.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class Searcher
+	{
+		private readonly PwDatabase[] mDatabases;
+		private readonly Dictionary mSearches = new Dictionary();
+
+		public Searcher(PwDatabase[] databases)
+		{
+			mDatabases = databases;
+		}
+
+		public SearchResults Search(string term)
+		{
+			if (term.Length < 2)
+			{
+				throw new ArgumentException("Search term must be at least 2 characters");
+			}
+
+			SearchResults parentResults = null;
+
+			var termParent = term;
+			while (termParent.Length >= 2)
+			{
+				if (mSearches.TryGetValue(termParent, out parentResults))
+				{
+					if (termParent == term)
+					{
+						// This is an exact duplicate search, so return it.
+						return parentResults;
+					}
+
+					// Found an existing search for a parent of the term, start from there.
+					break;
+				}
+		
+				// No existing search for termParent found, try less.
+				termParent = termParent.Remove(termParent.Length - 1, 1);
+			}
+
+			SearchResults searchResults;
+			if (parentResults == null)
+			{
+				// No parent found at all, start from scratch
+				searchResults = new SearchResults(GetCountOfAllDatabaseEntries(), term);
+
+				var rootSearchThread = new Thread(RootSearchWorker) { Name = term };
+				rootSearchThread.Start(searchResults);
+			}
+			else
+			{
+				searchResults = parentResults.CreateChildResults(term);
+
+				var childSearchThread = new Thread(ChildSearchWorker) { Name = term };
+				childSearchThread.Start(new ChildSearchWorkerState{ Source = parentResults, Results = searchResults });
+			}
+
+			mSearches.Add(term, searchResults);
+
+			return searchResults;
+		}
+
+		private int GetCountOfAllDatabaseEntries()
+		{
+			return (from database in mDatabases select (int)database.RootGroup.GetEntriesCount(true)).Sum();
+		}
+
+		private void RootSearchWorker(object stateObject)
+		{
+			var results = (SearchResults)stateObject;
+			var excludeExpired = Settings.Default.ExcludeExpired;
+			var searchStartTime = DateTime.Now;
+
+			foreach (var database in mDatabases)
+			{
+				SearchGroup(database, database.RootGroup, results, excludeExpired, searchStartTime);	
+			}
+
+			results.SetComplete();
+		}
+
+		/// 
+		/// Recursively search  and its children, adding results to 
+		/// 
+		private void SearchGroup(PwDatabase context, PwGroup group, SearchResults results, bool excludeExpired, DateTime searchStartTime)
+		{
+			if (group.EnableSearching ?? true) // Group will only be searched if it's parent enabled searching, so if it is inherit (null) or true, search it.
+			{
+				foreach (var childGroup in group.Groups)
+				{
+					SearchGroup(context, childGroup, results, excludeExpired, searchStartTime);
+				}
+
+				foreach (var entry in group.Entries)
+				{
+					if (!(excludeExpired && entry.Expires && searchStartTime > entry.ExpiryTime))
+					{
+						results.AddResultIfMatchesTerm(context, entry);
+					}
+				}
+			}
+		}
+
+		private struct ChildSearchWorkerState
+		{
+			public SearchResults Source;
+			public SearchResults Results;
+		}
+		private void ChildSearchWorker(object stateObject)
+		{
+			var state = (ChildSearchWorkerState)stateObject;
+
+			bool complete;
+			var index = 0;
+			do
+			{
+				foreach (var entry in state.Source.GetAvailableResults(ref index, out complete))
+				{
+					state.Results.AddResultIfMatchesTerm(entry);
+				}
+			} while (!complete);
+
+			state.Results.SetComplete();
+		}
+	}
+}
diff --git a/AutoTypeSearch/Throbber.gif b/AutoTypeSearch/Throbber.gif
new file mode 100755
index 0000000..494d426
--- /dev/null
+++ b/AutoTypeSearch/Throbber.gif
Binary files differ
diff --git a/AutoTypeSearch/app.config b/AutoTypeSearch/app.config
new file mode 100755
index 0000000..1370758
--- /dev/null
+++ b/AutoTypeSearch/app.config
@@ -0,0 +1,60 @@
+
+
+    
+        
+            
+        
+    
+    
+        
+            
+                True
+            
+            
+                False
+            
+            
+                True
+            
+            
+                True
+            
+            
+                True
+            
+            
+                True
+            
+            
+                False
+            
+            
+                0, 0, 0, 0
+            
+            
+                True
+            
+            
+                False
+            
+            
+                True
+            
+            
+                False
+            
+            
+                False
+            
+            
+                PerformAutoType
+            
+            
+                EditEntry
+            
+            
+                None
+            
+        
+    
+
\ No newline at end of file
diff --git a/CreatePlgX.bat b/CreatePlgX.bat
new file mode 100755
index 0000000..59b9aa0
--- /dev/null
+++ b/CreatePlgX.bat
@@ -0,0 +1,20 @@
+@echo off
+cd %~dp0
+
+echo Deleting existing PlgX folder
+rmdir /s /q PlgX
+
+echo Creating PlgX folder
+mkdir PlgX
+
+echo Copying files
+xcopy "AutoTypeSearch" PlgX /s /e /exclude:PlgXExclude.txt
+
+echo Compiling PlgX
+"../KeePass/KeePass.exe" /plgx-create "%~dp0PlgX" --plgx-prereq-kp:2.27
+
+echo Releasing PlgX
+move /y PlgX.plgx "Releases\Build Outputs\AutoTypeSearch.plgx"
+
+echo Cleaning up
+rmdir /s /q PlgX
diff --git a/PlgXExclude.txt b/PlgXExclude.txt
new file mode 100755
index 0000000..f626d58
--- /dev/null
+++ b/PlgXExclude.txt
@@ -0,0 +1,7 @@
+\bin\
+\obj\
+.user
+.sln
+.suo
+.pdb
+.xml
\ No newline at end of file
diff --git a/Readme.txt b/Readme.txt
new file mode 100755
index 0000000..96d2fc0
--- /dev/null
+++ b/Readme.txt
@@ -0,0 +1,103 @@
+AutoTypeSearch
+==============
+http://sourceforge.net/projects/autotypesearch
+
+
+This is a plugin to KeePass  to provide a quick searching capability as
+an enhancement to the global auto-type system. If a global auto-type is requested, but no matching
+entry for the active window is found, this plugin will show a quick as-you-type search window which
+lets you to easily pick the entry to auto-type.
+
+
+Installation
+------------
+Place AutoTypeSearch.plgx in your KeePass Plugins folder.
+
+
+Usage
+-----
+AutoTypeSearch is initially configured to automatically appear after an unsuccessful global
+auto-type. However, this can be changed in the KeePass Options window (an AutoTypeShow tab has
+been added). Here, a system-wide hot key can be configured to show the AutoTypeSearch window
+immediately. It is also possible to show the window by running KeePass.exe passing "/e1:AutoTypeSearch"
+as a command line parameter.
+
+Once the window is shown, usage is extremely simple. Just start typing, and AutoTypeSearch will
+search your database for matching entries. By default, the Title, Url, Notes, Tags, and Custom Fields
+will be searched, but this can be configured in the AutoTypeShow tab of the KeePass Options window.
+
+Protected fields (like Password) will not be searched.
+
+The arrow keys can be used to move the selection in the list of results, then press Enter to auto-
+type the selected entry. Alternatively, press Shift+Enter to open the entry instead of auto-typing it.
+(These actions can also be customised in the Options window.) Clicking and Shift-Clicking an entry will
+also perform those actions.
+
+
+Uninstallation
+--------------
+Delete AutoTypeSearch.plgx from your KeePass Plugins folder.
+
+
+Checking for updates
+--------------------
+If you want to use the KeePass Check for Updates function to check for updates to this plugin
+then it requires the SourceForgeUpdateChecker plugin to be installed too:
+http://sourceforge.net/projects/kpsfupdatechecker
+
+
+Bug Reporting, Questions, Comments, Feedback, Donations
+-------------------------------------------------------
+Please use the SourceForge project page: 
+Bugs can be reported using the issue tracker, for anything else, a discussion forum is available.
+
+
+Changelog
+---------
+v0.1
+ Initial release
+
+v0.2
+ Added information banner when search is shown as a result of an unsuccessful global auto-type
+ Compatibility with Linux/Mono
+
+v0.3
+ Added search result prioritisation for entries where the match is found at the start of the field
+
+v0.4
+ Added support for multiple databases. All currently open, unlocked, databases will be searched
+
+v0.5
+ Added support for KeePass 2.29 high resolution custom icons
+
+v0.6
+ Where title does not uniquely identify the results shown, now also shows the group name as context
+
+v0.7
+ Added support for the "Open entry URL" action. Use the Options window to choose this, if required.
+
+v0.8
+ Added support for the "Copy password" action. Use the Options window to choose this, if required.
+
+v0.9
+ Added workaround for mono bug under Linux that could cause an ArgumentOutOfRange crash when 
+  searching if only a single result is initially returned.
+
+v0.91
+ Fixed bug where up or down keys would cause an exception if there are no results to scroll through
+
+v0.10
+ Compatibility with KeePass 2.41 (No longer compatible with previous versions)
+
+v0.11
+ Diacritic (accent) insensitive searching
+
+v0.12
+ Removed ugly white top border under Windows 10
+
+v1.0
+ Compatibility with KeePass 2.42. For versions of KeePass prior to 2.42, use an 0.X version.
+
+Attributions
+------------
+Throbber image by FlipDarius http://www.mediawiki.org/wiki/File:Loading.gif
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..54be39f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+Releases/*
+!Releases/PackageRelease.bat
diff --git a/AutoTypeSearch/.gitignore b/AutoTypeSearch/.gitignore
new file mode 100644
index 0000000..114a799
--- /dev/null
+++ b/AutoTypeSearch/.gitignore
@@ -0,0 +1,357 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*[.json, .xml, .info]
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
diff --git a/AutoTypeSearch/Actions.cs b/AutoTypeSearch/Actions.cs
new file mode 100755
index 0000000..096c515
--- /dev/null
+++ b/AutoTypeSearch/Actions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Linq;
+
+namespace AutoTypeSearch
+{
+	internal enum Actions
+	{
+		PerformAutoType,
+		EditEntry,
+		ShowEntry,
+		OpenEntryUrl,
+		CopyPassword
+	}
+}
diff --git a/AutoTypeSearch/AutoTypeSearch.csproj b/AutoTypeSearch/AutoTypeSearch.csproj
new file mode 100755
index 0000000..7be4bdd
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.csproj
@@ -0,0 +1,127 @@
+
+
+  
+  
+    Debug
+    AnyCPU
+    {CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}
+    Library
+    Properties
+    AutoTypeSearch
+    AutoTypeSearch
+    v4.6.1
+    512
+    
+  
+  
+    true
+    full
+    false
+    ..\..\KeePass-Source\Build\KeePass\Debug\Plugins\AutoTypeSearch\
+    DEBUG;TRACE
+    prompt
+    4
+    false
+  
+  
+    pdbonly
+    false
+    bin\Release\
+    TRACE
+    prompt
+    4
+    false
+  
+  
+    
+      
+        
+          {10938016-DEE2-4A25-9A5A-8FD3444379CA}
+          KeePass
+          False
+        
+      
+    
+    
+      
+        
+          ..\..\KeePass\KeePass.exe
+          False
+        
+      
+    
+  
+  
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      Options.cs
+    
+    
+    
+      True
+      True
+      Resources.resx
+    
+    
+      True
+      True
+      Settings.settings
+    
+    
+    
+    
+    
+      Form
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+      Options.cs
+    
+    
+      ResXFileCodeGenerator
+      Resources.Designer.cs
+    
+    
+      SearchWindow.cs
+    
+  
+  
+    
+    
+      SettingsSingleFileGenerator
+      Settings.Designer.cs
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    IF $(ConfigurationName) == Release "$(ProjectDir)..\CreatePlgX.bat"
+  
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/AutoTypeSearch.sln b/AutoTypeSearch/AutoTypeSearch.sln
new file mode 100755
index 0000000..5812d0e
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearch.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTypeSearch", "AutoTypeSearch.csproj", "{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePass", "..\..\KeePass-Source\KeePass\KeePass.csproj", "{10938016-DEE2-4A25-9A5A-8FD3444379CA}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93BF1946-D769-4387-B47C-6269FBCE2303}"
+	ProjectSection(SolutionItems) = preProject
+		..\Releases\PackageRelease.bat = ..\Releases\PackageRelease.bat
+		..\Readme.txt = ..\Readme.txt
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD1AD3A1-EEEB-47C5-BB7E-43B59BDC9635}.Release|Any CPU.Build.0 = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{10938016-DEE2-4A25-9A5A-8FD3444379CA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTypeSearch/AutoTypeSearchExt.cs b/AutoTypeSearch/AutoTypeSearchExt.cs
new file mode 100755
index 0000000..850bcd6
--- /dev/null
+++ b/AutoTypeSearch/AutoTypeSearchExt.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Security;
+
+namespace AutoTypeSearch
+{
+// ReSharper disable once ClassNeverInstantiated.Global - Plugin instantiated by KeePass
+	public sealed class AutoTypeSearchExt : Plugin
+    {
+		private const string IpcEventName = "AutoTypeSearch";
+		private const int UnixAutoTypeWaitTime = 500; // Milliseconds
+		internal const string TagsVirtualFieldName = "***TAGS***";
+
+		private IPluginHost mHost;
+		private bool mAutoTypeSuccessful;
+		private string mLastAutoTypeWindowTitle;
+
+		public override string UpdateUrl
+		{
+			get { return "sourceforge-version://AutoTypeSearch/autotypesearch?-v(%5B%5Cd.%5D%2B)%5C.zip"; }
+		}
+
+		public override bool Initialize(IPluginHost host)
+		{
+			mHost = host;
+
+			IpcUtilEx.IpcEvent += OnIpcEvent;
+			GlobalWindowManager.WindowAdded += OnWindowAdded;
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed += HotKeyManager_HotKeyPressed;
+			}
+			AutoType.SequenceQueriesEnd += OnAutoTypeSequenceQueriesEnd;
+
+			Options.LoadSettings(host);
+
+			return true;
+		}
+
+		#region Unsuccessful AutoType Detection
+		private void OnAutoTypeSequenceQueriesEnd(object sender, SequenceQueriesEventArgs e)
+		{
+			// An auto-type has completed. Was it successful? Watch for an auto-type event, and for the UI thread unblocking. If the UI thread unblocks before the auto-type event, it wasn't successful.
+			// (hacky, yes, but no other means possible to detect failed auto-types at the time of writing)
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				mAutoTypeSuccessful = false;
+				mLastAutoTypeWindowTitle = e.TargetWindowTitle;
+				AutoType.FilterCompilePre += OnAutoType;
+
+				if (KeePassLib.Native.NativeLib.IsUnix())
+				{
+					// If Unix, can't rely on waiting for UI thread unblocking as the XDoTool mechanism calls DoEvents (in NativeMethods.TryXDoTool) before anything else.
+					// Instead, just wait half a second and hope for the best.
+					var timer = new Timer { Interval = UnixAutoTypeWaitTime };
+					timer.Tick += delegate
+					{
+						timer.Stop();
+						timer.Dispose();
+						OnAutoTypeEnd();
+					};
+					timer.Start();
+				}
+				else
+				{
+					mHost.MainWindow.BeginInvoke((Action)OnAutoTypeEnd);
+				}
+			}
+		}
+
+		private void OnAutoType(object sender, AutoTypeEventArgs autoTypeEventArgs)
+		{
+			// Detach event, we are only interested in a single invocation.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			mAutoTypeSuccessful = true;
+		}
+
+		private void OnAutoTypeEnd()
+		{
+			// Detach event, the auto-type failed, it won't be received now.
+			AutoType.FilterCompilePre -= OnAutoType;
+
+			if (!mAutoTypeSuccessful)
+			{
+				ShowSearch(String.Format(Resources.AutoTypeFailedMessage, mLastAutoTypeWindowTitle));
+			}
+		}
+		#endregion
+
+		#region Options
+		private void OnWindowAdded(object sender, GwmWindowEventArgs e)
+		{
+			var optionsForm = e.Form as OptionsForm;
+			if (optionsForm != null)
+			{
+				Options.AddToWindow(optionsForm);
+				return;
+			}
+
+			if (Settings.Default.ShowOnFailedAutoType)
+			{
+				var autoTypeCtxForm = e.Form as AutoTypeCtxForm;
+				if (autoTypeCtxForm != null)
+				{
+					mAutoTypeSuccessful = true; // Don't show the search if the picker box is shown
+					autoTypeCtxForm.Closed += OnAutoTypeCtxFormClosed;
+				}
+			}
+		}
+
+		private void OnAutoTypeCtxFormClosed(object sender, EventArgs e)
+		{
+			var autoTypeCtxForm = (AutoTypeCtxForm)sender;
+			autoTypeCtxForm.Closed -= OnAutoTypeCtxFormClosed;
+
+			if (autoTypeCtxForm.DialogResult == DialogResult.Cancel)
+			{
+				ShowSearch();
+			}
+		}
+		#endregion
+
+		public override void Terminate()
+		{
+			IpcUtilEx.IpcEvent -= OnIpcEvent;
+			GlobalWindowManager.WindowAdded -= OnWindowAdded;
+
+			if (!KeePassLib.Native.NativeLib.IsUnix())
+			{
+				HotKeyManager.HotKeyPressed -= HotKeyManager_HotKeyPressed;
+				Options.UnregisterHotKey();
+			}
+
+			Options.SaveSettings(mHost);
+			
+			base.Terminate();
+		}
+
+		#region Search Initiation
+		private void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
+		{
+			/*
+			var testGroup = mHost.Database.RootGroup.FindCreateGroup("Test", true);
+			for (int i = 0; i < 10000; i++)
+			{
+				var pwEntry = new PwEntry(true, true);
+				pwEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, "Title " + i));
+				pwEntry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "User " + i));
+				pwEntry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "http://website/" + i));
+				pwEntry.Strings.Set(PwDefs.NotesField, new ProtectedString(false, "Notes " + i + "\nLine 2\n\nLine 3\nLine 4\nLine 5\n Line 6\n Line 7\nLine 8\nLine 9\nLine 10"));
+				testGroup.AddEntry(pwEntry, true);
+			}*/
+
+			ShowSearch();
+		}
+
+		private void OnIpcEvent(object sender, IpcEventArgs ipcEventArgs)
+		{
+			if (Settings.Default.ShowOnIPC && ipcEventArgs.Name.Equals(IpcEventName, StringComparison.InvariantCultureIgnoreCase))
+			{
+				mHost.MainWindow.BeginInvoke(new Action(ShowSearch));
+			}
+		}
+
+		private void ShowSearch()
+		{
+			ShowSearch(null);
+		}
+
+		private void ShowSearch(string infoText)
+		{
+			// Unlock, if required
+			mHost.MainWindow.ProcessAppMessage((IntPtr)Program.AppMessage.Unlock, IntPtr.Zero);
+
+
+			if (mHost.MainWindow.IsAtLeastOneFileOpen())
+			{
+				var searchWindow = new SearchWindow(mHost.MainWindow, infoText);
+				searchWindow.Show();
+				searchWindow.Activate();
+			}
+		}
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/HotKeyManager.cs b/AutoTypeSearch/HotKeyManager.cs
new file mode 100755
index 0000000..b33f84b
--- /dev/null
+++ b/AutoTypeSearch/HotKeyManager.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	// This class taken from: http://stackoverflow.com/questions/3568513/how-to-create-keyboard-shortcut-in-windows-that-call-function-in-my-app/3569097#3569097
+	// And tweaked with answers in: http://stackoverflow.com/questions/15434505/key-capture-using-global-hotkey-in-c-sharp
+	// And logic from KeePass HotKeyManager
+	internal static class HotKeyManager
+	{
+		public static event EventHandler HotKeyPressed;
+
+		public static int RegisterHotKey(Keys keys)
+		{
+			int id = System.Threading.Interlocked.Increment(ref _id);
+
+			KeyModifiers modifiers = 0;
+			if ((keys & Keys.Shift) != Keys.None) modifiers |= KeyModifiers.Shift;
+			if ((keys & Keys.Alt) != Keys.None) modifiers |= KeyModifiers.Alt;
+			if ((keys & Keys.Control) != Keys.None) modifiers |= KeyModifiers.Control;
+
+			RegisterHotKey(_wnd.Handle, id, (uint)modifiers, (uint)(keys & Keys.KeyCode));
+			return id;
+		}
+
+		public static bool UnregisterHotKey(int id)
+		{
+			return UnregisterHotKey(_wnd.Handle, id);
+		}
+
+		private static void OnHotKeyPressed(HotKeyEventArgs e)
+		{
+			if (HotKeyManager.HotKeyPressed != null)
+			{
+				HotKeyManager.HotKeyPressed(null, e);
+			}
+		}
+
+		private static MessageWindow _wnd = new MessageWindow();
+
+		private class MessageWindow : NativeWindow, IDisposable
+		{
+			public MessageWindow()
+			{
+				CreateHandle(new CreateParams());
+			}
+
+			public void Dispose()
+			{
+				DestroyHandle();
+			}
+
+			protected override void WndProc(ref Message m)
+			{
+				if (m.Msg == WM_HOTKEY)
+				{
+					HotKeyEventArgs e = new HotKeyEventArgs(m.LParam);
+					HotKeyManager.OnHotKeyPressed(e);
+				}
+
+				base.WndProc(ref m);
+			}
+
+			private const int WM_HOTKEY = 0x312;
+		}
+
+		[DllImport("user32")]
+		private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
+
+		[DllImport("user32")]
+		private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
+
+		private static int _id = 0;
+	}
+
+
+	public class HotKeyEventArgs : EventArgs
+	{
+		public readonly Keys Key;
+		public readonly KeyModifiers Modifiers;
+
+		public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
+		{
+			this.Key = key;
+			this.Modifiers = modifiers;
+		}
+
+		public HotKeyEventArgs(IntPtr hotKeyParam)
+		{
+			uint param = (uint)hotKeyParam.ToInt64();
+			Key = (Keys)((param & 0xffff0000) >> 16);
+			Modifiers = (KeyModifiers)(param & 0x0000ffff);
+		}
+	}
+
+	[Flags]
+	public enum KeyModifiers
+	{
+		Alt = 1,
+		Control = 2,
+		Shift = 4,
+		Windows = 8,
+		NoRepeat = 0x4000
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/Info.png b/AutoTypeSearch/Info.png
new file mode 100755
index 0000000..c1a5608
--- /dev/null
+++ b/AutoTypeSearch/Info.png
Binary files differ
diff --git a/AutoTypeSearch/NativeMethods.cs b/AutoTypeSearch/NativeMethods.cs
new file mode 100755
index 0000000..0037441
--- /dev/null
+++ b/AutoTypeSearch/NativeMethods.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using KeePassLib.Native;
+using Microsoft.Win32;
+
+namespace AutoTypeSearch
+{
+	internal static class NativeMethods
+	{
+		private const int EM_SETMARGINS = 0x00D3;
+		private const int EC_RIGHTMARGIN = 0x2;
+
+		private const int WM_NCLBUTTONDOWN = 0xA1;
+		private const int HTCAPTION = 0x2;
+		[DllImport("User32.dll")]
+		private static extern bool ReleaseCapture();
+		[DllImport("User32.dll")]
+		private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+		private const int SWP_NOSIZE = 0x0001;
+		private const int SWP_NOMOVE = 0x0002;
+		private const int SWP_NOZORDER = 0x0004;
+		private const int SWP_FRAMECHANGED = 0x0020;
+		[DllImport("user32.dll", SetLastError=true)]
+		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
+
+		private const int WM_NCCALCSIZE = 0x83;
+
+		private struct RECT
+		{
+			public int Left, Top, Right, Bottom;
+		}
+		private struct WINDOWPOS
+		{
+			public IntPtr hwnd;
+			public IntPtr hwndinsertafter;
+			public int x, y, cx, cy;
+			public int flags;
+		}
+
+		struct NCCALCSIZE_PARAMS
+		{
+			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+			public RECT[] rgrc;
+			public WINDOWPOS lppos;
+		}
+
+		public static void SetTextBoxRightMargin(TextBox control, int rightMargin)
+		{
+			SendMessage(control.Handle, EM_SETMARGINS, EC_RIGHTMARGIN, rightMargin << 16);
+		}
+
+		public static void StartFormDrag(Form form)
+		{
+			Debug.Assert(Control.MouseButtons == MouseButtons.Left);
+			ReleaseCapture();
+			SendMessage(form.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
+		}
+
+		public static void RefreshWindowFrame(IntPtr hWnd)
+		{
+			NativeMethods.SetWindowPos(hWnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+		}
+
+		public static void RemoveWindowFrameTopBorder(ref Message m, int borderHeight)
+		{
+			if (m.Msg == WM_NCCALCSIZE)
+			{
+				var csp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
+				csp.rgrc[0].Top -= borderHeight;
+				Marshal.StructureToPtr(csp, m.LParam, false);
+			}
+		}
+
+		public static bool IsWindows10()
+		{
+			return NativeLib.GetPlatformID() == PlatformID.Win32NT &&
+			    // Can't just use OS Version because Windows 10 lies if you don't have specific support declared in the manifest.
+				(int)Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", -1) == 10;
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.Designer.cs b/AutoTypeSearch/Options.Designer.cs
new file mode 100755
index 0000000..4886b6d
--- /dev/null
+++ b/AutoTypeSearch/Options.Designer.cs
@@ -0,0 +1,324 @@
+using KeePass.UI;
+
+namespace AutoTypeSearch
+{
+	partial class Options
+	{
+		///  
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		///  
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		///  
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			System.Windows.Forms.GroupBox searchOptionsGroup;
+			System.Windows.Forms.GroupBox searchInGroup;
+			System.Windows.Forms.GroupBox actionsGroup;
+			System.Windows.Forms.Label alternativeActionLabel;
+			System.Windows.Forms.Label defaultActionLabel;
+			this.mResolveReferences = new System.Windows.Forms.CheckBox();
+			this.mExcludeExpired = new System.Windows.Forms.CheckBox();
+			this.mCaseSensitive = new System.Windows.Forms.CheckBox();
+			this.mSearchInTags = new System.Windows.Forms.CheckBox();
+			this.mSearchInOtherFields = new System.Windows.Forms.CheckBox();
+			this.mSearchInNotes = new System.Windows.Forms.CheckBox();
+			this.mSearchInUrl = new System.Windows.Forms.CheckBox();
+			this.mSearchInUserName = new System.Windows.Forms.CheckBox();
+			this.mSearchInTitle = new System.Windows.Forms.CheckBox();
+			this.mAlternativeAction = new System.Windows.Forms.ComboBox();
+			this.mDefaultAction = new System.Windows.Forms.ComboBox();
+			this.mShowHotKeyControl = new KeePass.UI.HotKeyControlEx();
+			this.mShowSearchGroup = new System.Windows.Forms.GroupBox();
+			this.mShowOnHotKey = new System.Windows.Forms.CheckBox();
+			this.mShowOnIPC = new System.Windows.Forms.CheckBox();
+			this.mShowOnFailedSearch = new System.Windows.Forms.CheckBox();
+			searchOptionsGroup = new System.Windows.Forms.GroupBox();
+			searchInGroup = new System.Windows.Forms.GroupBox();
+			actionsGroup = new System.Windows.Forms.GroupBox();
+			alternativeActionLabel = new System.Windows.Forms.Label();
+			defaultActionLabel = new System.Windows.Forms.Label();
+			searchOptionsGroup.SuspendLayout();
+			searchInGroup.SuspendLayout();
+			actionsGroup.SuspendLayout();
+			this.mShowSearchGroup.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// searchOptionsGroup
+			// 
+			searchOptionsGroup.Controls.Add(this.mResolveReferences);
+			searchOptionsGroup.Controls.Add(this.mExcludeExpired);
+			searchOptionsGroup.Controls.Add(this.mCaseSensitive);
+			searchOptionsGroup.Location = new System.Drawing.Point(6, 189);
+			searchOptionsGroup.Name = "searchOptionsGroup";
+			searchOptionsGroup.Size = new System.Drawing.Size(540, 45);
+			searchOptionsGroup.TabIndex = 2;
+			searchOptionsGroup.TabStop = false;
+			searchOptionsGroup.Text = "Search options";
+			// 
+			// mResolveReferences
+			// 
+			this.mResolveReferences.AutoSize = true;
+			this.mResolveReferences.Location = new System.Drawing.Point(251, 20);
+			this.mResolveReferences.Name = "mResolveReferences";
+			this.mResolveReferences.Size = new System.Drawing.Size(170, 17);
+			this.mResolveReferences.TabIndex = 2;
+			this.mResolveReferences.Text = "Resolve fiel&d references (slow)";
+			this.mResolveReferences.UseVisualStyleBackColor = true;
+			// 
+			// mExcludeExpired
+			// 
+			this.mExcludeExpired.AutoSize = true;
+			this.mExcludeExpired.Location = new System.Drawing.Point(108, 20);
+			this.mExcludeExpired.Name = "mExcludeExpired";
+			this.mExcludeExpired.Size = new System.Drawing.Size(135, 17);
+			this.mExcludeExpired.TabIndex = 1;
+			this.mExcludeExpired.Text = "Exclude &expired entries";
+			this.mExcludeExpired.UseVisualStyleBackColor = true;
+			// 
+			// mCaseSensitive
+			// 
+			this.mCaseSensitive.AutoSize = true;
+			this.mCaseSensitive.Location = new System.Drawing.Point(10, 20);
+			this.mCaseSensitive.Name = "mCaseSensitive";
+			this.mCaseSensitive.Size = new System.Drawing.Size(94, 17);
+			this.mCaseSensitive.TabIndex = 0;
+			this.mCaseSensitive.Text = "Case-sensiti&ve";
+			this.mCaseSensitive.UseVisualStyleBackColor = true;
+			// 
+			// searchInGroup
+			// 
+			searchInGroup.Controls.Add(this.mSearchInTags);
+			searchInGroup.Controls.Add(this.mSearchInOtherFields);
+			searchInGroup.Controls.Add(this.mSearchInNotes);
+			searchInGroup.Controls.Add(this.mSearchInUrl);
+			searchInGroup.Controls.Add(this.mSearchInUserName);
+			searchInGroup.Controls.Add(this.mSearchInTitle);
+			searchInGroup.Location = new System.Drawing.Point(6, 136);
+			searchInGroup.Name = "searchInGroup";
+			searchInGroup.Size = new System.Drawing.Size(540, 47);
+			searchInGroup.TabIndex = 1;
+			searchInGroup.TabStop = false;
+			searchInGroup.Text = "Search in";
+			// 
+			// mSearchInTags
+			// 
+			this.mSearchInTags.AutoSize = true;
+			this.mSearchInTags.Location = new System.Drawing.Point(258, 19);
+			this.mSearchInTags.Name = "mSearchInTags";
+			this.mSearchInTags.Size = new System.Drawing.Size(50, 17);
+			this.mSearchInTags.TabIndex = 4;
+			this.mSearchInTags.Text = "Ta&gs";
+			this.mSearchInTags.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInOtherFields
+			// 
+			this.mSearchInOtherFields.AutoSize = true;
+			this.mSearchInOtherFields.Location = new System.Drawing.Point(314, 19);
+			this.mSearchInOtherFields.Name = "mSearchInOtherFields";
+			this.mSearchInOtherFields.Size = new System.Drawing.Size(139, 17);
+			this.mSearchInOtherFields.TabIndex = 5;
+			this.mSearchInOtherFields.Text = "&Other unprotected fields";
+			this.mSearchInOtherFields.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInNotes
+			// 
+			this.mSearchInNotes.AutoSize = true;
+			this.mSearchInNotes.Location = new System.Drawing.Point(198, 19);
+			this.mSearchInNotes.Name = "mSearchInNotes";
+			this.mSearchInNotes.Size = new System.Drawing.Size(54, 17);
+			this.mSearchInNotes.TabIndex = 3;
+			this.mSearchInNotes.Text = "Note&s";
+			this.mSearchInNotes.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUrl
+			// 
+			this.mSearchInUrl.AutoSize = true;
+			this.mSearchInUrl.Location = new System.Drawing.Point(144, 19);
+			this.mSearchInUrl.Name = "mSearchInUrl";
+			this.mSearchInUrl.Size = new System.Drawing.Size(48, 17);
+			this.mSearchInUrl.TabIndex = 2;
+			this.mSearchInUrl.Text = "&URL";
+			this.mSearchInUrl.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInUserName
+			// 
+			this.mSearchInUserName.AutoSize = true;
+			this.mSearchInUserName.Location = new System.Drawing.Point(61, 19);
+			this.mSearchInUserName.Name = "mSearchInUserName";
+			this.mSearchInUserName.Size = new System.Drawing.Size(77, 17);
+			this.mSearchInUserName.TabIndex = 1;
+			this.mSearchInUserName.Text = "User &name";
+			this.mSearchInUserName.UseVisualStyleBackColor = true;
+			// 
+			// mSearchInTitle
+			// 
+			this.mSearchInTitle.AutoSize = true;
+			this.mSearchInTitle.Location = new System.Drawing.Point(9, 19);
+			this.mSearchInTitle.Name = "mSearchInTitle";
+			this.mSearchInTitle.Size = new System.Drawing.Size(46, 17);
+			this.mSearchInTitle.TabIndex = 0;
+			this.mSearchInTitle.Text = "&Title";
+			this.mSearchInTitle.UseVisualStyleBackColor = true;
+			// 
+			// actionsGroup
+			// 
+			actionsGroup.Controls.Add(this.mAlternativeAction);
+			actionsGroup.Controls.Add(this.mDefaultAction);
+			actionsGroup.Controls.Add(alternativeActionLabel);
+			actionsGroup.Controls.Add(defaultActionLabel);
+			actionsGroup.Location = new System.Drawing.Point(6, 241);
+			actionsGroup.Name = "actionsGroup";
+			actionsGroup.Size = new System.Drawing.Size(540, 67);
+			actionsGroup.TabIndex = 3;
+			actionsGroup.TabStop = false;
+			actionsGroup.Text = "Actions";
+			// 
+			// mAlternativeAction
+			// 
+			this.mAlternativeAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mAlternativeAction.Location = new System.Drawing.Point(288, 37);
+			this.mAlternativeAction.Name = "mAlternativeAction";
+			this.mAlternativeAction.Size = new System.Drawing.Size(240, 21);
+			this.mAlternativeAction.TabIndex = 3;
+			// 
+			// mDefaultAction
+			// 
+			this.mDefaultAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+			this.mDefaultAction.Location = new System.Drawing.Point(11, 37);
+			this.mDefaultAction.Name = "mDefaultAction";
+			this.mDefaultAction.Size = new System.Drawing.Size(240, 21);
+			this.mDefaultAction.TabIndex = 1;
+			// 
+			// alternativeActionLabel
+			// 
+			alternativeActionLabel.AutoSize = true;
+			alternativeActionLabel.Location = new System.Drawing.Point(285, 20);
+			alternativeActionLabel.Name = "alternativeActionLabel";
+			alternativeActionLabel.Size = new System.Drawing.Size(159, 13);
+			alternativeActionLabel.TabIndex = 2;
+			alternativeActionLabel.Text = "A<ernative action (Shift + Enter):";
+			// 
+			// defaultActionLabel
+			// 
+			defaultActionLabel.AutoSize = true;
+			defaultActionLabel.Location = new System.Drawing.Point(8, 20);
+			defaultActionLabel.Name = "defaultActionLabel";
+			defaultActionLabel.Size = new System.Drawing.Size(110, 13);
+			defaultActionLabel.TabIndex = 0;
+			defaultActionLabel.Text = "De&fault action (Enter):";
+			// 
+			// mShowHotKeyControl
+			// 
+			this.mShowHotKeyControl.Location = new System.Drawing.Point(30, 65);
+			this.mShowHotKeyControl.Name = "mShowHotKeyControl";
+			this.mShowHotKeyControl.Size = new System.Drawing.Size(123, 20);
+			this.mShowHotKeyControl.TabIndex = 2;
+			// 
+			// mShowSearchGroup
+			// 
+			this.mShowSearchGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mShowSearchGroup.Controls.Add(this.mShowOnHotKey);
+			this.mShowSearchGroup.Controls.Add(this.mShowHotKeyControl);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnIPC);
+			this.mShowSearchGroup.Controls.Add(this.mShowOnFailedSearch);
+			this.mShowSearchGroup.Location = new System.Drawing.Point(6, 12);
+			this.mShowSearchGroup.Name = "mShowSearchGroup";
+			this.mShowSearchGroup.Size = new System.Drawing.Size(540, 118);
+			this.mShowSearchGroup.TabIndex = 0;
+			this.mShowSearchGroup.TabStop = false;
+			this.mShowSearchGroup.Text = "Show search window";
+			// 
+			// mShowOnHotKey
+			// 
+			this.mShowOnHotKey.AutoSize = true;
+			this.mShowOnHotKey.Location = new System.Drawing.Point(10, 44);
+			this.mShowOnHotKey.Name = "mShowOnHotKey";
+			this.mShowOnHotKey.Size = new System.Drawing.Size(233, 17);
+			this.mShowOnHotKey.TabIndex = 1;
+			this.mShowOnHotKey.Text = "Show when system-wide &hot key is pressed:";
+			this.mShowOnHotKey.UseVisualStyleBackColor = true;
+			this.mShowOnHotKey.CheckedChanged += new System.EventHandler(this.mShowOnHotKey_CheckedChanged);
+			// 
+			// mShowOnIPC
+			// 
+			this.mShowOnIPC.AutoSize = true;
+			this.mShowOnIPC.Location = new System.Drawing.Point(10, 93);
+			this.mShowOnIPC.Name = "mShowOnIPC";
+			this.mShowOnIPC.Size = new System.Drawing.Size(386, 17);
+			this.mShowOnIPC.TabIndex = 3;
+			this.mShowOnIPC.Text = "Show when \"/e1:AutoTypeSearch\" is passed as a ¶meter to KeePass.exe";
+			this.mShowOnIPC.UseVisualStyleBackColor = true;
+			// 
+			// mShowOnFailedSearch
+			// 
+			this.mShowOnFailedSearch.AutoSize = true;
+			this.mShowOnFailedSearch.Location = new System.Drawing.Point(10, 21);
+			this.mShowOnFailedSearch.Name = "mShowOnFailedSearch";
+			this.mShowOnFailedSearch.Size = new System.Drawing.Size(275, 17);
+			this.mShowOnFailedSearch.TabIndex = 0;
+			this.mShowOnFailedSearch.Text = "Show &automatically if global auto-type finds no match";
+			this.mShowOnFailedSearch.UseVisualStyleBackColor = true;
+			// 
+			// Options
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.Controls.Add(actionsGroup);
+			this.Controls.Add(searchInGroup);
+			this.Controls.Add(searchOptionsGroup);
+			this.Controls.Add(this.mShowSearchGroup);
+			this.Name = "Options";
+			this.Size = new System.Drawing.Size(551, 311);
+			searchOptionsGroup.ResumeLayout(false);
+			searchOptionsGroup.PerformLayout();
+			searchInGroup.ResumeLayout(false);
+			searchInGroup.PerformLayout();
+			actionsGroup.ResumeLayout(false);
+			actionsGroup.PerformLayout();
+			this.mShowSearchGroup.ResumeLayout(false);
+			this.mShowSearchGroup.PerformLayout();
+			this.ResumeLayout(false);
+
+		}
+
+		#endregion
+
+		private KeePass.UI.HotKeyControlEx mShowHotKeyControl;
+		private System.Windows.Forms.CheckBox mShowOnHotKey;
+		private System.Windows.Forms.CheckBox mShowOnIPC;
+		private System.Windows.Forms.CheckBox mShowOnFailedSearch;
+		private System.Windows.Forms.CheckBox mCaseSensitive;
+		private System.Windows.Forms.CheckBox mSearchInTags;
+		private System.Windows.Forms.CheckBox mSearchInOtherFields;
+		private System.Windows.Forms.CheckBox mSearchInNotes;
+		private System.Windows.Forms.CheckBox mSearchInUrl;
+		private System.Windows.Forms.CheckBox mSearchInUserName;
+		private System.Windows.Forms.CheckBox mSearchInTitle;
+		private System.Windows.Forms.CheckBox mResolveReferences;
+		private System.Windows.Forms.CheckBox mExcludeExpired;
+		private System.Windows.Forms.ComboBox mAlternativeAction;
+		private System.Windows.Forms.ComboBox mDefaultAction;
+		private System.Windows.Forms.GroupBox mShowSearchGroup;
+
+	}
+}
diff --git a/AutoTypeSearch/Options.cs b/AutoTypeSearch/Options.cs
new file mode 100755
index 0000000..b99561c
--- /dev/null
+++ b/AutoTypeSearch/Options.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Plugins;
+using KeePassLib;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	internal partial class Options : UserControl
+	{
+		private const string OptionsConfigRoot = "AutoTypeSearchExt.";
+
+		private static int sRegisteredHotkeyId;
+
+		// ReSharper disable once MemberCanBePrivate.Global - Public for forms designer
+		public Options()
+		{
+			InitializeComponent();
+
+			// Must mach order and values of Actions enum
+			var actions = new object[] { Resources.PerformAutoType, Resources.EditEntry, Resources.ShowEntry, Resources.OpenEntryUrl, Resources.CopyPassword };
+			mDefaultAction.Items.AddRange(actions);
+			mAlternativeAction.Items.AddRange(actions);
+
+			// Read options
+			mShowOnFailedSearch.Checked = Settings.Default.ShowOnFailedAutoType;
+			
+			if (NativeLib.IsUnix())
+			{
+				mShowOnHotKey.Enabled = false;
+				mShowOnHotKey.Checked = false;
+
+				mShowHotKeyControl.Clear();
+			}
+			else
+			{
+				mShowOnHotKey.Checked = Settings.Default.ShowOnHotKey;
+				ShowHotKey = Settings.Default.ShowHotKey;
+			}
+			mShowOnHotKey_CheckedChanged(null, EventArgs.Empty);
+
+			mShowOnIPC.Checked = Settings.Default.ShowOnIPC;
+			mSearchInTitle.Checked = Settings.Default.SearchTitle;
+			mSearchInUserName.Checked = Settings.Default.SearchUserName;
+			mSearchInUrl.Checked = Settings.Default.SearchUrl;
+			mSearchInNotes.Checked = Settings.Default.SearchNotes;
+			mSearchInTags.Checked = Settings.Default.SearchTags;
+			mSearchInOtherFields.Checked = Settings.Default.SearchCustomFields;
+			
+			mCaseSensitive.Checked = Settings.Default.CaseSensitive;
+			mExcludeExpired.Checked = Settings.Default.ExcludeExpired;
+			mResolveReferences.Checked = Settings.Default.ResolveReferences;
+
+			mDefaultAction.SelectedIndex = (int)Settings.Default.DefaultAction;
+			mAlternativeAction.SelectedIndex = (int)Settings.Default.AlternativeAction;
+		}
+
+		private Keys ShowHotKey
+		{
+			get { return mShowHotKeyControl.HotKey; }
+			set { mShowHotKeyControl.HotKey = value; }
+		}
+
+		private void mShowOnHotKey_CheckedChanged(object sender, EventArgs e)
+		{
+			mShowHotKeyControl.Enabled = mShowOnHotKey.Checked;
+		}
+
+		private void ApplySettings()
+		{
+			// Apply settings
+			Settings.Default.ShowOnFailedAutoType = mShowOnFailedSearch.Checked;
+			Settings.Default.ShowOnHotKey = mShowOnHotKey.Checked;
+			Settings.Default.ShowOnIPC = mShowOnIPC.Checked;
+			Settings.Default.SearchTitle = mSearchInTitle.Checked;
+			Settings.Default.SearchUserName = mSearchInUserName.Checked;
+			Settings.Default.SearchUrl = mSearchInUrl.Checked;
+			Settings.Default.SearchNotes = mSearchInNotes.Checked;
+			Settings.Default.SearchTags = mSearchInTags.Checked;
+			Settings.Default.SearchCustomFields = mSearchInOtherFields.Checked;
+			Settings.Default.CaseSensitive = mCaseSensitive.Checked;
+			Settings.Default.ExcludeExpired = mExcludeExpired.Checked;
+			Settings.Default.ResolveReferences = mResolveReferences.Checked;
+			Settings.Default.DefaultAction = (Actions)mDefaultAction.SelectedIndex;
+			Settings.Default.AlternativeAction = (Actions)mAlternativeAction.SelectedIndex;
+			Settings.Default.ShowHotKey = ShowHotKey;
+
+			ApplyHotKey();
+		}
+
+		#region Settings persistence
+		public static void SaveSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					if (property.IsDirty)
+					{
+						var value = property.SerializedValue as String;
+						if (value != null)
+						{
+							host.CustomConfig.SetString(OptionsConfigRoot + property.Name, value);
+						}
+						else
+						{
+							Debug.Fail("Non-string serialized settings property");
+						}
+					}
+				}
+			}
+		}
+
+		public static void LoadSettings(IPluginHost host)
+		{
+			if (host != null)
+			{
+				// ReSharper disable once UnusedVariable
+				var ignored = Settings.Default.ShowOnFailedAutoType; //Access any property just to make it load settings.
+
+				foreach (SettingsPropertyValue property in Settings.Default.PropertyValues)
+				{
+					var value = host.CustomConfig.GetString(OptionsConfigRoot + property.Name);
+					if (value != null)
+					{
+						property.SerializedValue = value;
+						property.Deserialized = false;
+						property.IsDirty = false;
+					}
+				}
+
+				ApplyHotKey();
+			}
+		}
+		#endregion
+
+		#region Hotkey
+		private static void ApplyHotKey()
+		{
+			UnregisterHotKey();
+
+			if (Settings.Default.ShowOnHotKey && Settings.Default.ShowHotKey != Keys.None)
+			{
+				sRegisteredHotkeyId = HotKeyManager.RegisterHotKey(Settings.Default.ShowHotKey);
+			}
+		}
+
+		public static void UnregisterHotKey()
+		{
+			if (sRegisteredHotkeyId != 0)
+			{
+				var result = HotKeyManager.UnregisterHotKey(sRegisteredHotkeyId);
+				Debug.Assert(result);
+				sRegisteredHotkeyId = 0;
+			}
+		}
+		#endregion
+
+		public static void AddToWindow(OptionsForm optionsForm)
+		{
+			var tabControl = optionsForm.Controls.Find("m_tabMain", false).FirstOrDefault() as TabControl;
+			var okButton = optionsForm.Controls.Find("m_btnOK", false).FirstOrDefault() as Button;
+
+			if (tabControl == null || okButton == null)
+			{
+				Debug.Fail("Could not integrate with options form");
+			}
+
+			var tabPage = new TabPage(Resources.AutoTypeSearch)
+			{
+				UseVisualStyleBackColor = true,
+				AutoScroll = true,
+				ImageIndex = (int)PwIcon.EMailSearch
+			};
+			var options = new Options { Dock = DockStyle.Fill };
+			tabPage.Controls.Add(options);
+
+			tabControl.TabPages.Add(tabPage);
+
+			okButton.Click += delegate
+			{
+				options.ApplySettings();
+			};
+		}
+	}
+}
diff --git a/AutoTypeSearch/Options.resx b/AutoTypeSearch/Options.resx
new file mode 100755
index 0000000..4601c27
--- /dev/null
+++ b/AutoTypeSearch/Options.resx
@@ -0,0 +1,135 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+  
+    False
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/AssemblyInfo.cs b/AutoTypeSearch/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..4a8b0ac
--- /dev/null
+++ b/AutoTypeSearch/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoTypeSearch")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Alex Vallat")]
+[assembly: AssemblyProduct("KeePass Plugin")]
+[assembly: AssemblyCopyright("Copyright © 2017 Alex Vallat")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c4effc53-d77b-45e0-9d11-a0b9661ae822")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.42.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AutoTypeSearch/Properties/Resources.Designer.cs b/AutoTypeSearch/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..4a4fbaf
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.Designer.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    using System;
+    
+    
+    /// 
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// 
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// 
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoTypeSearch.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// 
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// 
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Global auto-type found no match for window: "{0}".
+        /// 
+        internal static string AutoTypeFailedMessage {
+            get {
+                return ResourceManager.GetString("AutoTypeFailedMessage", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to AutoTypeSearch.
+        /// 
+        internal static string AutoTypeSearch {
+            get {
+                return ResourceManager.GetString("AutoTypeSearch", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Start typing to search entries.
+        /// 
+        internal static string BannerText {
+            get {
+                return ResourceManager.GetString("BannerText", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Copy password.
+        /// 
+        internal static string CopyPassword {
+            get {
+                return ResourceManager.GetString("CopyPassword", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Edit entry.
+        /// 
+        internal static string EditEntry {
+            get {
+                return ResourceManager.GetString("EditEntry", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// 
+        internal static System.Drawing.Bitmap Info {
+            get {
+                object obj = ResourceManager.GetObject("Info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Open entry url.
+        /// 
+        internal static string OpenEntryUrl {
+            get {
+                return ResourceManager.GetString("OpenEntryUrl", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Perform entry auto-type.
+        /// 
+        internal static string PerformAutoType {
+            get {
+                return ResourceManager.GetString("PerformAutoType", resourceCulture);
+            }
+        }
+        
+        /// 
+        ///   Looks up a localized string similar to Show entry in the main window.
+        /// 
+        internal static string ShowEntry {
+            get {
+                return ResourceManager.GetString("ShowEntry", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Resources.resx b/AutoTypeSearch/Properties/Resources.resx
new file mode 100755
index 0000000..76e9bce
--- /dev/null
+++ b/AutoTypeSearch/Properties/Resources.resx
@@ -0,0 +1,148 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    Global auto-type found no match for window: "{0}"
+  
+  
+    AutoTypeSearch
+  
+  
+    Start typing to search entries
+  
+  
+    Copy password
+  
+  
+    Edit entry
+  
+  
+  
+    ..\Info.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+  
+  
+    Open entry url
+  
+  
+    Perform entry auto-type
+  
+  
+    Show entry in the main window
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Properties/Settings.Designer.cs b/AutoTypeSearch/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..62e2cdb
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.Designer.cs
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// 
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// 
+//------------------------------------------------------------------------------
+
+namespace AutoTypeSearch.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTitle {
+            get {
+                return ((bool)(this["SearchTitle"]));
+            }
+            set {
+                this["SearchTitle"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool SearchUserName {
+            get {
+                return ((bool)(this["SearchUserName"]));
+            }
+            set {
+                this["SearchUserName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchUrl {
+            get {
+                return ((bool)(this["SearchUrl"]));
+            }
+            set {
+                this["SearchUrl"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchNotes {
+            get {
+                return ((bool)(this["SearchNotes"]));
+            }
+            set {
+                this["SearchNotes"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchCustomFields {
+            get {
+                return ((bool)(this["SearchCustomFields"]));
+            }
+            set {
+                this["SearchCustomFields"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool SearchTags {
+            get {
+                return ((bool)(this["SearchTags"]));
+            }
+            set {
+                this["SearchTags"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool CaseSensitive {
+            get {
+                return ((bool)(this["CaseSensitive"]));
+            }
+            set {
+                this["CaseSensitive"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("0, 0, 0, 0")]
+        public global::System.Drawing.Rectangle WindowPosition {
+            get {
+                return ((global::System.Drawing.Rectangle)(this["WindowPosition"]));
+            }
+            set {
+                this["WindowPosition"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnFailedAutoType {
+            get {
+                return ((bool)(this["ShowOnFailedAutoType"]));
+            }
+            set {
+                this["ShowOnFailedAutoType"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ShowOnHotKey {
+            get {
+                return ((bool)(this["ShowOnHotKey"]));
+            }
+            set {
+                this["ShowOnHotKey"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("True")]
+        public bool ShowOnIPC {
+            get {
+                return ((bool)(this["ShowOnIPC"]));
+            }
+            set {
+                this["ShowOnIPC"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ExcludeExpired {
+            get {
+                return ((bool)(this["ExcludeExpired"]));
+            }
+            set {
+                this["ExcludeExpired"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool ResolveReferences {
+            get {
+                return ((bool)(this["ResolveReferences"]));
+            }
+            set {
+                this["ResolveReferences"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("PerformAutoType")]
+        public global::AutoTypeSearch.Actions DefaultAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["DefaultAction"]));
+            }
+            set {
+                this["DefaultAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("EditEntry")]
+        public global::AutoTypeSearch.Actions AlternativeAction {
+            get {
+                return ((global::AutoTypeSearch.Actions)(this["AlternativeAction"]));
+            }
+            set {
+                this["AlternativeAction"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("None")]
+        public global::System.Windows.Forms.Keys ShowHotKey {
+            get {
+                return ((global::System.Windows.Forms.Keys)(this["ShowHotKey"]));
+            }
+            set {
+                this["ShowHotKey"] = value;
+            }
+        }
+    }
+}
diff --git a/AutoTypeSearch/Properties/Settings.settings b/AutoTypeSearch/Properties/Settings.settings
new file mode 100755
index 0000000..edcae1b
--- /dev/null
+++ b/AutoTypeSearch/Properties/Settings.settings
@@ -0,0 +1,54 @@
+
+
+  
+  
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      True
+    
+    
+      False
+    
+    
+      0, 0, 0, 0
+    
+    
+      True
+    
+    
+      False
+    
+    
+      True
+    
+    
+      False
+    
+    
+      False
+    
+    
+      PerformAutoType
+    
+    
+      EditEntry
+    
+    
+      None
+    
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchResult.cs b/AutoTypeSearch/SearchResult.cs
new file mode 100755
index 0000000..5af4177
--- /dev/null
+++ b/AutoTypeSearch/SearchResult.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResult
+	{
+		private readonly PwDatabase mDatabase;
+		private readonly PwEntry mEntry;
+		private readonly string mFieldName;
+		private readonly int mStart;
+		private readonly int mLength;
+		private readonly string mFieldValue;
+		private readonly string mTitle;
+		private string mUniqueTitlePart;
+		private int mResultIndex = -1;
+
+		public SearchResult(PwDatabase database, PwEntry entry, string title, string fieldName, string fieldValue, int start, int length)
+		{
+			mDatabase = database;
+			mEntry = entry;
+			mFieldName = fieldName;
+			mFieldValue = fieldValue;
+			mStart = start;
+			mLength = length;
+			mTitle = title;
+
+			Debug.Assert(mLength >= 0 && mStart >= 0, "Negative values are invalid");
+			Debug.Assert(mLength > 0 || mStart == 0, "Length must be non-zero (unless no highlight)");
+			Debug.Assert((mStart + mLength) <= fieldValue.Length, "Length out of range");
+		}
+
+		public PwDatabase Database
+		{
+			get { return mDatabase; }
+		}
+
+		public PwEntry Entry
+		{
+			get { return mEntry; }
+		}
+
+		public string FieldName
+		{
+			get { return mFieldName; }
+		}
+
+		public string FieldValue
+		{
+			get { return mFieldValue; }
+		}
+
+		public int Start
+		{
+			get { return mStart; }
+		}
+
+		public int Length
+		{
+			get { return mLength; }
+		}
+
+		public string Title
+		{
+			get { return mTitle; }
+		}
+
+		/// 
+		/// The UniqueTitle may be modified from the  to ensure uniqueness in the list of results
+		/// 
+		public string UniqueTitle
+		{
+			get { return UniqueTitlePart + Title; }
+		}
+
+		public string UniqueTitlePart
+		{
+			get { return mUniqueTitlePart; }
+		}
+
+		public int ResultIndex
+		{
+			get { return mResultIndex; }
+		}
+
+		public void SetResultIndex(int resultIndex)
+		{
+			if (mResultIndex != -1)
+			{
+				throw new InvalidOperationException("Result index has already been set");
+			}
+			if (resultIndex < 0)
+			{
+				throw new ArgumentOutOfRangeException("resultIndex");
+			}
+
+			mResultIndex = resultIndex;
+		}
+
+		/// 
+		/// Sets  by including parent group names to the specified depth.
+		/// 
+		/// True if the group hierarchy is deep enough to support full requested 
+		public bool SetUniqueTitleDepth(int depth)
+		{
+			var groupPath = new StringBuilder();
+			var group = Entry.ParentGroup;
+			for (int i = 0; i < depth && group != null; i++)
+			{
+				groupPath.Insert(0, group.Name + " / ");
+				group = group.ParentGroup;
+			}
+
+			mUniqueTitlePart = groupPath.ToString();
+
+			return group != null;
+		}
+
+		
+	}
+}
diff --git a/AutoTypeSearch/SearchResults.cs b/AutoTypeSearch/SearchResults.cs
new file mode 100755
index 0000000..b2b0529
--- /dev/null
+++ b/AutoTypeSearch/SearchResults.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePass.Util.Spr;
+using KeePassLib;
+using KeePassLib.Utility;
+
+namespace AutoTypeSearch
+{
+	internal class SearchResults
+	{
+		private readonly string mTerm;
+		private readonly SearchResult[] mResults;
+
+		private readonly object mLock = new object();
+		private volatile int mCount;
+		private volatile bool mComplete;
+
+		private readonly AutoResetEvent mResultsUpdated = new AutoResetEvent(false);
+
+		private readonly CompareOptions mStringComparison;
+		private readonly bool mSearchTitle;
+		private readonly bool mSearchUserName;
+		private readonly bool mSearchUrl;
+		private readonly bool mSearchNotes;
+		private readonly bool mSearchCustomFields;
+		private readonly bool mResolveReferences;
+		private readonly bool mSearchTags;
+
+		public SearchResults(int capacity, string term)
+		{
+			mTerm = term;
+			mResults = new SearchResult[capacity];
+
+			mStringComparison = Settings.Default.CaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase;
+			mStringComparison |= CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace;
+			mSearchTitle = Settings.Default.SearchTitle;
+			mSearchUserName = Settings.Default.SearchUserName;
+			mSearchUrl = Settings.Default.SearchUrl;
+			mSearchNotes = Settings.Default.SearchNotes;
+			mSearchCustomFields = Settings.Default.SearchCustomFields;
+			mSearchTags = Settings.Default.SearchTags;
+			mResolveReferences = Settings.Default.ResolveReferences;
+		}
+
+		/// 
+		/// Gets an ordered list of fields to search for the term
+		/// 
+		/// 
+		/// 
+		private IEnumerable GetFieldsToSearch(PwEntry entry)
+		{
+			var fieldsToSearch = new List((int)entry.Strings.UCount);
+			if (mSearchTitle) fieldsToSearch.Add(PwDefs.TitleField);
+			if (mSearchUserName) fieldsToSearch.Add(PwDefs.UserNameField);
+			if (mSearchUrl) fieldsToSearch.Add(PwDefs.UrlField);
+			if (mSearchNotes) fieldsToSearch.Add(PwDefs.NotesField);
+			if (mSearchCustomFields)
+			{
+				foreach (var stringEntry in entry.Strings)
+				{
+					if (!stringEntry.Value.IsProtected && !PwDefs.IsStandardField(stringEntry.Key))
+					{
+						fieldsToSearch.Add(stringEntry.Key);
+					}
+				}
+			}
+			if (mSearchTags) fieldsToSearch.Add(AutoTypeSearchExt.TagsVirtualFieldName);
+
+			return fieldsToSearch;
+		}
+
+		public void AddResultIfMatchesTerm(PwDatabase context, PwEntry entry)
+		{
+			// First try without resolving
+			var addedResult = AddResultIfMatchesTerm(context, entry, false);
+
+			if (!addedResult && mResolveReferences)
+			{
+				// Not found without resolving, so try resolving
+				AddResultIfMatchesTerm(context, entry, true);
+			}
+		}
+
+		private bool AddResultIfMatchesTerm(PwDatabase context, PwEntry entry, bool resolveReferences)
+		{
+			foreach (var fieldName in GetFieldsToSearch(entry))
+			{
+				string fieldValue;
+				if (fieldName == AutoTypeSearchExt.TagsVirtualFieldName)
+				{
+					fieldValue = StrUtil.TagsToString(entry.Tags, true);
+				}
+				else
+				{
+					fieldValue = entry.Strings.ReadSafeEx(fieldName);
+
+					if (resolveReferences)
+					{
+						fieldValue = ResolveReferences(context, entry, fieldValue);
+					}
+				}
+
+				if (!String.IsNullOrEmpty(fieldValue))
+				{
+					var foundIndex = CultureInfo.CurrentCulture.CompareInfo.IndexOf(fieldValue, mTerm, mStringComparison);
+					if (foundIndex >= 0)
+					{
+						// Found a match, create a search result and add it
+						AddResult(new SearchResult(context, entry, entry.Strings.ReadSafe(PwDefs.TitleField), fieldName, fieldValue, foundIndex, mTerm.Length));
+						return true;
+					}
+				}
+			}
+			return false;
+		}
+
+		/// 
+		/// Resolves any references in the field value and returns it. If there were no references,
+		/// returns null (to avoid duplicate searching - it is assumed that the unresolved value has already been searched)
+		/// 
+		private string ResolveReferences(PwDatabase context, PwEntry entry, string fieldValue)
+		{
+			if (fieldValue.IndexOf('{') < 0)
+			{
+				// Can't contain any references
+				return null;
+			}
+			
+			var sprContext = new SprContext(entry, context, SprCompileFlags.Deref) { ForcePlainTextPasswords = false };
+
+			var result = SprEngine.Compile(fieldValue, sprContext);
+			if (CultureInfo.CurrentCulture.CompareInfo.Compare(result,fieldValue, mStringComparison) == 0)
+			{
+				return null;
+			}
+			
+			return result;
+		}
+
+		public void AddResultIfMatchesTerm(SearchResult candidate)
+		{
+			// First see whether the existing candidate is a further match in the same place
+			var fieldValue = candidate.FieldValue;
+			if (fieldValue.Length > candidate.Start + mTerm.Length && CultureInfo.CurrentCulture.CompareInfo.Compare(fieldValue.Substring(candidate.Start, mTerm.Length), mTerm, mStringComparison) == 0)
+			{
+				// Yep, match continues, so add it.
+				AddResult(new SearchResult(candidate.Database, candidate.Entry, candidate.Title, candidate.FieldName, fieldValue, candidate.Start, mTerm.Length));
+			}
+			else
+			{
+				// Existing candidate match couldn't be extended, so search from scratch again
+				AddResultIfMatchesTerm(candidate.Database, candidate.Entry);
+			}
+		}
+
+		private void AddResult(SearchResult result)
+		{
+			lock (mLock)
+			{
+				if (mComplete)
+				{
+					throw new InvalidOperationException("Search results have been completed");
+				}
+				result.SetResultIndex(mCount);
+				mResults[mCount++] = result;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Indicates that the results are complete, and no more will be added.
+		/// 
+		public void SetComplete()
+		{
+			lock (mLock)
+			{
+				mComplete = true;
+			}
+			mResultsUpdated.Set();
+		}
+
+		/// 
+		/// Gets all the available results so far.
+		/// 
+		/// Index to start returning from. Modified to be the first index not available yet on return.
+		/// Set to true if the results are complete, false if more results are pending but have not been returned.
+		/// 
+		public SearchResult[] GetAvailableResults(ref int index, out bool complete)
+		{
+			int count;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			if (count <= index)
+			{
+				return new SearchResult[0];
+			}
+
+			var availableResults = new SearchResult[count - index];
+			Array.Copy(mResults, index, availableResults, 0, availableResults.Length);
+			index = count;
+
+			return availableResults;
+		}
+
+		/// 
+		/// Gets all the results. Will block until complete.
+		/// 
+		/// 
+		public IEnumerable GetAllResults()
+		{
+			int count = -1;
+
+			for (var i = 0; i < mResults.Length; i++)
+			{
+				if (i > count)
+				{
+					// Reached the limit of availability so far, so see if more is available
+					do
+					{
+						bool moreAvailable, complete;
+
+						lock (mLock)
+						{
+							moreAvailable = mCount > count;
+							count = mCount;
+							complete = mComplete;
+						}
+
+						if (!moreAvailable)
+						{
+							if (complete)
+							{
+								// No more available, but the results are now complete anyway
+								yield break;
+							}
+
+							// No more available yet, not yet complete, wait until more becomes available
+							mResultsUpdated.WaitOne();
+						}
+						else
+						{
+							// More available now, so stop checking for more, continue with the loop to return them
+							break;
+						}
+					} while (true);
+
+					Debug.Assert(i <= count, "More should be available now");
+				}
+
+				yield return mResults[i];
+			}
+		}
+
+		public SearchResults CreateChildResults(string term)
+		{
+			Debug.Assert(term.StartsWith(mTerm));
+
+			int count;
+			bool complete;
+			lock (mLock)
+			{
+				count = mCount;
+				complete = mComplete;
+			}
+
+			// If complete, then we know we don't need more than count. Otherwise, it can't be more than this capacity anyway
+			var childCapacity = complete ? count : mResults.Length;
+
+			return new SearchResults(childCapacity, term);
+		}
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.Designer.cs b/AutoTypeSearch/SearchWindow.Designer.cs
new file mode 100755
index 0000000..18b37d1
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.Designer.cs
@@ -0,0 +1,201 @@
+using System.Windows.Forms;
+
+namespace AutoTypeSearch
+{
+	partial class SearchWindow
+	{
+		/// 
+		/// Required designer variable.
+		/// 
+		private System.ComponentModel.IContainer components = null;
+
+		#region Windows Form Designer generated code
+
+		/// 
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// 
+		private void InitializeComponent()
+		{
+			this.components = new System.ComponentModel.Container();
+			this.mSearch = new System.Windows.Forms.TextBox();
+			this.mResults = new System.Windows.Forms.ListBox();
+			this.mLayout = new System.Windows.Forms.TableLayoutPanel();
+			this.mBanner = new System.Windows.Forms.PictureBox();
+			this.mInfoBanner = new System.Windows.Forms.Panel();
+			this.mInfoLabel = new System.Windows.Forms.Label();
+			this.mInfoBannerImage = new System.Windows.Forms.PictureBox();
+			this.mThrobber = new System.Windows.Forms.PictureBox();
+			this.mResultsUpdater = new System.Windows.Forms.Timer(this.components);
+			this.mNoResultsLabel = new System.Windows.Forms.Label();
+			this.mLayout.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).BeginInit();
+			this.mInfoBanner.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).BeginInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).BeginInit();
+			this.SuspendLayout();
+			// 
+			// mSearch
+			// 
+			this.mSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+			this.mSearch.Location = new System.Drawing.Point(1, 78);
+			this.mSearch.Margin = new System.Windows.Forms.Padding(1, 0, 1, 0);
+			this.mSearch.Name = "mSearch";
+			this.mSearch.Size = new System.Drawing.Size(521, 20);
+			this.mSearch.TabIndex = 0;
+			this.mSearch.LocationChanged += new System.EventHandler(this.mSearch_LocationChanged);
+			this.mSearch.TextChanged += new System.EventHandler(this.mSearch_TextChanged);
+			// 
+			// mResults
+			// 
+			this.mResults.BorderStyle = System.Windows.Forms.BorderStyle.None;
+			this.mResults.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mResults.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
+			this.mResults.FormattingEnabled = true;
+			this.mResults.IntegralHeight = false;
+			this.mResults.Location = new System.Drawing.Point(0, 98);
+			this.mResults.Margin = new System.Windows.Forms.Padding(0);
+			this.mResults.Name = "mResults";
+			this.mResults.Size = new System.Drawing.Size(523, 176);
+			this.mResults.TabIndex = 1;
+			this.mResults.TabStop = false;
+			this.mResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseClick);
+			this.mResults.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.mResults_DrawItem);
+			this.mResults.LocationChanged += new System.EventHandler(this.mResults_LocationChanged);
+			this.mResults.MouseEnter += new System.EventHandler(this.mResults_MouseEnter);
+			this.mResults.MouseMove += new System.Windows.Forms.MouseEventHandler(this.mResults_MouseMove);
+			// 
+			// mLayout
+			// 
+			this.mLayout.ColumnCount = 1;
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+			this.mLayout.Controls.Add(this.mSearch, 0, 2);
+			this.mLayout.Controls.Add(this.mResults, 0, 3);
+			this.mLayout.Controls.Add(this.mBanner, 0, 0);
+			this.mLayout.Controls.Add(this.mInfoBanner, 0, 1);
+			this.mLayout.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mLayout.Location = new System.Drawing.Point(0, 0);
+			this.mLayout.Name = "mLayout";
+			this.mLayout.RowCount = 4;
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle());
+			this.mLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+			this.mLayout.Size = new System.Drawing.Size(523, 274);
+			this.mLayout.TabIndex = 2;
+			// 
+			// mBanner
+			// 
+			this.mBanner.Dock = System.Windows.Forms.DockStyle.Top;
+			this.mBanner.Location = new System.Drawing.Point(0, 0);
+			this.mBanner.Margin = new System.Windows.Forms.Padding(0);
+			this.mBanner.Name = "mBanner";
+			this.mBanner.Size = new System.Drawing.Size(523, 60);
+			this.mBanner.TabIndex = 3;
+			this.mBanner.TabStop = false;
+			this.mBanner.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mBannerImage_MouseDown);
+			// 
+			// mInfoBanner
+			// 
+			this.mInfoBanner.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+			this.mInfoBanner.BackColor = System.Drawing.SystemColors.Info;
+			this.mInfoBanner.Controls.Add(this.mInfoLabel);
+			this.mInfoBanner.Controls.Add(this.mInfoBannerImage);
+			this.mInfoBanner.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoBanner.Location = new System.Drawing.Point(2, 61);
+			this.mInfoBanner.Margin = new System.Windows.Forms.Padding(2, 1, 1, 1);
+			this.mInfoBanner.Name = "mInfoBanner";
+			this.mInfoBanner.Size = new System.Drawing.Size(520, 16);
+			this.mInfoBanner.TabIndex = 8;
+			// 
+			// mInfoLabel
+			// 
+			this.mInfoLabel.AutoEllipsis = true;
+			this.mInfoLabel.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.mInfoLabel.ForeColor = System.Drawing.SystemColors.InfoText;
+			this.mInfoLabel.Location = new System.Drawing.Point(16, 0);
+			this.mInfoLabel.Name = "mInfoLabel";
+			this.mInfoLabel.Size = new System.Drawing.Size(504, 16);
+			this.mInfoLabel.TabIndex = 6;
+			this.mInfoLabel.Text = "AutoType failed to find";
+			// 
+			// mInfoBannerImage
+			// 
+			this.mInfoBannerImage.Dock = System.Windows.Forms.DockStyle.Left;
+			this.mInfoBannerImage.Image = global::AutoTypeSearch.Properties.Resources.Info;
+			this.mInfoBannerImage.Location = new System.Drawing.Point(0, 0);
+			this.mInfoBannerImage.Margin = new System.Windows.Forms.Padding(0);
+			this.mInfoBannerImage.Name = "mInfoBannerImage";
+			this.mInfoBannerImage.Size = new System.Drawing.Size(16, 16);
+			this.mInfoBannerImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mInfoBannerImage.TabIndex = 7;
+			this.mInfoBannerImage.TabStop = false;
+			// 
+			// mThrobber
+			// 
+			this.mThrobber.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.mThrobber.BackColor = System.Drawing.SystemColors.Window;
+			this.mThrobber.Location = new System.Drawing.Point(503, 81);
+			this.mThrobber.Name = "mThrobber";
+			this.mThrobber.Size = new System.Drawing.Size(16, 16);
+			this.mThrobber.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+			this.mThrobber.TabIndex = 4;
+			this.mThrobber.TabStop = false;
+			this.mThrobber.Visible = false;
+			// 
+			// mResultsUpdater
+			// 
+			this.mResultsUpdater.Interval = 250;
+			this.mResultsUpdater.Tick += new System.EventHandler(this.mResultsUpdater_Tick);
+			// 
+			// mNoResultsLabel
+			// 
+			this.mNoResultsLabel.AutoSize = true;
+			this.mNoResultsLabel.Location = new System.Drawing.Point(5, 103);
+			this.mNoResultsLabel.Name = "mNoResultsLabel";
+			this.mNoResultsLabel.Size = new System.Drawing.Size(84, 13);
+			this.mNoResultsLabel.TabIndex = 5;
+			this.mNoResultsLabel.Text = "No results found";
+			// 
+			// SearchWindow
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.BackColor = System.Drawing.SystemColors.Window;
+			this.ClientSize = new System.Drawing.Size(523, 274);
+			this.ControlBox = false;
+			this.Controls.Add(this.mNoResultsLabel);
+			this.Controls.Add(this.mThrobber);
+			this.Controls.Add(this.mLayout);
+			this.MinimumSize = new System.Drawing.Size(160, 96);
+			this.Name = "SearchWindow";
+			this.ShowInTaskbar = false;
+			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+			this.TopMost = true;
+			this.mLayout.ResumeLayout(false);
+			this.mLayout.PerformLayout();
+			((System.ComponentModel.ISupportInitialize)(this.mBanner)).EndInit();
+			this.mInfoBanner.ResumeLayout(false);
+			((System.ComponentModel.ISupportInitialize)(this.mInfoBannerImage)).EndInit();
+			((System.ComponentModel.ISupportInitialize)(this.mThrobber)).EndInit();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.TextBox mSearch;
+		private System.Windows.Forms.ListBox mResults;
+		private System.Windows.Forms.TableLayoutPanel mLayout;
+		private System.Windows.Forms.PictureBox mBanner;
+		private PictureBox mThrobber;
+		private Timer mResultsUpdater;
+		private Label mNoResultsLabel;
+		private Label mInfoLabel;
+		private Panel mInfoBanner;
+		private PictureBox mInfoBannerImage;
+	}
+}
\ No newline at end of file
diff --git a/AutoTypeSearch/SearchWindow.cs b/AutoTypeSearch/SearchWindow.cs
new file mode 100755
index 0000000..363b898
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.cs
@@ -0,0 +1,925 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Media;
+using System.Reflection;
+using System.Text;
+using System.Windows.Forms;
+using AutoTypeSearch.Properties;
+using KeePass.Forms;
+using KeePass.Resources;
+using KeePass.UI;
+using KeePass.Util;
+using KeePassLib;
+using KeePassLib.Collections;
+using KeePassLib.Native;
+
+namespace AutoTypeSearch
+{
+	public partial class SearchWindow : Form
+	{
+		private const int SecondLineInset = 10;
+
+		// HACK to work around mono bug
+		private static readonly FieldInfo sMonoListBoxTopIndex = typeof(ListBox).GetField("top_index", BindingFlags.Instance | BindingFlags.NonPublic);
+
+		private readonly MainForm mMainForm;
+		private readonly Bitmap mBannerImage;
+		private readonly Searcher mSearcher;
+
+		private readonly Stream mThrobberImageStream;
+
+		private int? mWindowTopBorderHeight;
+		private int mBannerWidth = -1;
+		private int mMaximumExpandHeight;
+		private bool mManualSizeApplied;
+		private SearchResults mCurrentSearch;
+		private SearchResults mLastResultsUpdated;
+		private int mLastResultsUpdatedNextAvailableIndex;
+
+		#region Opening
+		public SearchWindow()
+		{
+			InitializeComponent();
+
+			// Mono can't load animated gifs from resx without crashing, so load it from an embedded resource instead
+			try
+			{
+				mThrobberImageStream = GetType().Assembly.GetManifestResourceStream("AutoTypeSearch.Throbber.gif");
+				if (mThrobberImageStream != null)
+				{
+					mThrobber.Image = Image.FromStream(mThrobberImageStream);
+				}
+			}
+			catch (Exception ex)
+			{
+				Debug.Fail("Failed to load Throbber.gif from embedded resource: " + ex.Message);
+			}
+
+			GlobalWindowManager.CustomizeControl(this);
+			UIUtil.SetExplorerTheme(mResults, true);
+			SetItemHeight();
+		}
+
+		public SearchWindow(MainForm mainForm, string infoBanner) : this()
+		{
+			mMainForm = mainForm;
+
+			mInfoBanner.Height = Math.Max(mInfoBannerImage.Height, mInfoLabel.Font.Height) + mInfoBanner.Margin.Vertical;
+			mInfoLabel.Padding = new Padding(0, (mInfoBanner.Height - mInfoLabel.Font.Height) / 2, 0, 0);
+			mInfoLabel.Text = infoBanner;
+
+			if (infoBanner == null)
+			{
+				mInfoBanner.Visible = false;
+				mInfoBanner.Height = 0;
+			}
+			
+			mSearcher = new Searcher(mMainForm.DocumentManager.GetOpenDatabases().ToArray());
+
+			Icon = mMainForm.Icon;
+			using (var bannerIcon = new Icon(Icon, 48, 48))
+			{
+				mBannerImage = bannerIcon.ToBitmap();
+			}
+			UpdateBanner();
+
+			ShowThrobber = false;
+
+			FontUtil.AssignDefaultItalic(mNoResultsLabel);
+		}
+
+
+		protected override void OnCreateControl()
+		{
+			base.OnCreateControl();
+
+			if (NativeMethods.IsWindows10())
+			{
+				mWindowTopBorderHeight = PointToScreen(Point.Empty).Y - this.Top;
+				NativeMethods.RefreshWindowFrame(Handle);
+			}
+
+			var windowRect = Settings.Default.WindowPosition;
+			var collapsedWindowRect = windowRect;
+			
+			collapsedWindowRect.Height = mSearch.Bottom + (Height - ClientSize.Height);
+
+			MinimumSize = new Size(MinimumSize.Width, collapsedWindowRect.Height);
+
+			if (windowRect.IsEmpty || !IsOnScreen(collapsedWindowRect))
+			{
+				windowRect = new Rectangle(0, 0, Width, Height);
+				Height = collapsedWindowRect.Height;
+
+				CenterToScreen();
+			}
+			else
+			{
+				Location = windowRect.Location;
+				Size = collapsedWindowRect.Size;
+			}
+
+			mMaximumExpandHeight = Math.Max(windowRect.Height, MinimumSize.Height + mResults.ItemHeight);
+		}
+		
+
+		private static bool IsOnScreen(Rectangle rectangle)
+		{
+			return Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(rectangle));
+		}
+
+		private void SetItemHeight()
+		{
+			mResults.ItemHeight = mResults.Font.Height * 2 + 2;
+		}
+
+		protected override void WndProc(ref Message m)
+		{
+			if (mWindowTopBorderHeight.HasValue)
+			{
+				NativeMethods.RemoveWindowFrameTopBorder(ref m, mWindowTopBorderHeight.Value);
+			}
+			base.WndProc(ref m);
+		}
+
+		#endregion
+
+		#region Closing
+		protected override void OnActivated(EventArgs e)
+		{
+			base.OnActivated(e);
+			Deactivate += OnDeactivate;
+		}
+
+		private void OnDeactivate(object sender, EventArgs eventArgs)
+		{
+			Close();
+		}
+
+		protected override void OnClosed(EventArgs e)
+		{
+			Deactivate -= OnDeactivate;
+			base.OnClosed(e);
+		}
+
+		/// 
+		/// Clean up any resources being used.
+		/// 
+		/// true if managed resources should be disposed; otherwise, false.
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				if (mBannerImage != null)
+				{
+					mBannerImage.Dispose();
+				}
+				if (mThrobber.Image != null)
+				{
+					mThrobber.Image.Dispose();
+					mThrobber.Image = null;
+					mThrobberImageStream.Dispose();
+				}
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+		#endregion
+
+		#region Item Drawing
+		private void mResults_DrawItem(object sender, DrawItemEventArgs e)
+		{
+			var searchResult = mResults.Items[e.Index] as SearchResult;
+			if (searchResult == null)
+			{
+				Debug.Fail("Unexpected item in mResults");
+// ReSharper disable once HeuristicUnreachableCode - Not unreachable
+				return;
+			}
+			var drawingArea = e.Bounds;
+			drawingArea.Height--; // Leave room for a dividing line at the bottom
+			
+			if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
+			{
+				DrawBorderedRectangle(e.Graphics, drawingArea, SystemColors.Highlight);
+			}
+			else
+			{
+				e.Graphics.FillRectangle(SystemBrushes.Window, drawingArea);
+			}
+
+			var image = GetImage(searchResult.Database, searchResult.Entry.CustomIconUuid, searchResult.Entry.IconId);
+			var imageMargin = (drawingArea.Height - image.Height) / 2;
+			e.Graphics.DrawImage(image, drawingArea.Left + imageMargin, drawingArea.Top + imageMargin, image.Width, image.Height);
+
+			var textLeftMargin = drawingArea.Left + imageMargin * 2 + image.Width;
+			var textBounds = new Rectangle(textLeftMargin, drawingArea.Top + 1, drawingArea.Width - textLeftMargin - 1, drawingArea.Height - 2);
+
+			var line1Bounds = textBounds;
+			line1Bounds.Height = e.Font.Height;
+			var line2Bounds = line1Bounds;
+			line2Bounds.Y += line2Bounds.Height - 1;
+			line2Bounds.X += SecondLineInset;
+			line2Bounds.Width -= SecondLineInset;
+
+			var resultInTitleField = searchResult.FieldName == PwDefs.TitleField;
+
+			var title = (resultInTitleField ? searchResult.FieldValue : searchResult.Title).Replace('\n', ' '); // The FieldValue may have references resolved, whereas the title is always read directly.
+
+			var uniqueTitlePartWidth = 0;
+			if (!String.IsNullOrEmpty(searchResult.UniqueTitlePart))
+			{
+				var uniqueTitlePart = searchResult.UniqueTitlePart.Replace('\n', ' ');
+
+				var titleWidth = TextRenderer.MeasureText(e.Graphics, title, e.Font, line1Bounds.Size, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+
+				var availableWidthForUniqueTitlePart = line1Bounds.Width - titleWidth;
+				if (availableWidthForUniqueTitlePart > 20) // Don't bother including a unique part if there's no room for it
+				{
+					var uniqueTitlePartReversed = ReverseString(uniqueTitlePart);
+
+					uniqueTitlePartWidth = TextRenderer.MeasureText(e.Graphics, uniqueTitlePartReversed, e.Font, new Size(availableWidthForUniqueTitlePart, line1Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+					uniqueTitlePart = ReverseString(uniqueTitlePartReversed);
+
+					TextRenderer.DrawText(e.Graphics, uniqueTitlePart, e.Font, new Rectangle(line1Bounds.X, line1Bounds.Y, uniqueTitlePartWidth, line1Bounds.Height), SystemColors.GrayText, TextFormatFlags.NoPadding);
+				}
+			}
+
+			var titleBounds = new Rectangle(line1Bounds.X + uniqueTitlePartWidth, line1Bounds.Y, line1Bounds.Width - uniqueTitlePartWidth, line1Bounds.Height);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Highlight title in first line.
+				DrawHighlight(e, titleBounds, title, searchResult.Start, searchResult.Length);
+			}
+
+			TextRenderer.DrawText(e.Graphics, searchResult.Title, e.Font, titleBounds, SystemColors.WindowText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+
+			if (resultInTitleField)
+			{
+				// Found the result in the title field. Use Username for second line.
+				TextRenderer.DrawText(e.Graphics, KPRes.UserName + ": " + searchResult.Entry.Strings.ReadSafeEx(PwDefs.UserNameField), e.Font, line2Bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+			}
+			else
+			{
+				// Found the result in not title field. Show the matching result on second line
+				
+				var fieldValue = searchResult.FieldValue.Replace('\n',' ');
+				var fieldNamePrefix = GetDisplayFieldName(searchResult.FieldName) + ": ";
+
+				var remainingSpace = line2Bounds.Width;
+				var fieldNamePrefixWidth = TextRenderer.MeasureText(e.Graphics, fieldNamePrefix, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+				remainingSpace -= fieldNamePrefixWidth;
+
+				int fieldValueHighlightWidth = 0, fieldValueLeftContextWidth = 0, fieldValueRightContextWidth = 0;
+
+				var leftContext = fieldValue.Substring(0, searchResult.Start);
+				var highlight = fieldValue.Substring(searchResult.Start, searchResult.Length);
+				var rightContext = fieldValue.Substring(searchResult.Start + searchResult.Length);
+
+				if (searchResult.Length == 0)
+				{
+					fieldValueHighlightWidth = remainingSpace;
+				}
+				else
+				{
+					if (remainingSpace > 0)
+					{
+						var availableSpace = remainingSpace;
+						fieldValueHighlightWidth = TextRenderer.MeasureText(e.Graphics, highlight, e.Font, new Size(availableSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						remainingSpace -= fieldValueHighlightWidth;
+					}
+
+					// Of the space remaining, divide it equally between that which comes before, and that which comes after
+					if (!String.IsNullOrEmpty(leftContext))
+					{
+						var leftContextReversed = ReverseString(leftContext);
+						fieldValueLeftContextWidth = TextRenderer.MeasureText(e.Graphics, leftContextReversed, e.Font, new Size(remainingSpace / 2, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis | TextFormatFlags.ModifyString).Width;
+
+						if (fieldValueLeftContextWidth > remainingSpace)
+						{
+							// Always allow space for the minimal left context
+							fieldValueHighlightWidth -= (fieldValueLeftContextWidth - remainingSpace);
+							remainingSpace = 0;
+						}
+						else
+						{
+							remainingSpace -= fieldValueLeftContextWidth;							
+						}
+						
+						// Replace left context with the truncated reversed left context.
+						leftContext = ReverseString(leftContextReversed);
+					}
+
+					if (remainingSpace > 0 && !String.IsNullOrEmpty(rightContext))
+					{
+						fieldValueRightContextWidth = TextRenderer.MeasureText(e.Graphics, rightContext, e.Font, new Size(remainingSpace, line2Bounds.Height), TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis).Width;
+						if (fieldValueRightContextWidth > remainingSpace)
+						{
+							fieldValueRightContextWidth = 0;
+						}
+					}
+				}
+
+				// Now draw it all
+				var bounds = line2Bounds;
+				bounds.Width = fieldNamePrefixWidth;
+				TextRenderer.DrawText(e.Graphics, fieldNamePrefix, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				if (fieldValueLeftContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueLeftContextWidth;
+					TextRenderer.DrawText(e.Graphics, leftContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding); // No ellipsis as the leftContext string has already been truncated appropriately
+				}
+				if (fieldValueHighlightWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueHighlightWidth;
+
+					if (searchResult.Length > 0)
+					{
+						DrawHighlightRectangle(e, bounds);
+					}
+					TextRenderer.DrawText(e.Graphics, highlight, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+				if (fieldValueRightContextWidth > 0)
+				{
+					bounds.X += bounds.Width;
+					bounds.Width = fieldValueRightContextWidth;
+					TextRenderer.DrawText(e.Graphics, rightContext, e.Font, bounds, SystemColors.GrayText, TextFormatFlags.NoPadding | TextFormatFlags.EndEllipsis);
+				}
+			}
+
+			e.Graphics.DrawLine(SystemPens.ButtonFace, drawingArea.Left, drawingArea.Bottom, drawingArea.Right, drawingArea.Bottom);
+		}
+
+		private static string ReverseString(string value)
+		{
+			return new String(value.ToCharArray().TakeWhile(c => c != '\0').Reverse().ToArray());
+		}
+
+		private static void DrawHighlight(DrawItemEventArgs e, Rectangle lineBounds, string text, int highlightFrom, int highlightLength)
+		{
+			var highlightX = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width;
+			var highlightWidth = TextRenderer.MeasureText(e.Graphics, text.Substring(0, highlightFrom + highlightLength), e.Font, Size.Empty, TextFormatFlags.NoPadding).Width - highlightX;
+
+			DrawHighlightRectangle(e, new Rectangle(lineBounds.Left + highlightX, lineBounds.Top, highlightWidth, lineBounds.Height));
+		}
+
+		private static void DrawHighlightRectangle(DrawItemEventArgs e, Rectangle rectangle)
+		{
+			DrawBorderedRectangle(e.Graphics, rectangle, Color.PaleTurquoise);
+		}
+
+		private static void DrawBorderedRectangle(Graphics graphics, Rectangle rectangle, Color colour)
+		{
+			var border = rectangle;
+			border.Width--;
+			border.Height--;
+
+			using (var brush = new SolidBrush(MergeColors(colour, SystemColors.Window, 0.2)))
+			{
+				graphics.FillRectangle(brush, rectangle);
+			}
+			using (var pen = new Pen(colour, 1f))
+			{
+				graphics.DrawRectangle(pen, border);
+			}
+		}
+
+		private Image GetImage(PwDatabase database, PwUuid customIconId, PwIcon iconId)
+		{
+			Image image = null;
+			if (!customIconId.Equals(PwUuid.Zero))
+			{
+				image = database.GetCustomIcon(customIconId, DpiUtil.ScaleIntX(16), DpiUtil.ScaleIntY(16));
+			}
+			if (image == null)
+			{
+				try { image = mMainForm.ClientIcons.Images[(int)iconId]; }
+				catch (Exception) { Debug.Assert(false); }
+			}
+
+			return image;
+		}
+
+		private static string GetDisplayFieldName(string fieldName)
+		{
+			switch (fieldName)
+			{
+				case PwDefs.TitleField:
+					return KPRes.Title;
+				case PwDefs.UserNameField:
+					return KPRes.UserName;
+				case PwDefs.PasswordField:
+					return KPRes.Password;
+				case PwDefs.UrlField:
+					return KPRes.Url;
+				case PwDefs.NotesField:
+					return KPRes.Notes;
+				case AutoTypeSearchExt.TagsVirtualFieldName:
+					return KPRes.Tags;
+				default:
+					return fieldName;
+			}
+		}
+
+		public static Color MergeColors(Color from, Color to, double amount)
+		{
+			var r = (byte)((from.R * amount) + to.R * (1 - amount));
+			var g = (byte)((from.G * amount) + to.G * (1 - amount));
+			var b = (byte)((from.B * amount) + to.B * (1 - amount));
+			return Color.FromArgb(r, g, b);
+		}
+		#endregion
+
+		#region Mouse tracking
+		private Point mMouseEntryPosition;
+		
+		private void mResults_MouseEnter(object sender, EventArgs e)
+		{
+			mMouseEntryPosition = MousePosition;
+		}
+
+		private void mResults_MouseMove(object sender, MouseEventArgs e)
+		{
+			// Discard the location the mouse has on entering the control (as it may be that the control has just moved under the mouse, not the other way around)
+			if (MousePosition == mMouseEntryPosition)
+			{
+				return;
+			}
+
+			// Hot tracking
+			var hoverIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (hoverIndex >= 0 && mResults.SelectedIndex != hoverIndex)
+			{
+				if (mResults.GetItemRectangle(hoverIndex).Bottom <= mResults.ClientRectangle.Bottom)
+				{
+					mResults.SelectedIndex = hoverIndex;
+				}
+				else
+				{
+					// Avoid the control scrolling
+					mResults.BeginUpdate();
+					var topIndex = mResults.TopIndex;
+					mResults.SelectedIndex = hoverIndex;
+					mResults.TopIndex = topIndex;
+					mResults.EndUpdate();
+				}
+			}
+		}
+		#endregion
+
+		#region Resizing
+		protected override void OnResizeBegin(EventArgs e)
+		{
+			// Stop automatically sizing - the user is picking a size they want.
+			mManualSizeApplied = true;
+			base.OnResizeBegin(e);
+		}
+
+		protected override void OnResize(EventArgs e)
+		{
+			base.OnResize(e);
+
+			UpdateBanner();
+
+			mResults.Invalidate();
+		}
+
+		protected override void OnResizeEnd(EventArgs e)
+		{
+			base.OnResizeEnd(e);
+
+			if (Height > MinimumSize.Height && Height != mMaximumExpandHeight)
+			{
+				mMaximumExpandHeight = Math.Max(Height, MinimumSize.Height + mResults.ItemHeight);
+			}
+			else
+			{
+				mManualSizeApplied = false;
+			}
+
+			Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+		}
+
+		private void UpdateBanner()
+		{
+			if (mBannerImage != null)
+			{
+				BannerFactory.UpdateBanner(this, mBanner, mBannerImage, PwDefs.ProductName, Resources.BannerText, ref mBannerWidth);
+			}
+		}
+
+		private void mSearch_LocationChanged(object sender, EventArgs e)
+		{
+			mThrobber.Location = new Point(mSearch.Right - mThrobber.Width - mThrobber.Margin.Right, mSearch.Top + (mSearch.Height - mThrobber.Height) / 2);
+		}
+
+		private void mResults_LocationChanged(object sender, EventArgs e)
+		{
+			mNoResultsLabel.Top = mResults.Top + (mResults.ItemHeight - mNoResultsLabel.Height) / 2;
+		}
+		#endregion
+
+		#region Searching
+		private static readonly SearchResultPrecedence SearchResultPrecedenceComparer = new SearchResultPrecedence();
+		private void mSearch_TextChanged(object sender, EventArgs e)
+		{
+			if (mSearch.Text.Length < 2)
+			{
+				// Stop searching
+				mResultsUpdater.Enabled = false;
+				ShowThrobber = false;
+				Height = MinimumSize.Height;
+				mManualSizeApplied = false;
+				mResults.Items.Clear();
+				mLastResultsUpdated = null;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			else
+			{
+				// Start searching
+				mNoResultsLabel.Visible = false;
+				mCurrentSearch = mSearcher.Search(mSearch.Text);
+				mResultsUpdater.Enabled = true;
+				ShowThrobber = true;
+				mResultsUpdater_Tick(null, EventArgs.Empty); // Quick poke just in case the results are already done.
+			}
+		}
+
+		[SuppressMessage("ReSharper", "CoVariantArrayConversion", Justification = "Object arrays for Listbox.Items, known to be of correct type")]
+		private void mResultsUpdater_Tick(object sender, EventArgs e)
+		{
+			if (mLastResultsUpdated != mCurrentSearch)
+			{
+				// Clear out old results and replace with new ones
+				mResults.Items.Clear();
+				mLastResultsUpdated = mCurrentSearch;
+				mLastResultsUpdatedNextAvailableIndex = 0;
+			}
+			var existingResultsCount = mResults.Items.Count;
+			
+			bool complete;
+			var newResults = mLastResultsUpdated.GetAvailableResults(ref mLastResultsUpdatedNextAvailableIndex, out complete);
+			if (newResults.Length > 0)
+			{
+				mResults.BeginUpdate();
+				
+				SearchResult[] allResults;
+				if (existingResultsCount > 0)
+				{
+					allResults = new SearchResult[existingResultsCount + newResults.Length];
+					mResults.Items.CopyTo(allResults, 0);
+					newResults.CopyTo(allResults, existingResultsCount);
+
+					mResults.Items.Clear();
+				}
+				else
+				{
+					allResults = newResults;
+				}
+
+				CalculateUniqueTitles(allResults);
+
+				Array.Sort(allResults, SearchResultPrecedenceComparer);
+				mResults.Items.AddRange(allResults);
+				
+				mResults.EndUpdate();
+
+				if (allResults.Length > 0)
+				{
+					if (mResults.SelectedIndex == -1)
+					{
+						try
+						{
+							// HACK to work around mono bug
+							if (sMonoListBoxTopIndex != null)
+							{
+								sMonoListBoxTopIndex.SetValue(mResults, 1); // Set the top_index to 1 so that when selected index is set to 0, and calls EnsureVisible(0), it follows the index < top_index pass and not the broken index >= top_index + rows path. 
+							}
+
+							mResults.SelectedIndex = 0;
+							mResults.TopIndex = 0;
+						}
+						catch (Exception ex)
+						{
+							Debug.Fail("Failed to set selection on count of " + allResults.Length + ": " + ex.Message);
+						}
+					}
+
+					if (!mManualSizeApplied)
+					{
+						Height = Math.Min(mMaximumExpandHeight, MinimumSize.Height + (allResults.Length * mResults.ItemHeight));
+					}
+				}
+			}
+
+			if (complete)
+			{
+				ShowThrobber = false;
+				mResultsUpdater.Enabled = false;
+
+				if (mResults.Items.Count == 0)
+				{
+					mNoResultsLabel.Visible = true;
+					Height = MinimumSize.Height + mResults.ItemHeight;
+					mManualSizeApplied = false;
+				}
+			}
+		}
+
+		private void CalculateUniqueTitles(IEnumerable results, int depth = 0)
+		{
+			// Where results have identical titles, include group titles to make them unique
+			depth += 1;
+
+			// First create a lookup by title
+			var titles = new Dictionary>();
+			foreach (var searchResult in results)
+			{
+				List resultsWithSameTitle;
+				if (titles.TryGetValue(searchResult.UniqueTitle, out resultsWithSameTitle))
+				{
+					resultsWithSameTitle.Add(searchResult);
+				}
+				else
+				{
+					titles.Add(searchResult.UniqueTitle, new List { searchResult });
+				}
+			}
+
+			// Attempt to unique-ify any non-unique titles
+			foreach (var resultsSharingTitle in titles.Values)
+			{
+				if (resultsSharingTitle.Count > 1)
+				{
+					var titlesModified = false;
+					foreach (var searchResult in resultsSharingTitle)
+					{
+						titlesModified |= searchResult.SetUniqueTitleDepth(depth);
+					}
+
+					if (titlesModified)
+					{
+						// Recurse in case of continuing non-uniqueness
+						CalculateUniqueTitles(resultsSharingTitle, depth);
+					}
+				}
+			}
+		}
+
+		private class SearchResultPrecedence : IComparer
+		{
+			public int Compare(SearchResult x, SearchResult y)
+			{
+				// First precedence is that if the result is the start of the field value, it's higher precedence than if it doesn't.
+				var result = -(x.Start == 0).CompareTo(y.Start == 0);
+
+				// Second precedence is that the start of the title field is higher precedence than the start of any other field
+				if (result == 0)
+				{
+					result = -(x.FieldName == PwDefs.TitleField).CompareTo(y.FieldName == PwDefs.TitleField);
+				}
+
+				// Both start the title field, so both equal. Have to have consistent ordering, so return final precedence based search index
+				if (result == 0)
+				{
+					result = x.ResultIndex.CompareTo(y.ResultIndex);
+				}
+				
+				return result;
+			}
+		}
+
+		private bool ShowThrobber
+		{
+			get { return mThrobber.Visible; }
+			set
+			{
+				if (value != ShowThrobber)
+				{
+					if (value)
+					{
+						mThrobber.Visible = true;
+
+						// Set the margin on the textbox to allow room for the throbber
+						NativeMethods.SetTextBoxRightMargin(mSearch, mThrobber.Width + mThrobber.Margin.Right);
+					}
+					else
+					{
+						mThrobber.Visible = false;
+
+						NativeMethods.SetTextBoxRightMargin(mSearch, 0);
+					}
+				}
+			}
+		}
+		#endregion
+
+		private void mBannerImage_MouseDown(object sender, MouseEventArgs e)
+		{
+			// Allow drag by banner image
+			if (e.Button == MouseButtons.Left)
+			{
+				if (e.Clicks == 2)
+				{
+					// Re-center the form on double-click
+					CenterToScreen();
+
+					Settings.Default.WindowPosition = new Rectangle(Left, Top, Width, mMaximumExpandHeight);
+				}
+				else if (!NativeLib.IsUnix())
+				{
+					NativeMethods.StartFormDrag(this);
+				}
+			}
+		}
+
+		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
+		{
+			switch (keyData)
+			{
+				case Keys.Escape:
+					Close();
+					return true;
+				case Keys.Up:
+					TryChangeSelection(-1);
+					return true;
+				case Keys.Down:
+					TryChangeSelection(1);
+					return true;
+				case Keys.PageUp:
+					TryChangeSelection(-mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.PageDown:
+					TryChangeSelection(mResults.ClientSize.Height / mResults.ItemHeight);
+					return true;
+				case Keys.Home | Keys.Control:
+					mResults.SelectedIndex = 0;
+					return true;
+				case Keys.End | Keys.Control:
+					mResults.SelectedIndex = mResults.Items.Count - 1;
+					return true;
+				case Keys.Enter:
+					PerformAction(Settings.Default.DefaultAction, mResults.SelectedItem as SearchResult);
+					break;
+				case Keys.Enter | Keys.Shift:
+					PerformAction(Settings.Default.AlternativeAction, mResults.SelectedItem as SearchResult);
+					break;
+			}
+			
+			return base.ProcessCmdKey(ref msg, keyData);
+		}
+
+		#region Selection Changing
+
+		protected override void OnMouseWheel(MouseEventArgs e)
+		{
+			mResults.TopIndex -= (e.Delta / Math.Abs(e.Delta));
+		}
+
+		private void TryChangeSelection(int delta)
+		{
+			if (mResults.Items.Count > 0)
+			{
+				mResults.SelectedIndex = Math.Max(Math.Min(mResults.Items.Count - 1, mResults.SelectedIndex + delta), 0);
+			}
+		}
+		#endregion
+
+		#region Actions
+
+		private void mResults_MouseClick(object sender, MouseEventArgs e)
+		{
+			var clickIndex = mResults.IndexFromPoint(e.X, e.Y);
+			if (clickIndex >= 0)
+			{
+				var clickedResult = mResults.Items[clickIndex] as SearchResult;
+				if (clickedResult != null)
+				{
+					PerformAction((ModifierKeys & Keys.Shift) == Keys.Shift ? Settings.Default.AlternativeAction : Settings.Default.DefaultAction, clickedResult);
+				}
+			}
+		}
+
+		private void PerformAction(Actions action, SearchResult searchResult)
+		{
+			Close();
+
+			if (searchResult != null)
+			{
+				switch (action)
+				{
+					case Actions.PerformAutoType:
+						AutoTypeEntry(searchResult);
+						break;
+					case Actions.EditEntry:
+						EditEntry(searchResult);
+						break;
+					case Actions.ShowEntry:
+						ShowEntry(searchResult);
+						break;
+					case Actions.OpenEntryUrl:
+						OpenEntryUrl(searchResult);
+						break;
+					case Actions.CopyPassword:
+						CopyPassword(searchResult);
+						break;
+					default:
+						throw new ArgumentOutOfRangeException("action");
+				}
+			}
+		}
+
+		private void AutoTypeEntry(SearchResult searchResult)
+		{
+			bool result;
+			if (ActiveForm != null)
+			{
+				result = AutoType.PerformIntoPreviousWindow(mMainForm, searchResult.Entry, searchResult.Database);
+			}
+			else
+			{
+				result = AutoType.PerformIntoCurrentWindow(searchResult.Entry, searchResult.Database);
+			}
+			if (!result)
+			{
+				SystemSounds.Beep.Play();
+
+				if (Settings.Default.AlternativeAction != Actions.PerformAutoType)
+				{
+					PerformAction(Settings.Default.AlternativeAction, searchResult);
+				}
+			}
+		}
+
+		private void EditEntry(SearchResult searchResult)
+		{
+			using (var entryForm = new PwEntryForm())
+			{
+				mMainForm.MakeDocumentActive(mMainForm.DocumentManager.FindDocument(searchResult.Database));
+				
+				entryForm.InitEx(searchResult.Entry, PwEditMode.EditExistingEntry, searchResult.Database, mMainForm.ClientIcons, false, false);
+
+				ShowForegroundDialog(entryForm);
+
+				mMainForm.UpdateUI(false, null, searchResult.Database.UINeedsIconUpdate, null, true, null, entryForm.HasModifiedEntry);
+			}
+		}
+
+// ReSharper disable once UnusedMethodReturnValue.Local - Generic helper, result may be used in future
+		private DialogResult ShowForegroundDialog(Form form)
+		{
+			mMainForm.EnsureVisibleForegroundWindow(false, false);
+			form.StartPosition = FormStartPosition.CenterScreen;
+			if (mMainForm.IsTrayed())
+			{
+				form.ShowInTaskbar = true;
+			}
+
+			form.Shown += ActivateFormOnShown;
+			return form.ShowDialog(mMainForm);
+		}
+
+		private static void ActivateFormOnShown(object sender, EventArgs eventArgs)
+		{
+			var form = (Form)sender;
+			form.Shown -= ActivateFormOnShown;
+			form.Activate();
+		}
+
+		private void ShowEntry(SearchResult searchResult)
+		{
+			// Show this entry
+			mMainForm.UpdateUI(false, mMainForm.DocumentManager.FindDocument(searchResult.Database), true, searchResult.Entry.ParentGroup, true, null, false, null);
+			mMainForm.SelectEntries(new PwObjectList { searchResult.Entry }, true, true);
+			mMainForm.EnsureVisibleEntry(searchResult.Entry.Uuid);
+			mMainForm.UpdateUI(false, null, false, null, false, null, false);
+			mMainForm.EnsureVisibleForegroundWindow(true, true);
+		}
+
+		private void OpenEntryUrl(SearchResult searchResult)
+		{
+			WinUtil.OpenEntryUrl(searchResult.Entry);
+		}
+
+		private void CopyPassword(SearchResult searchResult)
+		{
+			if (ClipboardUtil.Copy(searchResult.Entry.Strings.ReadSafe(PwDefs.PasswordField), true, true, searchResult.Entry,
+									mMainForm.DocumentManager.SafeFindContainerOf(searchResult.Entry),
+									IntPtr.Zero))
+			{
+				mMainForm.StartClipboardCountdown();
+			}
+		}
+		
+		#endregion
+	}
+}
diff --git a/AutoTypeSearch/SearchWindow.resx b/AutoTypeSearch/SearchWindow.resx
new file mode 100755
index 0000000..8ef82f0
--- /dev/null
+++ b/AutoTypeSearch/SearchWindow.resx
@@ -0,0 +1,123 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    17, 17
+  
+
\ No newline at end of file
diff --git a/AutoTypeSearch/Searcher.cs b/AutoTypeSearch/Searcher.cs
new file mode 100755
index 0000000..433ae94
--- /dev/null
+++ b/AutoTypeSearch/Searcher.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using AutoTypeSearch.Properties;
+using KeePassLib;
+
+namespace AutoTypeSearch
+{
+	internal class Searcher
+	{
+		private readonly PwDatabase[] mDatabases;
+		private readonly Dictionary mSearches = new Dictionary();
+
+		public Searcher(PwDatabase[] databases)
+		{
+			mDatabases = databases;
+		}
+
+		public SearchResults Search(string term)
+		{
+			if (term.Length < 2)
+			{
+				throw new ArgumentException("Search term must be at least 2 characters");
+			}
+
+			SearchResults parentResults = null;
+
+			var termParent = term;
+			while (termParent.Length >= 2)
+			{
+				if (mSearches.TryGetValue(termParent, out parentResults))
+				{
+					if (termParent == term)
+					{
+						// This is an exact duplicate search, so return it.
+						return parentResults;
+					}
+
+					// Found an existing search for a parent of the term, start from there.
+					break;
+				}
+		
+				// No existing search for termParent found, try less.
+				termParent = termParent.Remove(termParent.Length - 1, 1);
+			}
+
+			SearchResults searchResults;
+			if (parentResults == null)
+			{
+				// No parent found at all, start from scratch
+				searchResults = new SearchResults(GetCountOfAllDatabaseEntries(), term);
+
+				var rootSearchThread = new Thread(RootSearchWorker) { Name = term };
+				rootSearchThread.Start(searchResults);
+			}
+			else
+			{
+				searchResults = parentResults.CreateChildResults(term);
+
+				var childSearchThread = new Thread(ChildSearchWorker) { Name = term };
+				childSearchThread.Start(new ChildSearchWorkerState{ Source = parentResults, Results = searchResults });
+			}
+
+			mSearches.Add(term, searchResults);
+
+			return searchResults;
+		}
+
+		private int GetCountOfAllDatabaseEntries()
+		{
+			return (from database in mDatabases select (int)database.RootGroup.GetEntriesCount(true)).Sum();
+		}
+
+		private void RootSearchWorker(object stateObject)
+		{
+			var results = (SearchResults)stateObject;
+			var excludeExpired = Settings.Default.ExcludeExpired;
+			var searchStartTime = DateTime.Now;
+
+			foreach (var database in mDatabases)
+			{
+				SearchGroup(database, database.RootGroup, results, excludeExpired, searchStartTime);	
+			}
+
+			results.SetComplete();
+		}
+
+		/// 
+		/// Recursively search  and its children, adding results to 
+		/// 
+		private void SearchGroup(PwDatabase context, PwGroup group, SearchResults results, bool excludeExpired, DateTime searchStartTime)
+		{
+			if (group.EnableSearching ?? true) // Group will only be searched if it's parent enabled searching, so if it is inherit (null) or true, search it.
+			{
+				foreach (var childGroup in group.Groups)
+				{
+					SearchGroup(context, childGroup, results, excludeExpired, searchStartTime);
+				}
+
+				foreach (var entry in group.Entries)
+				{
+					if (!(excludeExpired && entry.Expires && searchStartTime > entry.ExpiryTime))
+					{
+						results.AddResultIfMatchesTerm(context, entry);
+					}
+				}
+			}
+		}
+
+		private struct ChildSearchWorkerState
+		{
+			public SearchResults Source;
+			public SearchResults Results;
+		}
+		private void ChildSearchWorker(object stateObject)
+		{
+			var state = (ChildSearchWorkerState)stateObject;
+
+			bool complete;
+			var index = 0;
+			do
+			{
+				foreach (var entry in state.Source.GetAvailableResults(ref index, out complete))
+				{
+					state.Results.AddResultIfMatchesTerm(entry);
+				}
+			} while (!complete);
+
+			state.Results.SetComplete();
+		}
+	}
+}
diff --git a/AutoTypeSearch/Throbber.gif b/AutoTypeSearch/Throbber.gif
new file mode 100755
index 0000000..494d426
--- /dev/null
+++ b/AutoTypeSearch/Throbber.gif
Binary files differ
diff --git a/AutoTypeSearch/app.config b/AutoTypeSearch/app.config
new file mode 100755
index 0000000..1370758
--- /dev/null
+++ b/AutoTypeSearch/app.config
@@ -0,0 +1,60 @@
+
+
+    
+        
+            
+        
+    
+    
+        
+            
+                True
+            
+            
+                False
+            
+            
+                True
+            
+            
+                True
+            
+            
+                True
+            
+            
+                True
+            
+            
+                False
+            
+            
+                0, 0, 0, 0
+            
+            
+                True
+            
+            
+                False
+            
+            
+                True
+            
+            
+                False
+            
+            
+                False
+            
+            
+                PerformAutoType
+            
+            
+                EditEntry
+            
+            
+                None
+            
+        
+    
+
\ No newline at end of file
diff --git a/CreatePlgX.bat b/CreatePlgX.bat
new file mode 100755
index 0000000..59b9aa0
--- /dev/null
+++ b/CreatePlgX.bat
@@ -0,0 +1,20 @@
+@echo off
+cd %~dp0
+
+echo Deleting existing PlgX folder
+rmdir /s /q PlgX
+
+echo Creating PlgX folder
+mkdir PlgX
+
+echo Copying files
+xcopy "AutoTypeSearch" PlgX /s /e /exclude:PlgXExclude.txt
+
+echo Compiling PlgX
+"../KeePass/KeePass.exe" /plgx-create "%~dp0PlgX" --plgx-prereq-kp:2.27
+
+echo Releasing PlgX
+move /y PlgX.plgx "Releases\Build Outputs\AutoTypeSearch.plgx"
+
+echo Cleaning up
+rmdir /s /q PlgX
diff --git a/PlgXExclude.txt b/PlgXExclude.txt
new file mode 100755
index 0000000..f626d58
--- /dev/null
+++ b/PlgXExclude.txt
@@ -0,0 +1,7 @@
+\bin\
+\obj\
+.user
+.sln
+.suo
+.pdb
+.xml
\ No newline at end of file
diff --git a/Readme.txt b/Readme.txt
new file mode 100755
index 0000000..96d2fc0
--- /dev/null
+++ b/Readme.txt
@@ -0,0 +1,103 @@
+AutoTypeSearch
+==============
+http://sourceforge.net/projects/autotypesearch
+
+
+This is a plugin to KeePass  to provide a quick searching capability as
+an enhancement to the global auto-type system. If a global auto-type is requested, but no matching
+entry for the active window is found, this plugin will show a quick as-you-type search window which
+lets you to easily pick the entry to auto-type.
+
+
+Installation
+------------
+Place AutoTypeSearch.plgx in your KeePass Plugins folder.
+
+
+Usage
+-----
+AutoTypeSearch is initially configured to automatically appear after an unsuccessful global
+auto-type. However, this can be changed in the KeePass Options window (an AutoTypeShow tab has
+been added). Here, a system-wide hot key can be configured to show the AutoTypeSearch window
+immediately. It is also possible to show the window by running KeePass.exe passing "/e1:AutoTypeSearch"
+as a command line parameter.
+
+Once the window is shown, usage is extremely simple. Just start typing, and AutoTypeSearch will
+search your database for matching entries. By default, the Title, Url, Notes, Tags, and Custom Fields
+will be searched, but this can be configured in the AutoTypeShow tab of the KeePass Options window.
+
+Protected fields (like Password) will not be searched.
+
+The arrow keys can be used to move the selection in the list of results, then press Enter to auto-
+type the selected entry. Alternatively, press Shift+Enter to open the entry instead of auto-typing it.
+(These actions can also be customised in the Options window.) Clicking and Shift-Clicking an entry will
+also perform those actions.
+
+
+Uninstallation
+--------------
+Delete AutoTypeSearch.plgx from your KeePass Plugins folder.
+
+
+Checking for updates
+--------------------
+If you want to use the KeePass Check for Updates function to check for updates to this plugin
+then it requires the SourceForgeUpdateChecker plugin to be installed too:
+http://sourceforge.net/projects/kpsfupdatechecker
+
+
+Bug Reporting, Questions, Comments, Feedback, Donations
+-------------------------------------------------------
+Please use the SourceForge project page: 
+Bugs can be reported using the issue tracker, for anything else, a discussion forum is available.
+
+
+Changelog
+---------
+v0.1
+ Initial release
+
+v0.2
+ Added information banner when search is shown as a result of an unsuccessful global auto-type
+ Compatibility with Linux/Mono
+
+v0.3
+ Added search result prioritisation for entries where the match is found at the start of the field
+
+v0.4
+ Added support for multiple databases. All currently open, unlocked, databases will be searched
+
+v0.5
+ Added support for KeePass 2.29 high resolution custom icons
+
+v0.6
+ Where title does not uniquely identify the results shown, now also shows the group name as context
+
+v0.7
+ Added support for the "Open entry URL" action. Use the Options window to choose this, if required.
+
+v0.8
+ Added support for the "Copy password" action. Use the Options window to choose this, if required.
+
+v0.9
+ Added workaround for mono bug under Linux that could cause an ArgumentOutOfRange crash when 
+  searching if only a single result is initially returned.
+
+v0.91
+ Fixed bug where up or down keys would cause an exception if there are no results to scroll through
+
+v0.10
+ Compatibility with KeePass 2.41 (No longer compatible with previous versions)
+
+v0.11
+ Diacritic (accent) insensitive searching
+
+v0.12
+ Removed ugly white top border under Windows 10
+
+v1.0
+ Compatibility with KeePass 2.42. For versions of KeePass prior to 2.42, use an 0.X version.
+
+Attributions
+------------
+Throbber image by FlipDarius http://www.mediawiki.org/wiki/File:Loading.gif
\ No newline at end of file
diff --git a/Releases/PackageRelease.bat b/Releases/PackageRelease.bat
new file mode 100755
index 0000000..3fb646d
--- /dev/null
+++ b/Releases/PackageRelease.bat
@@ -0,0 +1,23 @@
+@echo off
+set version=1.0
+set output=%~dp0v%version%\
+set zipfile="%output%AutoTypeSearch-v%version%.zip"
+set buildoutputs="%~dp0Build Outputs"
+
+rd /s /q "%output%"
+
+copy "%~dp0..\Readme.txt" %buildoutputs%
+rem copy "%~dp0..\COPYING" %buildoutputs%
+
+rem don't include pdb files
+rem del %buildoutputs%\*.pdb
+
+pushd %buildoutputs%
+"%ProgramFiles%\7-Zip\7z.exe" a -tzip -mx9 -bd %zipfile% *
+popd
+copy "%~dp0..\Readme.txt" "%output%"
+
+set version=
+set output=
+set zipfile=
+set buildoutputs=
\ No newline at end of file