=== modified file 'src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumInfo.cs'
--- src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumInfo.cs	2008-12-29 20:36:08 +0000
+++ src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseAlbumInfo.cs	2009-02-07 00:04:17 +0000
@@ -186,7 +186,7 @@
         
         [DatabaseColumn(Select = false)]
         protected string TitleLowered {
-            get { return Title == null ? null : Title.ToLower (); }
+            get { return Hyena.StringUtil.LowerAndStripIgnored (Title); }
         }
 
         [DatabaseColumn]
@@ -197,7 +197,7 @@
 
         [DatabaseColumn(Select = false)]
         protected string ArtistNameLowered {
-            get { return ArtistName == null ? null : ArtistName.ToLower (); }
+            get { return Hyena.StringUtil.LowerAndStripIgnored (ArtistName); }
         }
 
         public override string ToString ()

=== modified file 'src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistInfo.cs'
--- src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistInfo.cs	2008-08-19 18:05:46 +0000
+++ src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseArtistInfo.cs	2009-02-07 00:04:00 +0000
@@ -140,7 +140,7 @@
         
         [DatabaseColumn(Select = false)]
         protected string NameLowered {
-            get { return Name == null ? null : Name.ToLower (); }
+            get { return Hyena.StringUtil.LowerAndStripIgnored (Name); }
         }
 
         public override string ToString ()

=== modified file 'src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs'
--- src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs	2009-01-28 01:29:07 +0000
+++ src/Core/Banshee.Services/Banshee.Collection.Database/DatabaseTrackInfo.cs	2009-02-07 00:04:12 +0000
@@ -398,7 +398,7 @@
         
         [DatabaseColumn(Select = false)]
         protected string TitleLowered {
-            get { return TrackTitle == null ? null : TrackTitle.ToLower (); }
+            get { return Hyena.StringUtil.LowerAndStripIgnored (TrackTitle); }
         }
 
         [DatabaseColumn(Select = false)]

=== modified file 'src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs'
--- src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs	2009-01-26 01:41:24 +0000
+++ src/Core/Banshee.Services/Banshee.Database/BansheeDbFormatMigrator.cs	2009-02-07 00:22:01 +0000
@@ -53,7 +53,7 @@
         //       this version MUST be incremented and a migration method
         //       MUST be supplied to match the new version number
         protected const int CURRENT_VERSION = 22;
-        protected const int CURRENT_METADATA_VERSION = 4;
+        protected const int CURRENT_METADATA_VERSION = 5;
         
 #region Migration Driver
         

