Index: gedit/gedit-tab.c
===================================================================
--- gedit/gedit-tab.c	(revision 5426)
+++ gedit/gedit-tab.c	(working copy)
@@ -82,6 +82,8 @@
         
 	gint	                not_editable : 1;
 	gint                    auto_save : 1;
+
+	gint                    ask_if_externally_modified : 1;
 };
 
 G_DEFINE_TYPE(GeditTab, gedit_tab, GTK_TYPE_VBOX)
@@ -166,7 +168,6 @@
 	tab->priv->auto_save_timeout = 0;
 }
 
-
 static void
 gedit_tab_get_property (GObject    *object,
 		        guint       prop_id,
@@ -293,7 +294,6 @@
 	g_type_class_add_private (object_class, sizeof (GeditTabPrivate));
 }
 
-
 GeditTabState
 gedit_tab_get_state (GeditTab *tab)
 {
@@ -405,8 +405,6 @@
 	g_object_notify (G_OBJECT (tab), "state");		
 }
 
-
-
 static void 
 document_uri_notify_handler (GeditDocument *document,
 			     GParamSpec    *pspec,
@@ -1062,6 +1060,8 @@
 		gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
 		
 		install_auto_save_timeout_if_needed (tab);
+
+		tab->priv->ask_if_externally_modified = TRUE;
 	}
 
  end:
@@ -1381,13 +1381,110 @@
 			gedit_tab_set_state (tab, GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW);
 		else
 			gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
+
+		tab->priv->ask_if_externally_modified = TRUE;
 			
 		end_saving (tab);
 	}
+}
 
+static void 
+externally_modified_notification_message_area_response (GeditMessageArea *message_area,
+							gint              response_id,
+							GeditTab         *tab)
+{
+	GeditView *view;
+
+	set_message_area (tab, NULL);
+	view = gedit_tab_get_view (tab);
+
+	if (response_id == GTK_RESPONSE_OK)
+	{
+		_gedit_tab_revert (tab);
+	}
+	else
+	{
+		tab->priv->ask_if_externally_modified = FALSE;
+
+		/* go back to normal state */
+		gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
+	}
+
+	gtk_widget_grab_focus (GTK_WIDGET (view));
 }
 
 static void
+display_externally_modified_notification (GeditTab *tab)
+{
+	GtkWidget *message_area;
+	GeditDocument *doc;
+	gchar *uri;
+	gboolean document_modified;
+
+	doc = gedit_tab_get_document (tab);
+	g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
+
+	/* uri cannot be NULL, we're here because
+	 * the file we're editing changed on disk */
+	uri = gedit_document_get_uri (doc);
+	g_return_if_fail (uri != NULL);
+
+	document_modified = gtk_text_buffer_get_modified (GTK_TEXT_BUFFER(doc));
+	message_area = gedit_externally_modified_message_area_new (uri, document_modified);
+	g_free (uri);
+
+	tab->priv->message_area = NULL;
+	set_message_area (tab, message_area);
+	gtk_widget_show (message_area);
+
+	g_signal_connect (message_area,
+			  "response",
+			  G_CALLBACK (externally_modified_notification_message_area_response),
+			  tab);
+}
+
+static gboolean
+view_focused_in (GtkWidget     *widget,
+                 GdkEventFocus *event,
+                 GeditTab      *tab)
+{
+	GeditDocument *doc;
+
+	g_return_val_if_fail (GEDIT_IS_TAB (tab), FALSE);
+
+	/* we try to detect file changes only in the normal state */
+	if (tab->priv->state != GEDIT_TAB_STATE_NORMAL)
+	{
+		return FALSE;
+	}
+
+	/* we already asked, don't bug the user again */
+	if (!tab->priv->ask_if_externally_modified)
+	{
+		return FALSE;
+	}
+
+	doc = gedit_tab_get_document (tab);
+
+	/* If file was never saved or is remote we do not check */
+	if (!gedit_document_is_local (doc))
+	{
+		return FALSE;
+	}
+
+	if (_gedit_document_check_externally_modified (doc))
+	{
+		gedit_tab_set_state (tab, GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
+
+		display_externally_modified_notification (tab);
+
+		return FALSE;
+	}
+
+	return FALSE;
+}
+
+static void
 gedit_tab_init (GeditTab *tab)
 {
 	GtkWidget *sw;
@@ -1401,6 +1498,8 @@
 	tab->priv->not_editable = FALSE;
 
 	tab->priv->save_flags = 0;
+
+	tab->priv->ask_if_externally_modified = TRUE;
 	
 	/* Create the scrolled window */
 	sw = gtk_scrolled_window_new (NULL, NULL);
@@ -1459,11 +1558,16 @@
 			  "saved",
 			  G_CALLBACK (document_saved),
 			  tab);
-			  
-	g_signal_connect_after(tab->priv->view,
-			       "realize",
-			       G_CALLBACK (view_realized),
-			       tab);
+
+	g_signal_connect_after (tab->priv->view,
+				"focus-in-event",
+				G_CALLBACK (view_focused_in),
+				tab);
+
+	g_signal_connect_after (tab->priv->view,
+				"realize",
+				G_CALLBACK (view_realized),
+				tab);
 }
 
 GtkWidget *
