Index: gtksourceview/gtksourcelanguagemanager.c
===================================================================
--- gtksourceview/gtksourcelanguagemanager.c	(revision 1990)
+++ gtksourceview/gtksourcelanguagemanager.c	(working copy)
@@ -408,3 +408,161 @@ gtk_source_language_manager_get_language
 	return g_hash_table_lookup (lm->priv->language_ids, id);
 }
 
+static GtkSourceLanguage *
+pick_lang_for_filename (GtkSourceLanguageManager *lm,
+			const gchar              *filename)
+{
+	char *filename_utf8;
+	const gchar* const * p;
+
+	filename_utf8 = g_filename_display_name (filename);
+
+	for (p = gtk_source_language_manager_get_language_ids (lm);
+	     p != NULL && *p != NULL;
+	     p++)
+	{
+		GtkSourceLanguage *lang;
+		gchar **globs, **gptr;
+
+		lang = gtk_source_language_manager_get_language (lm, *p);
+		globs = gtk_source_language_get_globs (lang);
+
+		for (gptr = globs; gptr != NULL && *gptr != NULL; gptr++)
+		{
+			if (g_pattern_match_simple (*gptr, filename_utf8))
+			{
+				g_strfreev (globs);
+				g_free (filename_utf8);
+				return lang;
+			}
+		}
+
+		g_strfreev (globs);
+	}
+
+	g_free (filename_utf8);
+	return NULL;
+}
+
+static GtkSourceLanguage *
+pick_lang_for_mime_type_pass (GtkSourceLanguageManager *lm,
+			      const char               *mime_type,
+			      gboolean                  exact_match)
+{
+	const gchar* const * id_ptr;
+
+	for (id_ptr = gtk_source_language_manager_get_language_ids (lm);
+	     id_ptr != NULL && *id_ptr != NULL;
+	     id_ptr++)
+	{
+		GtkSourceLanguage *lang;
+		gchar **mime_types, **mptr;
+
+		lang = gtk_source_language_manager_get_language (lm, *id_ptr);
+		mime_types = gtk_source_language_get_mime_types (lang);
+
+		for (mptr = mime_types; mptr != NULL && *mptr != NULL; mptr++)
+		{
+			gboolean matches;
+
+			if (exact_match)
+				matches = strcmp (mime_type, *mptr) == 0;
+			else
+				matches = g_content_type_is_a (mime_type, *mptr);
+
+			if (matches)
+			{
+				g_strfreev (mime_types);
+				return lang;
+			}
+		}
+
+		g_strfreev (mime_types);
+	}
+
+	return NULL;
+}
+
+static GtkSourceLanguage *
+pick_lang_for_mime_type (GtkSourceLanguageManager *lm,
+			 const char               *mime_type)
+{
+	GtkSourceLanguage *lang;
+	lang = pick_lang_for_mime_type_pass (lm, mime_type, TRUE);
+	if (!lang)
+		lang = pick_lang_for_mime_type_pass (lm, mime_type, FALSE);
+	return lang;
+}
+
+/**
+ * gtk_source_language_manager_get_language_for_file:
+ * @lm: a #GtkSourceLanguageManager.
+ * @filename: a filename in Glib filename encoding, or %NULL.
+ * @content_type: a content type (as in GIO API), or %NULL.
+ *
+ * Picks a #GtkSourceLanguage for given file name and content type,
+ * according to the information in lang files. It tries to pick a
+ * language for @filename first, then tries @content_type. Either
+ * @filename or @content_type may be %NULL. This function is used
+ * as follows:
+ *
+ * <informalexample><programlisting>
+ *   GtkSourceLanguage *lang;
+ *   lang = gtk_source_language_manager_get_language_for_file (filename, NULL);
+ *   gtk_source_buffer_set_language (buffer, lang);
+ * </programlisting></informalexample>
+ *
+ * or
+ *
+ * <informalexample><programlisting>
+ *   GtkSourceLanguage *lang = NULL;
+ *   gboolean result_uncertain;
+ *   char *content_type;
+ *
+ *   content_type = g_content_type_guess (filename, NULL, 0, &result_uncertain);
+ *   if (!result_uncertain)
+ *     {
+ *       g_free (content_type);
+ *       content_type = NULL;
+ *     }
+ *
+ *   lang = gtk_source_language_manager_get_language_for_file (filename, content_type);
+ *   gtk_source_buffer_set_language (buffer, lang);
+ *
+     g_free (content_type);
+ * </programlisting></informalexample>
+ *
+ * etc. Use gtk_source_language_get_mime_types() and gtk_source_language_get_globs()
+ * a better control over file -> language mapping.
+ *
+ * <note><para>
+ *  On Windows @content_type is ignored because lang files provide
+ *  mime type information, and mime types are different from content
+ *  type on Windows.
+ * </para></note>
+ *
+ * Returns: a #GtkSourceLanguage, or %NULL if there is no suitable language
+ * for given @filename and/or @content_type. Return value is owned by @lm
+ * and should not be freed.
+ */
+GtkSourceLanguage *
+gtk_source_language_manager_get_language_for_file (GtkSourceLanguageManager *lm,
+						   const gchar		    *filename,
+						   const gchar		    *content_type)
+{
+	GtkSourceLanguage *lang = NULL;
+
+	g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE_MANAGER (lm), NULL);
+
+	ensure_languages (lm);
+
+	if (filename != NULL)
+		lang = pick_lang_for_filename (lm, filename);
+
+#ifndef G_OS_WIN32
+	if (lang == NULL && content_type != NULL)
+		lang = pick_lang_for_mime_type (lm, content_type);
+#endif
+
+	return lang;
+}
Index: gtksourceview/gtksourcelanguagemanager.h
===================================================================
--- gtksourceview/gtksourcelanguagemanager.h	(revision 1990)
+++ gtksourceview/gtksourcelanguagemanager.h	(working copy)
@@ -74,6 +74,10 @@ G_CONST_RETURN gchar* G_CONST_RETURN *
 GtkSourceLanguage	 *gtk_source_language_manager_get_language		(GtkSourceLanguageManager *lm,
 										 const gchar              *id);
 