=== modified file 'src/Core/Banshee.Services/Banshee.Query/BansheeQuery.cs'
--- src/Core/Banshee.Services/Banshee.Query/BansheeQuery.cs	2009-01-26 02:09:07 +0000
+++ src/Core/Banshee.Services/Banshee.Query/BansheeQuery.cs	2009-02-06 23:54:31 +0000
@@ -91,7 +91,7 @@
 
         public static QueryField ArtistField = new QueryField (
             "artist", "ArtistName",
-            Catalog.GetString ("Artist"), "CoreArtists.NameLowered", true,
+            Catalog.GetString ("Artist"), "CoreArtists.NameLowered", new Type [] {typeof(FuzzyStringQueryValue)}, true,
             // Translators: These are unique search aliases for "artist".  Please, no spaces. Blank ok.
             Catalog.GetString ("artist"), Catalog.GetString ("by"), Catalog.GetString ("artists"),
             "by", "artist", "artists"
@@ -99,7 +99,7 @@
 
         public static QueryField AlbumArtistField = new QueryField (
             "albumartist", "AlbumArtist",
-            Catalog.GetString ("Album Artist"), "CoreAlbums.ArtistNameLowered", true,
+            Catalog.GetString ("Album Artist"), "CoreAlbums.ArtistNameLowered", new Type [] {typeof(FuzzyStringQueryValue)}, true,
             // Translators: These are unique search aliases for "album artist".  Please, no spaces. Blank ok.
             Catalog.GetString ("albumartist"), Catalog.GetString ("compilationartist"),
             "albumartist", "compilationartist"
@@ -109,7 +109,7 @@
 
         public static QueryField AlbumField = new QueryField (
             "album", "AlbumTitle",
-            Catalog.GetString ("Album"), "CoreAlbums.TitleLowered", true,
+            Catalog.GetString ("Album"), "CoreAlbums.TitleLowered", new Type [] {typeof(FuzzyStringQueryValue)}, true,
             // Translators: These are unique search aliases for "album".  Please, no spaces. Blank ok.
             Catalog.GetString ("album"), Catalog.GetString ("on"), Catalog.GetString ("from"),
             "on", "album", "from", "albumtitle"
@@ -168,7 +168,7 @@
 
         public static QueryField TitleField = new QueryField (
             "title", "TrackTitle",
-            Catalog.GetString ("Name"), "CoreTracks.TitleLowered", true,
+            Catalog.GetString ("Name"), "CoreTracks.TitleLowered", new Type [] {typeof(FuzzyStringQueryValue)}, true,
             // Translators: These are unique search fields.  Please, no spaces. Blank ok.
             Catalog.GetString ("title"), Catalog.GetString ("titled"), Catalog.GetString ("name"), Catalog.GetString ("named"),
             "title", "titled", "name", "named"
@@ -184,28 +184,28 @@
 
         public static QueryField GenreField = new QueryField (
             "genre", "Genre",
-            Catalog.GetString ("Genre"), "CoreTracks.Genre", false,
+            Catalog.GetString ("Genre"), "CoreTracks.Genre", new Type [] {typeof(FuzzyStringQueryValue)}, false,
             // Translators: These are unique search fields.  Please, no spaces. Blank ok.
             Catalog.GetString ("genre"), "genre"
         );
 
         public static QueryField ComposerField = new QueryField (
             "composer", "Composer",
-            Catalog.GetString ("Composer"), "CoreTracks.Composer", false,
+            Catalog.GetString ("Composer"), "CoreTracks.Composer", new Type [] {typeof(FuzzyStringQueryValue)}, false,
             // Translators: These are unique search fields.  Please, no spaces. Blank ok.
             Catalog.GetString ("composer"), "composer"
         );
 
         public static QueryField ConductorField = new QueryField (
             "conductor", "Conductor",
-            Catalog.GetString ("Conductor"), "CoreTracks.Conductor", false,
+            Catalog.GetString ("Conductor"), "CoreTracks.Conductor", new Type [] {typeof(FuzzyStringQueryValue)}, false,
             // Translators: These are unique search fields.  Please, no spaces. Blank ok.
             Catalog.GetString ("conductor"), "conductor"
         );
 
         public static QueryField GroupingField = new QueryField (
             "grouping", "Grouping",
-            Catalog.GetString ("Grouping"), "CoreTracks.Grouping", false,
+            Catalog.GetString ("Grouping"), "CoreTracks.Grouping", new Type [] {typeof(FuzzyStringQueryValue)}, false,
             // Translators: These are unique search fields.  Please, no spaces. Blank ok.
             Catalog.GetString ("grouping"), "grouping"
         );
@@ -213,7 +213,7 @@
         public static QueryField CommentField = new QueryField (
             "comment", "Comment",
             // Translators: noun
-            Catalog.GetString ("Comment"), "CoreTracks.Comment", false,
+            Catalog.GetString ("Comment"), "CoreTracks.Comment", new Type [] {typeof(FuzzyStringQueryValue)}, false,
             // Translators: These are unique search fields (and nouns).  Please, no spaces. Blank ok.
             Catalog.GetString ("comment"), "comment"
         );

=== modified file 'src/Libraries/Hyena/Hyena.Query/QueryValue.cs'
--- src/Libraries/Hyena/Hyena.Query/QueryValue.cs	2008-06-23 16:56:52 +0000
+++ src/Libraries/Hyena/Hyena.Query/QueryValue.cs	2009-02-07 00:16:51 +0000
@@ -48,7 +48,7 @@
         public static QueryValue CreateFromUserQuery (string input, QueryField field)
         {
             if (field == null) {
-                QueryValue val = new StringQueryValue ();
+                QueryValue val = new FuzzyStringQueryValue ();
                 val.ParseUserQuery (input);
                 return val;
             } else {

=== modified file 'src/Libraries/Hyena/Hyena/StringUtil.cs'
--- src/Libraries/Hyena/Hyena/StringUtil.cs	2009-01-21 20:28:36 +0000
+++ src/Libraries/Hyena/Hyena/StringUtil.cs	2009-02-07 00:04:36 +0000
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections.Generic;
 using System.Text;
 using System.Globalization;
 using System.Text.RegularExpressions;
@@ -160,5 +161,47 @@
             else
                 return (int)num + 1;
         }
+        
+        // A mapping of non-Latin characters to be considered the same as
+        // a Latin equivalent.
+        private static Dictionary<char, char> ignored_special_cases = null;
+        private static void BuildSpecialCases ()
+        {
+            Dictionary<char, char> dict = new Dictionary<char, char>();
+            dict['\u00f8'] = 'o';
+            dict['\u0142'] = 'l';
+            ignored_special_cases = dict;
+        }
+        
+        //  Removes accents from Latin characters, and some kinds of punctuation.
+        public static string LowerAndStripIgnored (string val)
+        {
+            if (String.IsNullOrEmpty (val)) { return null; }
+            if (ignored_special_cases == null) { BuildSpecialCases (); }
+            
+            val = val.ToLower ();
+            StringBuilder sb = new StringBuilder ();
+            UnicodeCategory category;
+            bool has_ascii = false;
+            
+            foreach (char c in val.Normalize (NormalizationForm.FormKD))
+            {
+                category = Char.GetUnicodeCategory (c);
+                if (ignored_special_cases.ContainsKey (c))
+                {
+                    sb.Append (ignored_special_cases[c]);
+                }
+                
+                // Skip punctuation
+                else if (category == UnicodeCategory.OtherPunctuation) {}
+                else if(!(has_ascii && category == UnicodeCategory.NonSpacingMark))
+                {
+                    sb.Append (c);
+                }
+                has_ascii = (c >= 'a' && c <= 'z');
+            }
+            
+            return sb.ToString ().Normalize (NormalizationForm.FormKC);
+        }
     }
 }

=== modified file 'src/Libraries/Hyena/Makefile.am'
--- src/Libraries/Hyena/Makefile.am	2009-01-28 01:29:07 +0000
+++ src/Libraries/Hyena/Makefile.am	2009-02-06 23:55:59 +0000
@@ -59,6 +59,7 @@
 	Hyena.Query/AliasedObjectSet.cs \
 	Hyena.Query/DateQueryValue.cs \
 	Hyena.Query/FileSizeQueryValue.cs \
+	Hyena.Query/FuzzyStringQueryValue.cs \
 	Hyena.Query/IntegerKeyedObjectQueryValue.cs \
 	Hyena.Query/IntegerQueryValue.cs \
 	Hyena.Query/NullQueryValue.cs \