@@ -1836,7 +1940,8 @@
 	gchar *uri;
 
 	g_return_if_fail (GEDIT_IS_TAB (tab));
-	g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_NORMAL);
+	g_return_if_fail ((tab->priv->state == GEDIT_TAB_STATE_NORMAL) ||
+			  (tab->priv->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION));
 
 	doc = gedit_tab_get_document (tab);
 	g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
@@ -1865,9 +1970,11 @@
 _gedit_tab_save (GeditTab *tab)
 {
 	GeditDocument *doc;
+	GeditDocumentSaveFlags save_flags;
 
 	g_return_if_fail (GEDIT_IS_TAB (tab));
 	g_return_if_fail ((tab->priv->state == GEDIT_TAB_STATE_NORMAL) ||
+			  (tab->priv->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) ||
 			  (tab->priv->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW));
 	g_return_if_fail (tab->priv->tmp_save_uri == NULL);
 	g_return_if_fail (tab->priv->tmp_encoding == NULL);
@@ -1876,6 +1983,21 @@
 	g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
 	g_return_if_fail (!gedit_document_is_untitled (doc));
 
+	if (tab->priv->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
+	{
+		/* We already told the user about the external
+		 * modification: hide the message area and set
+		 * the save flag.
+		 */
+
+		set_message_area (tab, NULL);
+		save_flags = tab->priv->save_flags | GEDIT_DOCUMENT_SAVE_IGNORE_MTIME;
+	}
+	else
+	{
+		save_flags = tab->priv->save_flags;
+	}
+
 	gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING);
 
 	/* uri used in error messages, will be freed in document_saved */
@@ -1885,7 +2007,7 @@
 	if (tab->priv->auto_save_timeout > 0)
 		remove_auto_save_timeout (tab);
 		
-	gedit_document_save (doc, tab->priv->save_flags);
+	gedit_document_save (doc, save_flags);
 }
 
 static gboolean
Index: gedit/gedit-tab.h
===================================================================
--- gedit/gedit-tab.h	(revision 5426)
+++ gedit/gedit-tab.h	(working copy)
@@ -54,6 +54,7 @@
 	GEDIT_TAB_STATE_SAVING_ERROR,
 	GEDIT_TAB_STATE_GENERIC_ERROR,
 	GEDIT_TAB_STATE_CLOSING,
+	GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION,
 	GEDIT_TAB_NUM_OF_STATES /* This is not a valid state */
 } GeditTabState;
 
Index: gedit/gedit-io-error-message-area.c
===================================================================
--- gedit/gedit-io-error-message-area.c	(revision 5426)
+++ gedit/gedit-io-error-message-area.c	(working copy)
@@ -75,11 +75,12 @@
 	return is_recoverable;
 }
 
-static GtkWidget *
-create_io_loading_error_message_area (const gchar *primary_text,
-				      const gchar *secondary_text)
+static void
+set_message_area_text_and_icon (GeditMessageArea *message_area,
+				const gchar      *icon_stock_id,
+				const gchar      *primary_text,
+				const gchar      *secondary_text)
 {
-	GtkWidget *message_area;
 	GtkWidget *hbox_content;
 	GtkWidget *image;
 	GtkWidget *vbox;
@@ -87,19 +88,15 @@
 	gchar *secondary_markup;
 	GtkWidget *primary_label;
 	GtkWidget *secondary_label;
-	
-	message_area = gedit_message_area_new_with_buttons (
-					GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-					NULL);
 
 	hbox_content = gtk_hbox_new (FALSE, 8);
 	gtk_widget_show (hbox_content);
 
-	image = gtk_image_new_from_stock ("gtk-dialog-error", GTK_ICON_SIZE_DIALOG);
+	image = gtk_image_new_from_stock (icon_stock_id, GTK_ICON_SIZE_DIALOG);
 	gtk_widget_show (image);
 	gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0);
 	gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0);
