Index: test/functional/issues_controller_test.rb
===================================================================
--- test/functional/issues_controller_test.rb	(revision 1725)
+++ test/functional/issues_controller_test.rb	(working copy)
@@ -638,4 +638,10 @@
     j = issue.journals.find(:first, :order => 'created_on DESC')
     assert_equal 'attachment', j.details.first.property
   end
+  
+  def test_diff
+    @request.session[:user_id] = 2
+    get :diff, :id => journal_details(:description_change).id
+    assert_response :success
+  end
 end
Index: test/fixtures/journal_details.yml
===================================================================
--- test/fixtures/journal_details.yml	(revision 1725)
+++ test/fixtures/journal_details.yml	(working copy)
@@ -1,4 +1,4 @@
---- 
+--- 
 journal_details_001: 
   old_value: "1"
   property: attr
@@ -12,4 +12,12 @@
   id: 2
   value: "30"
   prop_key: done_ratio
-  journal_id: 1
+  journal_id: 1
+journal_details_003: 
+  old_value: "one two three"
+  property: attr
+  id: 3
+  value: "one one two three"
+  prop_key: description
+  journal_id: 1+  
Index: app/helpers/issues_helper.rb
===================================================================
--- app/helpers/issues_helper.rb	(revision 1725)
+++ app/helpers/issues_helper.rb	(working copy)
@@ -75,6 +75,10 @@
       when 'fixed_version_id'
         v = Version.find_by_id(detail.value) and value = v.name if detail.value
         v = Version.find_by_id(detail.old_value) and old_value = v.name if detail.old_value
+      when 'description'
+        return content_tag('strong', l(:field_description)) + ' ' + 
+          link_to(l(:text_journal_just_changed), 
+          :controller => 'issues', :action => 'diff', :id => detail.id)
       end
     when 'cf'
       custom_field = CustomField.find_by_id(detail.prop_key)
Index: app/models/issue.rb
===================================================================
--- app/models/issue.rb	(revision 1725)
+++ app/models/issue.rb	(working copy)
@@ -136,7 +136,7 @@
   def before_save  
     if @current_journal
       # attributes changes
-      (Issue.column_names - %w(id description)).each {|c|
+      (Issue.column_names - ['id']).each {|c|
         @current_journal.details << JournalDetail.new(:property => 'attr',
                                                       :prop_key => c,
                                                       :old_value => @issue_before_change.send(c),
Index: app/models/journal_detail.rb
===================================================================
--- app/models/journal_detail.rb	(revision 1725)
+++ app/models/journal_detail.rb	(working copy)
@@ -17,9 +17,4 @@
 
 class JournalDetail < ActiveRecord::Base
   belongs_to :journal
-  
-  def before_save
-    self.value = value[0..254] if value && value.is_a?(String)
-    self.old_value = old_value[0..254] if old_value && old_value.is_a?(String)
-  end
 end
Index: app/controllers/issues_controller.rb
===================================================================
--- app/controllers/issues_controller.rb	(revision 1725)
+++ app/controllers/issues_controller.rb	(working copy)
@@ -22,7 +22,10 @@
   before_filter :find_issue, :only => [:show, :edit, :reply, :destroy_attachment]
   before_filter :find_issues, :only => [:bulk_edit, :move, :destroy]
   before_filter :find_project, :only => [:new, :update_form, :preview]
-  before_filter :authorize, :except => [:index, :changes, :preview, :update_form, :context_menu]
+  
+  before_filter :authorize, :except => [:index, :changes, :preview, 
+    :update_form, :context_menu, :diff]
+  
   before_filter :find_optional_project, :only => [:index, :changes]
   accept_key_auth :index, :changes
 
@@ -360,7 +363,24 @@
     render :partial => 'common/preview'
   end
   
-private
+  #warning - relies on availability of 'diff' utility
+  def diff
+    @detail = JournalDetail.find(params[:id])
+    @issue = @detail.journal.issue
+    Tempfile.open 'issue_description_oldval', 'tmp' do |old_val_file|      
+      old_val_file.write normalize(@detail.old_value)
+      Tempfile.open 'issue_description_oldval', 'tmp' do |new_val_file|
+        new_val_file.write normalize(@detail.value)
+        old_val_file.close
+        new_val_file.close
+        #at this moment old_val_file and new_val_file files still exist - they 
+        #  will disappear after these objects finalization
+        @diff = `diff #{old_val_file.path} #{new_val_file.path} -U 3`
+      end
+    end
+  end
+
+  private
   def find_issue
     @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
     @project = @issue.project
@@ -427,4 +447,14 @@
       end
     end
   end
+
+  #Converts \n-terminated string to \r\n-teminated. At least FF on Windows 
+  #  inserts \r\n everywhere, even if original text was \n-terminated (that's 
+  #  how it is after Trac migration)
+  def normalize(long_string)
+    #we assume that if one line is \r\n\'ed, all others are too
+    return long_string if long_string["\r\n"] 
+    long_string.split("\n").join("\r\n")
+  end
+
 end
Index: lang/ru.yml
===================================================================
--- lang/ru.yml	(revision 1725)
+++ lang/ru.yml	(working copy)
@@ -471,6 +471,9 @@
 label_associated_revisions: Связанные редакции
 label_issues_by: Сортировать по %s
 label_display_per_page: 'На страницу: %s'
+label_diff: Различия
+label_show_old_value: Показать старое значение
+label_show_new_value: Показать новое значение
 
 button_login: Вход
 button_submit: Принять
@@ -521,6 +524,7 @@
 text_are_you_sure: Подтвердите
 text_journal_changed: параметр изменился с %s на %s
 text_journal_set_to: параметр изменился на %s
+text_journal_just_changed: параметр изменился
 text_journal_deleted: удалено
 text_tip_task_begin_day: дата начала задачи
 text_tip_task_end_day: дата завершения задачи
Index: lang/en.yml
===================================================================
--- lang/en.yml	(revision 1725)
+++ lang/en.yml	(working copy)
@@ -521,6 +521,9 @@
 label_planning: Planning
 label_incoming_emails: Incoming emails
 label_generate_key: Generate a key
+label_diff: Difference
+label_show_old_value: Show old value
+label_show_new_value: Show new value
 label_issue_watchers: Watchers
 
 button_login: Login
@@ -573,6 +576,7 @@
 text_workflow_edit: Select a role and a tracker to edit the workflow
 text_are_you_sure: Are you sure ?
 text_journal_changed: changed from %s to %s
+text_journal_just_changed: changed
 text_journal_set_to: set to %s
 text_journal_deleted: deleted
 text_tip_task_begin_day: task beginning this day