+GtkSourceLanguage	 *gtk_source_language_manager_get_language_for_file	(GtkSourceLanguageManager *lm,
+										 const gchar		  *filename,
+										 const gchar		  *content_type);
+
 
 
 G_END_DECLS
Index: tests/test-widget.c
===================================================================
--- tests/test-widget.c	(revision 1990)
+++ tests/test-widget.c	(working copy)
@@ -311,129 +311,45 @@ remove_all_marks (GtkSourceBuffer *buffe
 	gtk_source_buffer_remove_source_marks (buffer, &s, &e, NULL);
 }
 
-/* Note this is wrong for several reasons, e.g. g_pattern_match is broken
- * for glob matching. */
 static GtkSourceLanguage *
-get_language_for_filename (const gchar *filename)
+get_language_for_file (GtkTextBuffer *buffer, const gchar *filename)
 {
-	const gchar * const *languages;
-	gchar *filename_utf8;
 	GtkSourceLanguageManager *manager;
+	GtkSourceLanguage *language;
+	GtkTextIter start, end;
+	gchar *text;
+	gchar *content_type;
+	gboolean result_uncertain;
 
-	filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
-	g_return_val_if_fail (filename_utf8 != NULL, NULL);
-
-	manager = gtk_source_language_manager_get_default ();
-	languages = gtk_source_language_manager_get_language_ids (manager);
+	gtk_text_buffer_get_start_iter (buffer, &start);
+	if (gtk_text_buffer_get_char_count (buffer) < 1024)
+		gtk_text_buffer_get_end_iter (buffer, &end);
+	else
+		gtk_text_buffer_get_iter_at_offset (buffer, &end, 1024);
+	text = gtk_text_buffer_get_slice (buffer, &start, &end, TRUE);
 
-	while (*languages != NULL)
+	content_type = g_content_type_guess (filename,
+					     (guchar*) text,
+					     strlen (text),
+					     &result_uncertain);
+	if (result_uncertain)
 	{
-		GtkSourceLanguage *lang;
-		gchar **globs, **p;
-
-		lang = gtk_source_language_manager_get_language (manager,
-								 *languages);
-		g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (lang), NULL);
-		++languages;
-
-		globs = gtk_source_language_get_globs (lang);
-		if (globs == NULL)
-			continue;
-
-		for (p = globs; *p != NULL; p++)
-		{
-			if (g_pattern_match_simple (*p, filename_utf8))
-			{
-				g_strfreev (globs);
-				g_free (filename_utf8);
-
-				return lang;
-			}
-		}
-
-		g_strfreev (globs);
+		g_free (content_type);
+		content_type = NULL;
 	}
 