-  
+
 	vbox = gtk_vbox_new (FALSE, 6);
 	gtk_widget_show (vbox);
 	gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
@@ -114,7 +111,7 @@
 	gtk_misc_set_alignment (GTK_MISC (primary_label), 0, 0.5);
 	GTK_WIDGET_SET_FLAGS (primary_label, GTK_CAN_FOCUS);
 	gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
-  
+
   	if (secondary_text != NULL)
   	{
   		secondary_markup = g_strdup_printf ("<small>%s</small>",
@@ -135,6 +132,24 @@
 	return message_area;
 }
 
+static GtkWidget *
+create_io_loading_error_message_area (const gchar *primary_text,
+				      const gchar *secondary_text)
+{
+	GtkWidget *message_area;
+
+	message_area = gedit_message_area_new_with_buttons (
+					GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+					NULL);
+
+	set_message_area_text_and_icon (GEDIT_MESSAGE_AREA (message_area),
+					"gtk-dialog-error",
+					primary_text,
+					secondary_text);
+
+	return message_area;
+}
+
 GtkWidget *
 gedit_io_loading_error_message_area_new (const gchar  *uri,
 					 const GError *error)
@@ -1372,3 +1387,60 @@
 	return message_area;
 }
 
+GtkWidget *
+gedit_externally_modified_message_area_new (const gchar *uri,
+					    gboolean     document_modified)
+{
+       	gchar *full_formatted_uri;
+       	gchar *uri_for_display;
+       	gchar *temp_uri_for_display;
+	const gchar *primary_text;
+	const gchar *secondary_text;
+	GtkWidget *message_area;
+
+	g_return_val_if_fail (uri != NULL, NULL);
+
+	full_formatted_uri = gedit_utils_format_uri_for_display (uri);
+
+	/* Truncate the URI so it doesn't get insanely wide. Note that even
+	 * though the dialog uses wrapped text, if the URI doesn't contain
+	 * white space then the text-wrapping code is too stupid to wrap it.
+	 */
+	temp_uri_for_display = gedit_utils_str_middle_truncate (full_formatted_uri, 
+								MAX_URI_IN_DIALOG_LENGTH);								
+	g_free (full_formatted_uri);
+
+	uri_for_display = g_markup_printf_escaped ("<i>%s</i>", temp_uri_for_display);
+	g_free (temp_uri_for_display);
+
+	// FIXME: review this message, it's not clear since for the user the "modification"
+	// could be interpreted as the changes he made in the document. beside "reading" is
+	// not accurate (since last load/save)
+	primary_text = g_strdup_printf (_("The file %s changed on disk."),
+					uri_for_display);
+	g_free (uri_for_display);
+
+	if (document_modified)
+		secondary_text = _("Do you want to drop your changes and reload the file?");
+	else
+		secondary_text = _("Do you want to reload the file?");
+
+	message_area = gedit_message_area_new ();
+
+	set_message_area_text_and_icon (GEDIT_MESSAGE_AREA (message_area),
+					"gtk-dialog-warning",
+					primary_text,
+					secondary_text);
+
+	gedit_message_area_add_stock_button_with_text (GEDIT_MESSAGE_AREA (message_area),
+						       _("_Reload"),
+						       GTK_STOCK_REFRESH,
+						       GTK_RESPONSE_OK);
+
+	gedit_message_area_add_button (GEDIT_MESSAGE_AREA (message_area),
+				       GTK_STOCK_CANCEL,
+				       GTK_RESPONSE_CANCEL);
+
+	return message_area;
+}
+
Index: gedit/gedit-io-error-message-area.h
===================================================================
--- gedit/gedit-io-error-message-area.h	(revision 5426)
+++ gedit/gedit-io-error-message-area.h	(working copy)
@@ -63,6 +63,9 @@
 GtkWidget	*gedit_unrecoverable_saving_error_message_area_new	 (const gchar         *uri,
 									  const GError        *error);
 
+GtkWidget	*gedit_externally_modified_message_area_new		 (const gchar         *uri,
+									  gboolean             document_modified);
+
 G_END_DECLS
 
 #endif  /* __GEDIT_IO_ERROR_MESSAGE_AREA_H__  */
Index: gedit/gedit-window.c
===================================================================
--- gedit/gedit-window.c	(revision 5426)
+++ gedit/gedit-window.c	(working copy)
@@ -673,6 +673,7 @@
 					      "FileSave");
 	gtk_action_set_sensitive (action,
 				  (state_normal ||
+				   (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) ||
 				   (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)) &&
 				  !gedit_document_get_readonly (doc) &&
 				  !(lockdown & GEDIT_LOCKDOWN_SAVE_TO_DISK));
@@ -681,14 +682,16 @@
 					      "FileSaveAs");
 	gtk_action_set_sensitive (action,
 				  (state_normal ||
-				  (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)) &&
+				   (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) ||
+				   (state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW)) &&
 				  !(lockdown & GEDIT_LOCKDOWN_SAVE_TO_DISK));
-				  	
+
 	action = gtk_action_group_get_action (window->priv->action_group,
 					      "FileRevert");
-	gtk_action_set_sensitive (action, 
-				  !gedit_document_is_untitled (doc) &&
-				  state_normal);
+	gtk_action_set_sensitive (action,
+				  (state_normal ||
+				   (state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)) &&
+				  !gedit_document_is_untitled (doc));
 
 	action = gtk_action_group_get_action (window->priv->action_group,
 					      "FilePrintPreview");
Index: gedit/gedit-document.c
===================================================================
--- gedit/gedit-document.c	(revision 5426)
+++ gedit/gedit-document.c	(working copy)
@@ -887,6 +887,40 @@
 	return doc->priv->readonly;
 }
 
+gboolean
+_gedit_document_check_externally_modified (GeditDocument *doc)
+{
+	GnomeVFSFileInfo *info;
+	GnomeVFSResult result;
+	gint file_mtime;
+
+	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE);
+
+	if (doc->priv->uri == NULL)
+	{
+		return FALSE;
+	}
+
+	info = gnome_vfs_file_info_new ();
+
+	result = gnome_vfs_get_file_info_uri (doc->priv->vfs_uri,
+					      info,
+					      GNOME_VFS_FILE_INFO_DEFAULT|
+					      GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
+	if (result != GNOME_VFS_OK)
+	{
+		gnome_vfs_file_info_unref (info);
+
+		return FALSE;
+	}
+
+	file_mtime = info->mtime;
+
+	gnome_vfs_file_info_unref (info);
+
+	return (file_mtime > doc->priv->mtime);
+}
+
 static void
 reset_temp_loading_data (GeditDocument       *doc)
 {
@@ -1202,7 +1236,19 @@
 	return (doc->priv->uri == NULL);
 }
 
+gboolean
+gedit_document_is_local (GeditDocument *doc)
+{
+	g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE);
 
+	if (doc->priv->uri == NULL)
+	{
+		return FALSE;
+	}
+
+	return gedit_utils_uri_has_file_scheme (doc->priv->uri);
+}
+
 gboolean
 gedit_document_get_deleted (GeditDocument *doc)
 {
Index: gedit/gedit-document.h
===================================================================
--- gedit/gedit-document.h	(revision 5426)
+++ gedit/gedit-document.h	(working copy)
@@ -178,11 +178,9 @@
 gboolean	 gedit_document_is_untouched 	(GeditDocument       *doc);
 gboolean	 gedit_document_is_untitled 	(GeditDocument       *doc);
 
+gboolean	 gedit_document_is_local	(GeditDocument       *doc);
+
 gboolean	 gedit_document_get_deleted	(GeditDocument       *doc);
-/* Ancora da discutere
-gboolean	 gedit_document_get_externally_modified
-						(GeditDocument       *doc);
-*/
 
 gboolean	 gedit_document_goto_line 	(GeditDocument       *doc, 
 						 gint                 line);
@@ -234,10 +232,13 @@
  */
 gboolean	_gedit_document_is_saving_as	(GeditDocument       *doc);
 
-// CHECK: va bene un gint?
 glong		 _gedit_document_get_seconds_since_last_save_or_load 
 						(GeditDocument       *doc);
 
+/* Note: this is a sync stat: use only on local files */
+gboolean	_gedit_document_check_externally_modified
+						(GeditDocument       *doc);
+
 void		_gedit_document_search_region   (GeditDocument       *doc,
 						 const GtkTextIter   *start,
 						 const GtkTextIter   *end);
Index: bindings/python/gedit.defs
===================================================================
--- bindings/python/gedit.defs	(revision 5426)
+++ bindings/python/gedit.defs	(working copy)
@@ -303,6 +303,12 @@
   (return-type "gboolean")
 )
 
+(define-method is_local
+  (of-object "GeditDocument")
+  (c-name "gedit_document_is_local")
+  (return-type "gboolean")
+)
+
 (define-method get_deleted
   (of-object "GeditDocument")
   (c-name "gedit_document_get_deleted")