-	g_free (filename_utf8);
-	return NULL;
-}
-
-/* Note this is wrong, because it ignores mime parent types and subtypes.
- * It's fine to use in a simplish program like this, but is unacceptable
- * in a serious text editor. */
-static GtkSourceLanguage *
-get_language_for_mime_type (const gchar *mime)
-{
-	const gchar * const *languages;
-	GtkSourceLanguageManager *manager;
-
 	manager = gtk_source_language_manager_get_default ();
-	languages = gtk_source_language_manager_get_language_ids (manager);
-
-	while (*languages != NULL)
-	{
-		GtkSourceLanguage *lang;
-		gchar **mimetypes, **p;
-
-		lang = gtk_source_language_manager_get_language (manager,
-								 *languages);
-		g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (lang), NULL);
-		++languages;
-
-		mimetypes = gtk_source_language_get_mime_types (lang);
-
-		if (mimetypes == NULL)
-			continue;
-
-		for (p = mimetypes; *p != NULL; p++)
-		{
-			if (strcmp (*p, mime) == 0)
-			{
-				g_strfreev (mimetypes);
-				return lang;
-			}
-		}
-
-		g_strfreev (mimetypes);
-	}
-
-	return NULL;
-}
-
-static GtkSourceLanguage *
-get_language_for_file (const gchar *filename)
-{
-	GtkSourceLanguage *language = NULL;
-
-#if defined(USE_GNOME_VFS)
-	gchar *mime_type;
-	gchar *uri;
-
-	/* I hate this! */
-	if (g_path_is_absolute (filename))
-	{
-		uri = gnome_vfs_get_uri_from_local_path (filename);
-	}
-	else
-	{
-		gchar *curdir, *path;
-		curdir = g_get_current_dir ();
-		path = g_strconcat (curdir, "/", filename, NULL);
-		g_free (curdir);
-		uri = gnome_vfs_get_uri_from_local_path (path);
-		g_free (path);
-	}
-
-	if ((mime_type = gnome_vfs_get_mime_type (uri)))
-		language = get_language_for_mime_type (mime_type);
-
-	g_free (mime_type);
-	g_free (uri);
-#endif
-
-	if (!language)
-		language = get_language_for_filename (filename);
+	language = gtk_source_language_manager_get_language_for_file (manager,
+								      filename,
+								      content_type);
+
+	g_message ("Detected '%s' mime type for file %s, chose language %s",
+		   content_type ? content_type : "(null)",
+		   filename,
+		   language ? gtk_source_language_get_id (language) : "(none)");
 
+	g_free (content_type);
+	g_free (text);
 	return language;
 }
 
@@ -476,7 +392,7 @@ get_language (GtkTextBuffer *buffer, con
 	}
 
 	if (!language)
-		language = get_language_for_file (filename);
+		language = get_language_for_file (buffer, filename);
 
 	g_free (text);
 	return language;
