[Codestriker-commits] CVS update: codestriker/template/en/default viewdeltas.html.tmpl
                
                Brought to you by:
                
                    sits
                    
                
            
            
        
        
        
    | 
      
      
      From: <si...@us...> - 2008-03-14 01:30:54
      
     | 
|   User: sits    
  Date: 08/03/13 18:30:53
  Modified:    lib      Codestriker.pm
               lib/Codestriker/Action DownloadTopic.pm EditComment.pm
                        SubmitNewComment.pm SubmitNewTopic.pm
                        ViewTopicComments.pm ViewTopicFile.pm
                        ViewTopicInfo.pm ViewTopicProperties.pm
               lib/Codestriker/Http DeltaRenderer.pm Response.pm
               lib/Codestriker/Model Delta.pm
               lib/Codestriker/Template/Plugin FormatWhitespace.pm
               lib/Codestriker/TopicListeners Email.pm
               template/en/default viewdeltas.html.tmpl
  Removed:     lib/Codestriker/Http Render.pm
  Log:
  Remove Render.pm from the system.
  
  
  
  Index: Codestriker.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker.pm,v
  retrieving revision 1.106
  retrieving revision 1.107
  diff -u -r1.106 -r1.107
  --- Codestriker.pm	9 Jan 2008 04:08:52 -0000	1.106
  +++ Codestriker.pm	14 Mar 2008 01:30:52 -0000	1.107
  @@ -627,5 +627,22 @@
       $stderr_fh->flush;
   }
   
  +# Replace the passed in string with the correct number of spaces, for
  +# alignment purposes.
  +sub tabadjust ($$$) {
  +    my ($tabwidth, $input, $htmlmode) = @_;
  +
  +    $_ = $input;
  +    if ($htmlmode) {
  +	1 while s/\t+/' ' x
  +	    (length($&) * $tabwidth - length($`) % $tabwidth)/eo;
  +    }
  +    else {
  +	1 while s/\t+/' ' x
  +	    (length($&) * $tabwidth - length($`) % $tabwidth)/eo;
  +    }
  +    return $_;
  +}
  +
   1;
   
  
  
  
  
  
  Index: DownloadTopic.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Action/DownloadTopic.pm,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- DownloadTopic.pm	19 May 2006 00:40:15 -0000	1.13
  +++ DownloadTopic.pm	14 Mar 2008 01:30:52 -0000	1.14
  @@ -11,7 +11,6 @@
   
   use strict;
   
  -use Codestriker::Http::Render;
   use Codestriker::Model::Topic;
   
   # If the input is valid, display the topic.
  
  
  
  
  
  Index: EditComment.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Action/EditComment.pm,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- EditComment.pm	15 Jan 2006 21:20:05 -0000	1.14
  +++ EditComment.pm	14 Mar 2008 01:30:52 -0000	1.15
  @@ -11,7 +11,6 @@
   
   use strict;
   use Codestriker::Model::Topic;
  -use Codestriker::Http::Render;
   
   # Create an appropriate form for adding a comment to a topic.
   sub process($$$) {
  @@ -83,16 +82,17 @@
   	# Retrieve the context for a comment made against a specific line.
   	my $delta = Codestriker::Model::Delta->get_delta($topicid, $fn,
   							 $line, $new);
  -	
  -    $vars->{'context'} =
  -	$query->pre(
  -	    Codestriker::Http::Render->get_context($line, 
  -						   $context, 1,
  -						   $delta->{old_linenumber},
  -						   $delta->{new_linenumber},
  -						   $delta->{text},
  -						   $new)) .
  -						       $query->p . "\n";
  +
  +	my @text = ();
  +	my $offset = $delta->retrieve_context($line, $new, $context, \@text);
  +	for (my $i = 0; $i <= $#text; $i++) {
  +	    $text[$i] = HTML::Entities::encode($text[$i]);
  +	    if ($i == $offset) {
  +		$text[$i] = "<font color=\"red\">" . $text[$i] . "</font>";
  +	    }
  +	}
  +
  +	$vars->{'context'} = $query->pre(join '\n', @text) . $query->p;
       }
   
       # Display the comments which have been made for this line number
  
  
  
  
  
  Index: SubmitNewComment.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Action/SubmitNewComment.pm,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- SubmitNewComment.pm	11 Jun 2006 08:29:11 -0000	1.12
  +++ SubmitNewComment.pm	14 Mar 2008 01:30:52 -0000	1.13
  @@ -15,7 +15,6 @@
   use Codestriker::Model::Comment;
   use Codestriker::Model::File;
   use Codestriker::Model::Topic;
  -use Codestriker::Http::Render;
   
   # If the input is valid, create the appropriate topic into the database.
   sub process($$$) {
  
  
  
  
  
  Index: SubmitNewTopic.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Action/SubmitNewTopic.pm,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -r1.32 -r1.33
  --- SubmitNewTopic.pm	22 Feb 2008 00:32:05 -0000	1.32
  +++ SubmitNewTopic.pm	14 Mar 2008 01:30:52 -0000	1.33
  @@ -15,7 +15,6 @@
   use FileHandle;
   
   use Codestriker::Model::Topic;
  -use Codestriker::Http::Render;
   use Codestriker::Repository::RepositoryFactory;
   use Codestriker::Repository::ScmBug;
   use Codestriker::FileParser::Parser;
  
  
  
  
  
  Index: ViewTopicComments.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Action/ViewTopicComments.pm,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- ViewTopicComments.pm	22 May 2006 23:19:05 -0000	1.17
  +++ ViewTopicComments.pm	14 Mar 2008 01:30:52 -0000	1.18
  @@ -12,7 +12,6 @@
   use strict;
   
   use Codestriker::Http::Template;
  -use Codestriker::Http::Render;
   use Codestriker::Model::Comment;
   use Codestriker::Model::File;
   
  @@ -121,13 +120,16 @@
                                   $comment->{fileline} , 
                                   $comment->{filenew});
   
  -                $comment->{context} = Codestriker::Http::Render->get_context(
  -                                                $comment->{fileline} , 
  -                                                $show_context, 1,
  -                                                $delta->{old_linenumber},
  -                                                $delta->{new_linenumber},
  -                                                $delta->{text}, 
  -                                                $comment->{filenew});
  +		my @text = ();
  +		my $offset = $delta->retrieve_context($comment->{fileline}, $comment->{filenew},
  +						      $show_context, \@text);
  +		for (my $i = 0; $i <= $#text; $i++) {
  +		    $text[$i] = HTML::Entities::encode($text[$i]);
  +		    if ($i == $offset) {
  +			$text[$i] = "<font color=\"red\">" . $text[$i] . "</font>";
  +		    }
  +		}
  +                $comment->{context} = $offset == -1 ? "" : (join "\n", @text);
          }
       }
   
  
  
  
  
  
  Index: ViewTopicFile.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Action/ViewTopicFile.pm,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- ViewTopicFile.pm	12 Mar 2008 08:29:14 -0000	1.13
  +++ ViewTopicFile.pm	14 Mar 2008 01:30:52 -0000	1.14
  @@ -13,7 +13,6 @@
   
   use Codestriker::Model::File;
   use Codestriker::Model::Comment;
  -use Codestriker::Http::Render;
   use Codestriker::Repository::RepositoryFactory;
   
   # If the input is valid, display the topic.
  @@ -58,10 +57,8 @@
       my @comments = $topic->read_comments();
   
       # Load the appropriate original form of this file into memory.
  -    my ($filedata_max_line_length, @filedata);
  -    if (!_read_repository_file($filename, $revision, $tabwidth,
  -			       $repository, \@filedata,
  -			       \$filedata_max_line_length)) {
  +    my @filedata;
  +    if (!$repository->retrieve($filename, $revision, \@filedata)) {
   	$http_response->error("Couldn't get repository data for $filename " .
   			      "$revision: $!");
       }
  @@ -153,27 +150,4 @@
       Codestriker::TopicListeners::Manager::topic_viewed($email, $topic);
   }
   
  -# Read the specified repository file and revision into memory.  Return true if
  -# successful, false otherwise.
  -sub _read_repository_file ($$$$$$) {
  -    my ($filename, $revision, $tabwidth, $repository, $data_array_ref,
  -	$maxline_length_ref) = @_;
  -
  -    # Read the file data.
  -    $repository->retrieve($filename, $revision, $data_array_ref);
  -
  -    # Determine the maximum line length, and replace tabs with spaces.
  -    $$maxline_length_ref = 0;
  -    for (my $i = 1; $i <= $#$data_array_ref; $i++) {
  -	$$data_array_ref[$i] =
  -	    Codestriker::Http::Render::tabadjust($tabwidth,
  -						 $$data_array_ref[$i], 0);
  -	my $line_length = length($$data_array_ref[$i]);
  -	if ($line_length > $$maxline_length_ref) {
  -	    $$maxline_length_ref = $line_length;
  -	}
  -    }
  -    return 1;
  -}
  -
   1;
  
  
  
  
  
  Index: ViewTopicInfo.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Action/ViewTopicInfo.pm,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- ViewTopicInfo.pm	1 Mar 2005 10:12:49 -0000	1.12
  +++ ViewTopicInfo.pm	14 Mar 2008 01:30:52 -0000	1.13
  @@ -14,7 +14,6 @@
   use Codestriker::Model::Topic;
   use Codestriker::Model::Comment;
   use Codestriker::Http::UrlBuilder;
  -use Codestriker::Http::Render;
   use Codestriker::Repository::RepositoryFactory;
   use HTML::Entities ();
   
  
  
  
  
  
  Index: ViewTopicProperties.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Action/ViewTopicProperties.pm,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- ViewTopicProperties.pm	23 Feb 2008 02:30:14 -0000	1.15
  +++ ViewTopicProperties.pm	14 Mar 2008 01:30:52 -0000	1.16
  @@ -14,7 +14,6 @@
   use Codestriker::Model::Topic;
   use Codestriker::Model::Comment;
   use Codestriker::Http::UrlBuilder;
  -use Codestriker::Http::Render;
   use Codestriker::Repository::RepositoryFactory;
   use HTML::Entities ();
   
  
  
  
  
  
  Index: DeltaRenderer.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Http/DeltaRenderer.pm,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DeltaRenderer.pm	10 Mar 2008 23:18:03 -0000	1.2
  +++ DeltaRenderer.pm	14 Mar 2008 01:30:52 -0000	1.3
  @@ -169,14 +169,15 @@
   
   		# Now render the line which is present on both sides.
   		my $line = {};
  +		$data = $self->_apply_line_filters($data);
   		my $data_class =
   		    $self->{mode} == $Codestriker::COLOURED_MODE ? "n" : "msn";
  -		$line->{old_data} = $self->_apply_line_filters($data);
  +		$line->{old_data} = $data;
   		$line->{old_data_line} =
   		    $self->comment_link($self->{filenumber}, $old_linenumber,
   					0, $old_linenumber);
   		$line->{old_data_class} = $data_class;
  -		$line->{new_data} = $self->_apply_line_filters($data);
  +		$line->{new_data} = $data;
   		$line->{new_data_line} =
   		    $self->comment_link($self->{filenumber}, $new_linenumber,
   					1, $new_linenumber);
  @@ -185,6 +186,17 @@
   		$old_linenumber++;
   		$new_linenumber++;
   	    }
  +
  +	    # Check if the delta corresponds to a new file.  This is true
  +	    # if there is only one delta for the whole file, there are no
  +	    # old lines, and the diff strarts at 0,1.
  +	    $delta->{new_file} = 
  +		$delta->{only_delta_in_file} &&	$old_linenumber == 0 &&
  +		$delta->{old_linenumber} == 0 && $delta->{new_linenumber} == 1;
  +	    if ($delta->{new_file}) {
  +		$delta->{new_file_class} =
  +		    $self->{mode} == $Codestriker::COLOURED_MODE ? "n" : "msn";
  +	    }
   	}
   
   	# Render any remaining diff segments.
  @@ -280,13 +292,17 @@
   	}
   	
   	my $line = {};
  -	$line->{old_data} = $self->_apply_line_filters($old_data);
  -	$line->{old_data_line} =
  -	    $self->comment_link($self->{filenumber}, $old_data_line, 0, $old_data_line);
  +	if (defined $old_data) {
  +	    $line->{old_data} = $self->_apply_line_filters($old_data);
  +	    $line->{old_data_line} =
  +		$self->comment_link($self->{filenumber}, $old_data_line, 0, $old_data_line);
  +	}
   	$line->{old_data_class} = $render_old_colour;
  -	$line->{new_data} = $self->_apply_line_filters($new_data);
  -	$line->{new_data_line} =
  -	    $self->comment_link($self->{filenumber}, $new_data_line, 1, $new_data_line);
  +	if (defined $new_data) {
  +	    $line->{new_data} = $self->_apply_line_filters($new_data);
  +	    $line->{new_data_line} =
  +		$self->comment_link($self->{filenumber}, $new_data_line, 1, $new_data_line);
  +	}
   	$line->{new_data_class} = $render_new_colour;
   	push @{$self->{lines}}, $line;
       }
  
  
  
  
  
  Index: Response.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Http/Response.pm,v
  retrieving revision 1.42
  retrieving revision 1.43
  diff -u -r1.42 -r1.43
  --- Response.pm	24 Sep 2007 21:15:08 -0000	1.42
  +++ Response.pm	14 Mar 2008 01:30:52 -0000	1.43
  @@ -403,7 +403,7 @@
   	    $data =~ s/\'/\\\'/mgo;
   	    $data =~ s/\n/<br>/mgo;
   	    $data =~ s/ \s+/' ' x (length($&)-1)/emgo;
  -	    $data = Codestriker::Http::Render::tabadjust($tabwidth, $data, 1);
  +	    $data = Codestriker::tabadjust($tabwidth, $data, 1);
   
   	    # Show each comment with the author and date in bold.
   	    $overlib_html .= "<b>Comment from $comment->{author} ";
  
  
  
  
  
  Index: Render.pm
  ===================================================================
  RCS file: Render.pm
  diff -N Render.pm
  --- Render.pm	28 Feb 2008 11:01:58 -0000	1.56
  +++ /dev/null	1 Jan 1970 00:00:00 -0000
  @@ -1,1148 +0,0 @@
  -###############################################################################
  -# Codestriker: Copyright (c) 2001, 2002 David Sitsky.  All rights reserved.
  -# si...@us...
  -#
  -# This program is free software; you can redistribute it and modify it under
  -# the terms of the GPL.
  -
  -# Collection of routines for rendering HTML output.
  -
  -package Codestriker::Http::Render;
  -
  -use strict;
  -use DBI;
  -use CGI::Carp 'fatalsToBrowser';
  -use HTML::Entities ();
  -
  -# Colour to use when displaying the line number that a comment is being made
  -# against.
  -my $CONTEXT_COLOUR = "red";
  -
  -sub _coloured_mode_finish( $ );
  -
  -# New lines within a diff block.
  -my @diff_new_lines = ();
  -
  -# The corresponding lines they refer to.
  -my @diff_new_lines_numbers = ();
  -
  -# The corresponding offsets they refer to.
  -my @diff_new_lines_offsets = ();
  -
  -# Old lines within a diff block.
  -my @diff_old_lines = ();
  -
  -# The corresponding lines they refer to.
  -my @diff_old_lines_numbers = ();
  -
  -# A record of added and removed lines for a given diff block when displaying a
  -# file in a popup window, along with their offsets.
  -my @view_file_minus = ();
  -my @view_file_plus = ();
  -my @view_file_minus_offset = ();
  -my @view_file_plus_offset = ();
  -
  -# What colour a line should appear if it has a comment against it.
  -my $COMMENT_LINE_COLOUR = "red";
  -
  -# Constructor for rendering complex data.
  -sub new ($$$$$$$\%\@$$\@\@\@\@$$) {
  -    my ($type, $query, $url_builder, $parallel, $max_digit_width, $topic,
  -	$mode, $comments, $tabwidth, $repository, $filenames_ref,
  -	$revisions_ref, $binaries_ref, $numchanges_ref, $max_line_length,
  -	$brmode, $fview) = @_;
  -
  -    # Record all of the above parameters as instance variables, which remain
  -    # constant while we render code lines.
  -    my $self = {};
  -    $self->{query} = $query;
  -    $self->{url_builder} = $url_builder;
  -    $self->{parallel} = $parallel;
  -    $self->{max_digit_width} = $max_digit_width;
  -    $self->{topic} = $topic;
  -    $self->{mode} = $mode;
  -    if (! defined $brmode) {
  -        $brmode = $Codestriker::default_topic_br_mode;
  -    }
  -    if (! defined $fview) {
  -	$fview = $Codestriker::default_file_to_view;
  -    }	
  -    $self->{brmode} = $brmode;
  -    $self->{fview}  = $fview;
  -    $self->{comments} = $comments;
  -    $self->{tabwidth} = $tabwidth;
  -    $self->{repository} = $repository;
  -    $self->{filenames_ref} = $filenames_ref;
  -    $self->{revisions_ref} = $revisions_ref;
  -    $self->{binaries_ref} = $binaries_ref;
  -    $self->{numchanges_ref} = $numchanges_ref;
  -    $self->{max_line_length} = $max_line_length;
  -    $self->{old_linenumber} = 1;
  -    $self->{new_linenumber} = 1;
  -
  -    # Get the main entry to the database
  -    my $topic_obj = Codestriker::Model::Topic->new($self->{topic});
  -    # Check for readonly
  -    $self->{topic_state} = $topic_obj->{topic_state};
  -
  -    # Build a hash from filenumber|fileline|new -> comment array, so that
  -    # when rendering, lines can be coloured appropriately.  Also build a list
  -    # of what points in the review have a comment.  Also record a mapping
  -    # from filenumber|fileline|new -> the comment number.
  -    my %comment_hash = ();
  -    my @comment_locations = ();
  -    my %comment_location_map = ();
  -    for (my $i = 0; $i <= $#$comments; $i++) {
  -	my $comment = $$comments[$i];
  -	my $key = $comment->{filenumber} . "|" . $comment->{fileline} . "|" .
  -	    $comment->{filenew};
  -	if (! exists $comment_hash{$key}) {
  -	    push @comment_locations, $key;
  -	    $comment_location_map{$key} = $#comment_locations;
  -	}
  -        push @{ $comment_hash{$key} }, $comment;
  -    }
  -    $self->{comment_hash} = \%comment_hash;
  -    $self->{comment_locations} = \@comment_locations;
  -    $self->{comment_location_map} = \%comment_location_map;
  -
  -    # Also have a number of additional private variables which need to
  -    # be initialised.
  -    $self->{diff_current_filename} = "";
  -    $self->{diff_current_revision} = "";
  -    $self->{diff_current_repmatch} = 0;
  -
  -    # Check if the repository has an associated LXR mapping, and if so, 
  -    # setup a db connection and prepare a select statement.
  -    if (defined $repository) {
  -	my $value = $Codestriker::lxr_map->{$repository->toString()};
  -	if (defined $value) {
  -	    my %lxr = %{ $value };
  -
  -	    my $passwd = $lxr{password};
  -	    if (! defined $passwd) {
  -		# For backwards compatibility.
  -		$passwd = $lxr{passwd};
  -	    }
  -	    my $dbh = DBI->connect($lxr{db}, $lxr{user}, $passwd,
  -				   {AutoCommit=>0, RaiseError=>1})
  -		|| die "Couldn't connect to database: " . DBI->errstr;
  -	    my $select_ids =
  -		$dbh->prepare_cached('SELECT count(symname) FROM symbols where symname = ?');
  -	    $self->{idhashref} = {};
  -	    $self->{idhashsth} = $select_ids;
  -	    $self->{idhashdbh} = $dbh;
  -	    $self->{lxr_base_url} = $lxr{url};
  -	}
  -	else {
  -	    # No LXR mapping defined for this repository.
  -	    $self->{idhashref} = undef;
  -	}
  -    }
  -    else {
  -	# Topic has no repository, so no LXR mapping.
  -	$self->{idhashref} = undef;
  -    }
  -
  -    bless $self, $type;
  -}
  -
  -# cleanup, disconnect from the lxr database if connected
  -sub DESTROY {
  -    my $self = shift;
  -    $self->{idhashdbh}->disconnect() if exists $self->{idhashdbh};
  -} 
  -
  -
  -# Given an identifier, wrap it within the appropriate <A HREF> tag if it
  -# is a known identifier to LXR, otherwise just return the id.  To avoid
  -# excessive crap, only consider those identifiers which are at least 4
  -# characters long.
  -sub lxr_ident($$) {
  -    my ($self, $id) = @_;
  -
  -    my $idhashref = $self->{idhashref};
  -    
  -    if (length($id) >= 4) {
  -	
  -	# Check if the id has not yet been found in lxr.
  -    	if (not exists $idhashref->{$id}) {
  -	    $idhashref->{$id} = 0;        # By default not found.
  -	    my $sth = $self->{idhashsth}; # DB statement handle.
  -
  -	    # Fetch ids from lxr and store in hash.
  -	    $sth->execute($id);
  -	    ($idhashref->{$id}) = $sth->fetchrow_array();
  -        }
  -    }
  -
  -    # Check if the id has been found in lxr.
  -    if ($$idhashref{$id}) {
  -	return "<A HREF=\"" . $self->{lxr_base_url} . "$id\" " .
  -	    "CLASS=\"fid\">$id</A>";
  -    } else {
  -	return $id;
  -    }
  -}
  -
  -# Parse the line and product the appropriate hyperlinks to LXR.
  -# Currently, this is very Java/C/C++ centric, but it will do for now.
  -sub lxr_data($$) {
  -    my ($self, $data) = @_;
  -
  -    # Don't do anything if LXR is not enabled for this topic.
  -    return $data if ! defined $self->{idhashref};
  -
  -    # If the line is just a comment, don't do any processing.  Note this code
  -    # isn't bullet-proof, but its good enough most of the time.
  -    $_ = $data;
  -    return $data if (/^(\s| )*\/\// || /^(\s| ){0,10}\*/ ||
  -		     /^(\s| ){0,10}\/\*/ ||
  -		     /^(\s| )*\*\/(\s| )*$/);
  -    
  -    # Handle package Java statements.
  -    if ($data =~ /^(package(\s| )+)([\w\.]+)(.*)$/) {
  -	return $1 . $self->lxr_ident($3) . $4;
  -    }
  -    
  -    # Handle Java import statements.
  -    if ($data =~ /^(import(\s| )+)([\w\.]+)\.(\w+)((\s| )*)(.*)$/) {
  -	return $1 . $self->lxr_ident($3) . "." . $self->lxr_ident($4) . "$5$7";
  -    }
  -    
  -    # Handle #include statements.  Note, these aren't identifier lookups, but
  -    # need to be mapped to http://localhost.localdomain/lxr/xxx/yyy/incfile.h
  -    # Should include the current filename in the object for matching purposes.
  -#    if (/^(\#\s*include\s+[\"<])(.*?)([\">].*)$/) {
  -#	return $1 . $self->lxr_ident($2) . $3;
  -#    }
  -    
  -    # Break the string into potential identifiers, and look them up to see
  -    # if they can be hyperlinked to an LXR lookup.
  -    my $idhashref = $self->{idhashref};
  -    my @data_tokens = split /([A-Za-z][\w]+)/, $data;
  -    my $newdata = "";
  -    my $in_comment = 0;
  -    my $eol_comment = 0;
  -    for (my $i = 0; $i <= $#data_tokens; $i++) {
  -	my $token = $data_tokens[$i];
  -	if ($token =~ /^[A-Za-z]/) {
  -	    if ($eol_comment || $in_comment) {
  -		# Currently in a comment, don't LXRify.
  -		$newdata .= $token;
  -	    } elsif ($token eq "nbsp" || $token eq "quot" || $token eq "amp" ||
  -		     $token eq "lt" || $token eq "gt") {
  -		# HACK - ignore potential HTML entities.  This needs to be
  -		# done in a smarter fashion later.
  -		$newdata .= $token;
  -	    } else {
  -		$newdata .= $self->lxr_ident($token);
  -	    }
  -	} else {
  -	    $newdata .= $token;
  -	    $token =~ s/(\s| )//g;
  -	    
  -	    # Check if we are entering or exiting a comment.
  -	    if ($token =~ /\/\//) {
  -		$eol_comment = 1;
  -	    } elsif ($token =~ /\*+\//) {
  -		$in_comment = 0;
  -	    } elsif ($token =~ /\/\*/) {
  -		$in_comment = 1;
  -	    }
  -	}
  -    }
  -
  -    return $newdata;
  -}
  -
  -# Render a delta.  If the filename has changed since the last delta, output the
  -# appropriate file headers. Pass in the delta object you want to render.
  -sub delta ($$$$$$$$$$) {
  -    my ($self, $delta) = @_;
  -
  -    my $filename = $delta->{filename};
  -    my $filenumber = $delta->{filenumber},
  -    my $revision = $delta->{revision};
  -    my $old_linenumber = $delta->{old_linenumber};
  -    my $new_linenumber = $delta->{new_linenumber};
  -    my $text = $delta->{text};
  -    my $description = $delta->{description};
  -    my $binary = $delta->{binary};
  -    my $repmatch = $delta->{repmatch};
  -
  -    # Don't do anything for binary files.
  -    return if $binary;
  -
  -    my $query = $self->{query};
  -
  -    if ($delta->is_delta_new_file() == 0)
  -    {
  -        # Check if the file heading needs to be output.
  -        if ($self->{diff_current_filename} ne $filename) {
  -	    $self->delta_file_header($filename, $revision, $repmatch);
  -        }
  -
  -        # Display the delta heading.
  -        $self->delta_heading($filenumber, $revision, $old_linenumber,
  -			     $new_linenumber, $description, $repmatch);
  -
  -        # Now render the actual diff text itself.
  -        $self->delta_text($filename, $filenumber, $revision, $old_linenumber,
  -			  $new_linenumber, $text, $repmatch, 1, 1);
  -    }
  -    else
  -    {
  -	# Special formatting for full file upload that is not a diff.
  -        # If it not a diff, show the entire delta (actually the file
  -        # contents) in a single column.
  -	$self->delta_file_header($filename, $revision, $repmatch);
  -
  -        print $query->Tr($query->td(" "), $query->td(" "),"\n");
  -	
  -	my @lines = split /\n/, $text;
  -        for (my $i = 0; $i <= $#lines; $i++) {
  -	    my $line = $lines[$i];
  -	    
  -	    my $rendered_left_linenumber =
  -		$self->render_linenumber($i+1, $filenumber,1,1);
  -	    
  -	    # Removed the delta text, where + is added to the start of each
  -	    # line.  Also make sure the line is suitably escaped.
  -	    $line =~ s/^\+//;
  -	    $line = HTML::Entities::encode($line);
  -
  -	    my $cell = $self->render_coloured_cell($line);
  -	    my $cell_class =
  -		$self->{mode} == $Codestriker::COLOURED_MODE ? "n" : "msn";
  -	    
  -	    print $query->Tr($query->td($rendered_left_linenumber),
  -			     $query->td({-class=>$cell_class}, $cell),
  -			     "\n");
  -    	}
  -    }
  -}
  -
  -# Output the header for a series of deltas for a specific file.
  -sub delta_file_header ($$$$) {
  -    my ($self, $filename, $revision, $repmatch) = @_;
  -
  -    my $query = $self->{query};
  -    
  -    # We need the file names for building the forward and backward
  -    # url Strings.
  -    my $filenames = $self->{filenames_ref};
  -
  -    # Close the table, update the current filename, and open a new table.
  -    print $query->end_table();
  -    $self->{diff_current_filename} = $filename;
  -    $self->{diff_current_revision} = $revision;
  -    $self->{diff_current_repmatch} = $repmatch;
  -    $self->print_coloured_table();
  -
  -    # Url to the table of contents on the same page.
  -    my $contents_url =
  -	$self->{url_builder}->view_url($self->{topic}, -1,
  -				       $self->{mode}, $self->{brmode},
  -				       $self->{fview})
  -                                       . "#contents";
  -				       
  -    # Variables to store the navigation Urls.	
  -    my $fwd_index = "";
  -    my $bwd_index = "";
  -    my $fwd_url   = "";
  -    my $bwd_url   = "";
  -    
  -    # Get the current file index.
  -    my $cfi = $self->{fview};
  -    
  -    # Store the current view mode, single view = 0, all files = -1.
  -    my $vmode = $self->{fview} == -1 ? -1 : 0; 
  -    
  -    # No better idea how I can get the array index of the current file. In the
  -    # single display mode you got it through fview - but in multi mode?
  -    if ($cfi == -1) {
  -    	for (my $i = 0; $i <= $#$filenames; $i++) {
  -	    if ($$filenames[$i] eq $filename) {
  -		$cfi = $i;
  -		last;
  -	    }
  -    	}
  -    }
  -    
  -    # Check the bounds for the previous and next browser.  A value of -1
  -    # indicates there it is not a valid link.
  -    $fwd_index = ($cfi+1 > $#$filenames ? -1 : $cfi+1);
  -    $bwd_index = ($cfi-1 < 0 ? -1 : $cfi-1);
  -	
  -    # Build the urls for next and previous file. Differ through $vmode
  -    # between all and single file review.
  -    if ($fwd_index != -1) {
  -	$fwd_url = $self->{url_builder}->view_url($self->{topic}, -1,
  -						  $self->{mode},
  -						  $self->{brmode},
  -						  $vmode == -1 ? -1 : $fwd_index)
  -                                 	          . "#$$filenames[$fwd_index]";
  -    }
  -    if ($bwd_index != -1) {
  -	$bwd_url = $self->{url_builder}->view_url($self->{topic}, -1,
  -						  $self->{mode},
  -						  $self->{brmode},
  -						  $vmode == -1 ? -1 : $bwd_index)
  -		                                  . "#$$filenames[$bwd_index]";
  -    }
  -
  -    # Generate the text for the link to add a file-level comment.
  -    my $add_file_level_comment_text =
  -	$self->render_comment_link($cfi, -1, 1, "[Add File Comment]",
  -				   "file_comment", undef);
  -
  -    if ($repmatch && $revision ne $Codestriker::ADDED_REVISION &&
  -	$revision ne $Codestriker::PATCH_REVISION) {
  -	# File matches something in the repository.  Link it to
  -	# the repository viewer if it is defined.
  -	my $cell = "";
  -	my $revision_text = "revision $revision";
  -	my $file_url = "";
  -	if (defined $self->{repository}) {
  -	    $file_url = $self->{repository}->getViewUrl($filename);
  -	}
  -
  -	if ($file_url eq "") {
  -	    # Output the header without hyperlinking the filename.
  -	    $cell = "Diff for " . 
  -		$query->a({name=>$filename},
  -			  $filename) .
  -			  $revision_text;
  -	}
  -	else {
  -	    # Link the filename to the repository system with more information
  -	    # about it.
  -	    $cell = "Diff for " .
  -		$query->a({href=>$file_url,
  -			   name=>$filename},
  -			  $filename) .
  -			  $revision_text;
  -	}
  -
  -	# Output the "back to contents" link and some browsing links
  -	# for visiting the previous and next file (<<, >>), in
  -	# addition to the "add file-level comment" link.
  -
  -	print $query->Tr($query->td({-class=>'file', -colspan=>'4'},
  -				    $query->table({-width=>'100%'},
  -				        $query->Tr(
  -					    $query->td({align=>'left'}, $cell),
  -					    $query->td({align=>'right'},
  -						       "$add_file_level_comment_text ",
  -						       ($bwd_url ne "" ? $query->a({href=>$bwd_url},"[<<]") : ""),
  -						       $query->a({href=>$contents_url},"[Top]"),
  -						       ($fwd_url ne "" ? $query->a({href=>$fwd_url},"[>>]") : ""))))));
  -    } else {
  -	# No match in repository, or a new file.
  -	print $query->Tr($query->td({-class=>'file', -colspan=>'4'},
  -				    $query->table({-width=>'100%'},
  -					$query->Tr(
  -					    $query->td({align=>'left'},
  -						       "File ",
  -						       $query->a({name=>$filename},
  -								 $filename)),
  -					    $query->td({align=>'right'},
  -						       "$add_file_level_comment_text ",
  -						       ($bwd_url ne "" ? $query->a({href=>$bwd_url},"[<<]") : ""),
  -						       $query->a({href=>$contents_url},"[Top]"),
  -						       ($fwd_url ne "" ? $query->a({href=>$fwd_url},"[>>]") : ""))))));
  -    }
  -
  -}
  -
  -# Output the delta heading, which consists of links to view the old and new
  -# file in its entirety.
  -sub delta_heading ($$$$$$$) {
  -    my ($self, $filenumber, $revision, $old_linenumber, $new_linenumber,
  -	$description, $repmatch) = @_;
  -
  -    my $query = $self->{query};
  -
  -    # Create some blank space.
  -    print $query->Tr($query->td(" "), $query->td(" "),
  -		     $query->td(" "), $query->td(" "), "\n");
  -
  -    # Output a diff block description if one is available, in a separate
  -    # row.
  -    if ($description ne "") {
  -	my $description_escaped = HTML::Entities::encode($description);
  -	print $query->Tr($query->td({-class=>'line', -colspan=>'2'},
  -				    $description_escaped),
  -			 $query->td({-class=>'line', -colspan=>'2'},
  -				    $description_escaped));
  -    }
  -
  -    if ($repmatch && $revision ne $Codestriker::ADDED_REVISION &&
  -	$revision ne $Codestriker::PATCH_REVISION) {
  -	# Display the line numbers corresponding to the patch, with links
  -	# to the entire file.
  -	my $url_builder = $self->{url_builder};
  -	my $topic = $self->{topic};
  -	my $mode = $self->{mode};
  -	my $url_old_full =
  -	    $url_builder->view_file_url($topic, $filenumber, 0,
  -					$old_linenumber, $mode, 0);
  -	my $url_old = "javascript: myOpen('$url_old_full','CVS')";
  -
  -	my $url_old_both_full =
  -	    $url_builder->view_file_url($topic, $filenumber, 0,
  -					$old_linenumber, $mode, 1);
  -	my $url_old_both =
  -	    "javascript: myOpen('$url_old_both_full','CVS')";
  -
  -	my $url_new_full =
  -	    $url_builder->view_file_url($topic, $filenumber, 1,
  -					$new_linenumber, $mode, 0);
  -	my $url_new = "javascript: myOpen('$url_new_full','CVS')";
  -
  -	my $url_new_both_full =
  -	    $url_builder->view_file_url($topic, $filenumber, 1,
  -					$new_linenumber, $mode, 1);
  -	my $url_new_both = "javascript: myOpen('$url_new_both_full','CVS')";
  -
  -	print $query->Tr($query->td({-class=>'line', -colspan=>'2'},
  -				    $query->a({href=>$url_old}, "Line " .
  -					      $old_linenumber) .
  -				    " | " .
  -				    $query->a({href=>$url_old_both},
  -					      "Parallel")),
  -			 $query->td({-class=>'line', -colspan=>'2'},
  -				    $query->a({href=>$url_new}, "Line " .
  -					      $new_linenumber) .
  -				    " | " .
  -				    $query->a({href=>$url_new_both},
  -					      "Parallel"))),
  -				    "\n";
  -    } else {
  -	# No match in the repository - or a new file.  Just display
  -	# the headings.
  -	print $query->Tr($query->td({-class=>'line', -colspan=>'2'},
  -				    "Line $old_linenumber"),
  -			 $query->td({-class=>'line', -colspan=>'2'},
  -				    "Line $new_linenumber")),
  -	"\n";
  -    }
  -}
  -
  -# Output the delta text chunk in the coloured format.
  -sub delta_text ($$$$$$$$$$$) {
  -    my ($self, $filename, $filenumber, $revision, $old_linenumber,
  -	$new_linenumber, $text, $repmatch, $new, $link) = @_;
  -
  -    my $query = $self->{query};
  -
  -    # Split up the lines, and display them, with the appropriate links.
  -    my @lines = split /\n/, $text;
  -    $self->{old_linenumber} = $old_linenumber;
  -    $self->{new_linenumber} = $new_linenumber;
  -    for (my $i = 0; $i <= $#lines; $i++) {
  -	my $line = $lines[$i];
  -	if ($self->{parallel}) {
  -	    $self->display_coloured_data($filenumber, $line, $link);
  -	} else {
  -	    $self->display_single_filedata($filenumber, $line, $new, $link);
  -	}
  -    }
  -
  -    # Render the diff blocks.
  -    if ($self->{parallel}) {
  -	$self->render_changes($filenumber, $link);
  -    } else {
  -	$self->flush_monospaced_lines($filenumber, $self->{max_line_length},
  -				      $new, $link);
  -    }
  -}
  -
  -# Display a line for coloured data.  Note special handling is done for
  -# unidiff formatted text, to output it in the "coloured-diff" style.  This
  -# requires storing state when retrieving each line.
  -sub display_coloured_data ($$$$) {
  -    my ($self, $filenumber, $data, $link) = @_;
  -
  -    my $query = $self->{query};
  -
  -    # Escape the data.
  -    $data = HTML::Entities::encode($data);
  -
  -    my $leftline = $self->{old_linenumber};
  -    my $rightline = $self->{new_linenumber};
  -    if ($data =~ /^\-(.*)$/) {
  -	# Line corresponds to something which has been removed.
  -	add_old_change($1, $leftline);
  -	$leftline++;
  -    } elsif ($data =~ /^\+(.*)$/) {
  -	# Line corresponds to something which has been removed.
  -	add_new_change($1, $rightline);
  -	$rightline++;
  -    } elsif ($data =~ /^\\/) {
  -	# A diff comment such as "No newline at end of file" - ignore it.
  -    } else {
  -	# Strip the first space off the diff for proper alignment.
  -	$data =~ s/^\s//;
  -
  -	# Render the previous diff changes visually.
  -	$self->render_changes($filenumber, $link);
  -
  -	# Render the current line for both cells.
  -	my $celldata = $self->render_coloured_cell($data);
  -
  -	# Determine the appropriate classes to render.
  -	my $cell_class =
  -	    $self->{mode} == $Codestriker::COLOURED_MODE ? "n" : "msn";
  -
  -	my $rendered_left_linenumber =
  -	    $self->render_linenumber($leftline, $filenumber, 0, $link);
  -	my $rendered_right_linenumber =
  -	    ($leftline == $rightline && !$self->{parallel}) ?
  -	    $rendered_left_linenumber :
  -	    $self->render_linenumber($rightline, $filenumber, 1, $link);
  -
  -	print $query->Tr($query->td($rendered_left_linenumber),
  -			 $query->td({-class=>$cell_class}, $celldata),
  -			 $query->td($rendered_right_linenumber),
  -			 $query->td({-class=>$cell_class}, $celldata),
  -			 "\n");
  -
  -	$leftline++;
  -	$rightline++;
  -    }
  -
  -    # Update the left and right line nymber state variables.
  -    $self->{old_linenumber} = $leftline;
  -    $self->{new_linenumber} = $rightline;
  -}
  -
  -# Render a cell for the coloured diff.
  -sub render_coloured_cell($$)
  -{
  -    my ($self, $data) = @_;
  -
  -    if (! defined $data || $data eq "") {
  -	return " ";
  -    }
  -
  -    # Replace spaces and tabs with the appropriate number of  's.
  -    $data = tabadjust($self->{tabwidth}, $data, 1);
  -    if ($self->{brmode} == $Codestriker::LINE_BREAK_ASSIST_MODE) {
  -	$data =~ s/^(\s+)/my $sp='';for(my $i=0;$i<length($1);$i++){$sp.=' '}$sp;/ge;
  -    }
  -    else {
  -    $data =~ s/\s/ /g;
  -    }
  -
  -    # Add LXR links to the output.
  -    $data = $self->lxr_data($data);
  -
  -    # Unconditionally add a   at the start for better alignment.
  -    return " $data";
  -}
  -
  -# Indicate a line of data which has been removed in the diff.
  -sub add_old_change($$) {
  -    my ($data, $linenumber) = @_;
  -    push @diff_old_lines, $data;
  -    push @diff_old_lines_numbers, $linenumber;
  -}
  -
  -# Indicate that a line of data has been added in the diff.
  -sub add_new_change($$) {
  -    my ($data, $linenumber) = @_;
  -    push @diff_new_lines, $data;
  -    push @diff_new_lines_numbers, $linenumber;
  -}
  -
  -# Render the current diff changes, if there is anything.
  -sub render_changes($$$) {
  -    my ($self, $filenumber, $link) = @_;
  -
  -    return if ($#diff_new_lines == -1 && $#diff_old_lines == -1);
  -
  -    my ($arg1, $arg2, $arg3, $arg4);
  -    my $mode = $self->{mode};
  -    if ($#diff_new_lines != -1 && $#diff_old_lines != -1) {
  -	# Lines have been added and removed.
  -	if ($mode == $Codestriker::COLOURED_MODE) {
  -	    $arg1 = "c"; $arg2 = "cb"; $arg3 = "c"; $arg4 = "cb";
  -	} else {
  -	    $arg1 = "msc"; $arg2 = "mscb"; $arg3 = "msc"; $arg4 = "mscb";
  -	}
  -    } elsif ($#diff_new_lines != -1 && $#diff_old_lines == -1) {
  -	# New lines have been added.
  -	if ($mode == $Codestriker::COLOURED_MODE) {
  -	    $arg1 = "a"; $arg2 = "ab"; $arg3 = "a"; $arg4 = "ab";
  -	} else {
  -	    $arg1 = "msa"; $arg2 = "msab"; $arg3 = "msa"; $arg4 = "msab";
  -	}
  -    } else {
  -	# Lines have been removed.
  -	if ($mode == $Codestriker::COLOURED_MODE) {
  -	    $arg1 = "r"; $arg2 = "rb"; $arg3 = "r"; $arg4 = "rb";
  -	} else {
  -	    $arg1 = "msr"; $arg2 = "msrb"; $arg3 = "msr"; $arg4 = "msrb";
  -	}
  -    }
  -    $self->render_inplace_changes($arg1, $arg2, $arg3, $arg4, $filenumber,
  -				  $link);
  -
  -    # Now that the diff changeset has been rendered, remove the state data.
  -    @diff_new_lines = ();
  -    @diff_new_lines_numbers = ();
  -    @diff_old_lines = ();
  -    @diff_old_lines_numbers = ();
  -}
  -
  -# Render the inplace changes in the current diff change set.
  -sub render_inplace_changes($$$$$$$)
  -{
  -    my ($self, $old_col, $old_notpresent_col, $new_col,
  -	$new_notpresent_col, $filenumber, $link) = @_;
  -
  -    my $old_data;
  -    my $new_data;
  -    my $old_data_line;
  -    my $new_data_line;
  -    while ($#diff_old_lines != -1 || $#diff_new_lines != -1) {
  -
  -	# Retrieve the next lines which were removed (if any).
  -	if ($#diff_old_lines != -1) {
  -	    $old_data = shift @diff_old_lines;
  -	    $old_data_line = shift @diff_old_lines_numbers;
  -	} else {
  -	    undef($old_data);
  -	    undef($old_data_line);
  -	}
  -
  -	# Retrieve the next lines which were added (if any).
  -	if ($#diff_new_lines != -1) {
  -	    $new_data = shift @diff_new_lines;
  -	    $new_data_line = shift @diff_new_lines_numbers;
  -	} else {
  -	    undef($new_data);
  -	    undef($new_data_line);
  -	}
  -
  -	my $render_old_data = $self->render_coloured_cell($old_data);
  -	my $render_new_data = $self->render_coloured_cell($new_data);
  -	
  -	# Set the colours to use appropriately depending on what is defined.
  -	my $render_old_colour = $old_col;
  -	my $render_new_colour = $new_col;
  -	if (defined $old_data && ! defined $new_data) {
  -	    $render_new_colour = $new_notpresent_col;
  -	} elsif (! defined $old_data && defined $new_data) {
  -	    $render_old_colour = $old_notpresent_col;
  -	}
  -
  -	my $parallel = $self->{parallel};
  -
  -	my $query = $self->{query};
  -	print $query->Tr($query->td($self->render_linenumber($old_data_line,
  -							     $filenumber,
  -							     0, $link)),
  -			 $query->td({-class=>"$render_old_colour"},
  -				    $render_old_data),
  -			 $query->td($self->render_linenumber($new_data_line,
  -							     $filenumber,
  -							     1, $link)),
  -			 $query->td({-class=>"$render_new_colour"},
  -				    $render_new_data), "\n");
  -    }
  -}
  -	
  -# Render a linenumber as a hyperlink.  If the line already has a
  -# comment made against it, render it with $comment_line_colour.  The
  -# title of the link should be set to the comment digest, and the
  -# status line should be set if the mouse moves over the link.
  -# Clicking on the link will take the user to the add comment page.
  -sub render_linenumber($$$$$) {
  -    my ($self, $line, $filenumber, $new, $link) = @_;
  -
  -    if (! defined $line) {
  -	return " ";
  -    }
  -
  -    # Determine what class to use when rendering the number.
  -    my ($comment_class, $no_comment_class);
  -    if ($self->{mode} == $Codestriker::COLOURED_MODE) {
  -	$comment_class = "com";
  -	$no_comment_class = "nocom";
  -    } else {
  -	$comment_class = "smscom";
  -	$no_comment_class = "smsnocom";
  -    }
  -
  -    # Check if the linenumber is outside the review.
  -    if ($link == 0) {
  -	return $line;
  -    }
  -
  -    # Now render the line.
  -    return $self->render_comment_link($filenumber, $line, $new, $line,
  -				      $comment_class, $no_comment_class);
  -}
  -
  -# Render the supplied text within a edit comment link.
  -sub render_comment_link {
  -    my ($self, $filenumber, $line, $new, $text,
  -	$comment_class, $no_comment_class) = @_;
  -
  -    # Determine the anchor and edit URL for this line number.
  -    my $anchor = "$filenumber|$line|$new";
  -    my $edit_url = "javascript:eo('$filenumber','$line','$new')";
  -
  -    # Set the anchor to this line number.
  -    my $params = {};
  -    $params->{name} = $anchor;
  -
  -    # Only set the href attribute if the comment is in open state.
  -    if (!Codestriker::topic_readonly($self->{topic_state})) {
  -	    $params->{href} = $edit_url;
  -    }
  -
  -    # If a comment exists on this line, set span and the overlib hooks onto
  -    # it.
  -    my $query = $self->{query};
  -    my %comment_hash = %{ $self->{comment_hash} };
  -    my %comment_location_map = %{ $self->{comment_location_map} };
  -    my $comment_number = undef;
  -    if (exists $comment_hash{$anchor}) {
  -	# Determine what comment number this anchor refers to.
  -	$comment_number = $comment_location_map{$anchor};
  -
  -	if (defined $comment_class) {
  -	    $text = $query->span({-id=>"c$comment_number"}, "") .
  -		$query->span({-class=>$comment_class}, $text);
  -	}
  -
  -	# Determine what the next comment in line is.
  -	my $index = -1;
  -	my @comment_locations = @{ $self->{comment_locations} };
  -	for ($index = 0; $index <= $#comment_locations; $index++) {
  -	    last if $anchor eq $comment_locations[$index];
  -	}
  -
  -	$params->{onmouseover} = "return overlib(comment_text[$index],STICKY,DRAGGABLE,ALTCUT);";
  -	$params->{onmouseout} = "return nd();";
  -    } else {
  -	if (defined $no_comment_class) {
  -	    $text = $query->span({-class=>$no_comment_class}, $text);
  -	}
  -    }
  -
  -    return $query->a($params, $text);
  -}
  -
  -# Finished hook called when finished rendering to a page.
  -sub finish($) {
  -    my ($self) = @_;
  -    if ($self->{mode} == $Codestriker::NORMAL_MODE) {
  -	$self->_normal_mode_finish();
  -    } else {
  -	$self->_coloured_mode_finish();
  -    }
  -
  -    $self->_print_legend();
  -}
  -
  -# Private functon to print the diff legend out at the bottom of the topic text page.
  -sub _print_legend($) {
  -    my ($self) = @_;
  -
  -    my $query = $self->{query};
  -    my $topic = $self->{topic};
  -    my $mode = $self->{mode};
  -
  -    print $query->start_table({-cellspacing=>'0', -cellpadding=>'0',
  -			       -border=>'0'}), "\n";
  -    print $query->Tr($query->td(" "), $query->td(" "));
  -    print $query->Tr($query->td({-colspan=>'2'}, "Legend:"));
  -    print $query->Tr($query->td({-class=>'rf'},
  -				"Removed"),
  -		     $query->td({-class=>'rb'}, " "));
  -    print $query->Tr($query->td({-class=>'cf',
  -				 -align=>"center", -colspan=>'2'},
  -				"Changed"));
  -    print $query->Tr($query->td({-class=>'ab'}, " "),
  -		     $query->td({-class=>'af'},
  -				"Added"));
  -    print $query->end_table(), "\n";
  -}
  -
  -# Render the initial start of the coloured table, with an empty row setting
  -# the widths.
  -sub print_coloured_table($)
  -{
  -    my ($self) = @_;
  -
  -    my $query = $self->{query};
  -    print $query->start_table({-width=>'100%',
  -			       -border=>'0',
  -			       -cellspacing=>'0',
  -			       -cellpadding=>'0'}), "\n";
  -    print $query->Tr($query->td({-width=>'2%'}, " "),
  -		     $query->td({-width=>'48%'}, " "),
  -		     $query->td({-width=>'2%'}, " "),
  -		     $query->td({-width=>'48%'}, " "), "\n");
  -}
  -
  -
  -# Finish topic view display hook for coloured mode.
  -sub _coloured_mode_finish ($) {
  -    my ($self) = @_;
  -
  -    if ($self->{fview} != -1) {
  -	# Show the current file header again for navigation purposes when
  -	# viewing a single file at a time.
  -	$self->delta_file_header($self->{diff_current_filename},
  -				 $self->{diff_current_revision},
  -				 $self->{diff_current_repmatch});
  -    }
  -
  -    print "</TABLE>\n";
  -
  -    # Render the "Add comment to topic" link.
  -    my $query = $self->{query};
  -    print $query->p;
  -    print $self->render_comment_link(-1, -1, 1, "Add General Comment",
  -				     "general_comment", undef);
  -    print " to topic.";
  -    print $query->p;
  -}
  -
  -# Display a line for a single file view.
  -sub display_single_filedata ($$$$$) {
  -    my ($self, $filenumber, $data, $new, $link) = @_;
  -
  -    my $leftline = $self->{old_linenumber};
  -    my $rightline = $self->{new_linenumber};
  -    my $max_line_length = $self->{max_line_length};
  -
  -    # Handling of either an old or new view.
  -    if ($data =~ /^\-(.*)$/o) {
  -	# A removed line.
  -	$self->add_minus_monospace_line($1, $leftline++);
  -    } elsif ($data =~ /^\+(.*)$/o) {
  -	# An added line.
  -	$self->add_plus_monospace_line($1, $rightline++);
  -    } else {
  -	# An unchanged line, output it and anything pending, and remove
  -	# the leading space for alignment reasons.
  -	$data =~ s/^\s//;
  -	$self->flush_monospaced_lines($filenumber, $max_line_length, $new,
  -				      $link);
  -
  -	my $linenumber = $new ? $rightline : $leftline;
  -	print $self->render_monospaced_line($filenumber, $linenumber, $new,
  -					    $data, $link,
  -					    $max_line_length, "");
  -	$leftline++;
  -	$rightline++;
  -    }
  -
  -    # Update the left and right line nymber state variables.
  -    $self->{old_linenumber} = $leftline;
  -    $self->{new_linenumber} = $rightline;
  -}
  -
  -# Print out a line of data with the specified line number suitably aligned,
  -# and with tabs replaced by spaces for proper alignment.
  -sub render_monospaced_line ($$$$$$$$) {
  -    my ($self, $filenumber, $linenumber, $new, $data, $link,
  -	$max_line_length, $class) = @_;
  -
  -    # Convert any identifier to their LXR links.
  -    $data = $self->lxr_data(HTML::Entities::encode($data));
  -
  -    my $prefix = "";
  -    my $digit_width = length($linenumber);
  -    my $max_digit_width = $self->{max_digit_width};
  -    for (my $i = 0; $i < ($max_digit_width - $digit_width); $i++) {
  -	$prefix .= " ";
  -    }
  -
  -    # Determine what class to use when rendering the number.
  -    my ($comment_class, $no_comment_class);
  -    if ($self->{parallel} == 0) {
  -	$comment_class = "mscom";
  -	$no_comment_class = "msnocom";
  -    } else {
  -	if ($self->{mode} == $Codestriker::COLOURED_MODE) {
  -	    $comment_class = "com";
  -	    $no_comment_class = "nocom";
  -	} else {
  -	    $comment_class = "smscom";
  -	    $no_comment_class = "smsnocom";
  -	}
  -    }
  -
  -    my $line_cell = "";
  -    if ($link == 0) {
  -	# A line outside of the review.  Just render the line number, as
  -	# the "name" of the linenumber should not be used.
  -	$line_cell = "$prefix$linenumber";
  -    } else {
  -	$line_cell = $prefix .
  -	    $self->render_comment_link($filenumber, $linenumber, $new,
  -				       $linenumber, $comment_class,
  -				       $no_comment_class);
  -    }
  -
  -    # Render the line data.  If the user clicks on a topic line, the
  -    # edit window is focused to the appropriate line.
  -    my $query = $self->{query};
  -
  -    # Replace the line data with spaces.
  -    my $newdata = tabadjust($self->{tabwidth}, $data, 0);
  -
  -    if ($class ne "") {
  -	# Add the appropriate number of spaces to justify the data to a length
  -	# of $max_line_length, and render it within a SPAN to get the correct
  -	# background colour.
  -	my $padding = $max_line_length - length($data);
  -	for (my $i = 0; $i < ($padding); $i++) {
  -	    $newdata .= " ";
  -	}
  -	return "$line_cell " .
  -	    $query->span({-class=>"$class"}, $newdata) . "\n";
  -    }
  -    else {
  -	return "$line_cell $newdata\n";
  -    }
  -}
  -
  -# Record a plus line.
  -sub add_plus_monospace_line ($$$) {
  -    my ($self, $linedata, $offset) = @_;
  -    push @view_file_plus, $linedata;
  -    push @view_file_plus_offset, $offset;
  -}
  -
  -# Record a minus line.
  -sub add_minus_monospace_line ($$$) {
  -    my ($self, $linedata, $offset) = @_;
  -    push @view_file_minus, $linedata;
  -    push @view_file_minus_offset, $offset;
  -}
  -
  -# Flush the current diff chunk.  Note if the original file is being rendered,
  -# the minus lines are used, otherwise the plus lines.
  -sub flush_monospaced_lines ($$$$$) {
  -    my ($self, $filenumber, $max_line_length, $new, $link) = @_;
  -
  -    my $class = "";
  -    if ($#view_file_plus != -1 && $#view_file_minus != -1) {
  -	# This is a change chunk.
  -	$class = "msc";
  -    }
  -    elsif ($#view_file_plus != -1) {
  -	# This is an add chunk.
  -	$class = "msa";
  -    }
  -    elsif ($#view_file_minus != -1) {
  -	# This is a remove chunk.
  -	$class = "msr";
  -    }
  -
  -    if ($new) {
  -	for (my $i = 0; $i <= $#view_file_plus; $i++) {
  -	    print $self->render_monospaced_line($filenumber,
  -						$view_file_plus_offset[$i],
  -						$new,
  -						$view_file_plus[$i], $link,
  -						$max_line_length, $class);
  -	}
  -    }
  -    else {
  -	for (my $i = 0; $i <= $#view_file_minus; $i++) {
  -	    print $self->render_monospaced_line($filenumber,
  -						$view_file_minus_offset[$i],
  -						$new,
  -						$view_file_minus[$i], $link,
  -						$max_line_length, $class);
  -	}
  -    }
  -    $#view_file_minus = -1;
  -    $#view_file_minus_offset = -1;
  -    $#view_file_plus = -1;
  -    $#view_file_plus_offset = -1;
  -}
  -
  -# Replace the passed in string with the correct number of spaces, for
  -# alignment purposes.
  -sub tabadjust ($$$) {
  -    my ($tabwidth, $input, $htmlmode) = @_;
  -
  -    $_ = $input;
  -    if ($htmlmode) {
  -	1 while s/\t+/' ' x
  -	    (length($&) * $tabwidth - length($`) % $tabwidth)/eo;
  -    }
  -    else {
  -	1 while s/\t+/' ' x
  -	    (length($&) * $tabwidth - length($`) % $tabwidth)/eo;
  -    }
  -    return $_;
  -}
  -
  -# Retrieve the data that forms the "context" when submitting a comment.
  -sub get_context ($$$$$$$$$) {
  -    my ($type, $targetline, $context, $html_view, $old_startline,
  -	$new_startline, $text, $new) = @_;
  -
  -    # Break the text into lines.
  -    my @document = split /\n/, $text;
  -
  -    # Calculate the location of the target line within the diff chunk.
  -    my $offset;
  -    my $old_linenumber = $old_startline;
  -    my $new_linenumber = $new_startline;
  -    for ($offset = 0; $offset <= $#document; $offset++) {
  -
  -	my $data = $document[$offset];
  -
  -	# Check if the target line as been found.
  -	if ($data =~ /^ /o) {
  -	    last if ($new && $new_linenumber == $targetline);
  -	    last if ($new == 0 && $old_linenumber == $targetline);
  -	    $old_linenumber++;
  -	    $new_linenumber++;
  -	} elsif ($data =~ /^\+/o) {
  -	    last if ($new && $new_linenumber == $targetline);
  -	    $new_linenumber++;
  -	} elsif ($data =~ /^\-/o) {
  -	    last if ($new == 0 && $old_linenumber == $targetline);
  -	    $old_linenumber++;
  -	}
  -    }
  -
  -    # Get the minimum and maximum line numbers for this context, and return
  -    # the data.  The line of interest will be rendered appropriately.
  -    my $min_line = ($offset - $context < 0 ? 0 : $offset - $context);
  -    my $max_line = $offset + $context;
  -    my $context_string = "";
  -    for (my $i = $min_line; $i <= $max_line && $i <= $#document; $i++) {
  -	my $linedata = $document[$i];
  -	if ($html_view) {
  -	    if ($i == $offset) {
  -		$context_string .=
  -		    "<font color=\"$CONTEXT_COLOUR\">" .
  -		      HTML::Entities::encode($linedata) . "</font>\n";
  -	    } else {
  -		$context_string .= HTML::Entities::encode("$linedata") ."\n";
  -	    }
  -	} else {
  -            # This is the context for emails.
  -	    $context_string .= ($i == $offset) ? "* " : "  ";
  -	    $context_string .= $linedata . "\n";
  -	}
  -    }
  -    return $context_string;
  -}
  -
  -1;
  
  
  
  
  
  Index: Delta.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Model/Delta.pm,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- Delta.pm	30 May 2006 07:18:09 -0000	1.11
  +++ Delta.pm	14 Mar 2008 01:30:53 -0000	1.12
  @@ -169,31 +169,66 @@
       return @results;
   }
   
  +# Determine the offset of $target_line within the delta text. or -1
  +# if it can't be located.
  +sub find_line_offset {
  +    my ($self, $targetline, $new) = @_;
   
  -# This function looks at the delta, and will return 1 if the delta looks like
  -# it is a delta for a completly new file. This happens when a new file is added
  -# to SCM system, or the user updated a plain old text document to be reviewed
  -# without diffs. We need this function because we want to format this case
  -# special.
  -sub is_delta_new_file
  -{
  -    my $self = shift;
  -    
  -    # All of the following must be true:
  -    # - one delta for the entire file
  -    # - delta must start at line 1 (0ld, and new)
  -    my $is_new_file = 0;
  -    if ($self->{only_delta_in_file} &&
  -	$self->{old_linenumber} == 0 &&
  -	$self->{new_linenumber} == 1) {
  -	# All of the delta text lines must start with +.
  -	my @lines = split '\n', $self->{text};
  -	if ( scalar( grep !/^\+/, @lines ) == 0) {
  -	    $is_new_file = 1;
  +    # Break the text into lines.
  +    my @document = split /\n/, $self->{text};
  +
  +    # Calculate the location of the target line within the diff chunk.
  +    my $offset;
  +    my $old_linenumber = $self->{old_linenumber};
  +    my $new_linenumber = $self->{new_linenumber};
  +    for ($offset = 0; $offset <= $#document; $offset++) {
  +
  +	my $data = $document[$offset];
  +
  +	# Check if the target line as been found.
  +	if ($data =~ /^ /o) {
  +	    last if ($new && $new_linenumber == $targetline);
  +	    last if ($new == 0 && $old_linenumber == $targetline);
  +	    $old_linenumber++;
  +	    $new_linenumber++;
  +	} elsif ($data =~ /^\+/o) {
  +	    last if ($new && $new_linenumber == $targetline);
  +	    $new_linenumber++;
  +	} elsif ($data =~ /^\-/o) {
  +	    last if ($new == 0 && $old_linenumber == $targetline);
  +	    $old_linenumber++;
   	}
       }
  -    
  -    return $is_new_file;
  +
  +    if (($new && $new_linenumber == $targetline) ||
  +	($new == 0 && $old_linenumber == $targetline)) {
  +	return $offset;
  +    } else {
  +	# No match was found.
  +	return -1;
  +    }
  +}
  +
  +# Retrieve the textual context for the delta at the specified line and
  +# context width.
  +sub retrieve_context {
  +    my ($self, $targetline, $new, $context, $text) = @_;
  +
  +    my $offset = $self->find_line_offset($targetline, $new);
  +    if ($offset == -1) {
  +	return -1;
  +    }
  +
  +    # Get the minimum and maximum line numbers for this context, and return
  +    # the data.
  +    my @document = split /\n/, $self->{text};
  +    my $min_line = ($offset - $context < 0 ? 0 : $offset - $context);
  +    my $max_line = $offset + $context;
  +    for (my $i = $min_line; $i <= $max_line && $i <= $#document; $i++) {
  +	push @{ $text }, $document[$i];
  +    }
  +
  +    return $offset - $min_line;
   }
   
   1;
  
  
  
  
  
  Index: FormatWhitespace.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/Template/Plugin/FormatWhitespace.pm,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- FormatWhitespace.pm	2 Jun 2005 11:31:01 -0000	1.1
  +++ FormatWhitespace.pm	14 Mar 2008 01:30:53 -0000	1.2
  @@ -22,7 +22,7 @@
       $text =~ s/ \s+/' ' x (length($&)-1)/emgo;
   
       # Replace tabs.
  -    $text = Codestriker::Http::Render::tabadjust($tabwidth, $text, 1);
  +    $text = Codestriker::tabadjust($tabwidth, $text, 1);
       
       return $text;
   }
  
  
  
  
  
  Index: Email.pm
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/lib/Codestriker/TopicListeners/Email.pm,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- Email.pm	9 Jan 2008 06:16:05 -0000	1.25
  +++ Email.pm	14 Mar 2008 01:30:53 -0000	1.26
  @@ -370,14 +370,18 @@
   						 $comment->{filenumber}, 
   						 $comment->{fileline}, 
   						 $comment->{filenew});
  -	$body .=
  -	     Codestriker::Http::Render->get_context($comment->{fileline}, 
  -						    $email_context, 0,
  -						    $delta->{old_linenumber},
  -						    $delta->{new_linenumber},
  -						    $delta->{text}, 
  -						    $comment->{filenew})
  -	. "\n";
  +	my @text = ();
  +	my $offset = $delta->retrieve_context($comment->{fileline}, $comment->{filenew}, 
  +					      $email_context, \@text);
  +	for (my $i = 0; $i <= $#text; $i++) {
  +	    if ($i == $offset) {
  +		$text[$i] = "* " . $text[$i];
  +	    } else {
  +		$text[$i] = "  " . $text[$i];
  +	    }
  +	}
  +	$body .= join "\n", @text;
  +	$body .= "\n\n";
   	$body .= "$EMAIL_HR";
       }
       $body .= "\n\n";
  
  
  
  
  
  Index: viewdeltas.html.tmpl
  ===================================================================
  RCS file: /cvsroot/codestriker/codestriker/template/en/default/viewdeltas.html.tmpl,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- viewdeltas.html.tmpl	13 Mar 2008 22:39:07 -0000	1.4
  +++ viewdeltas.html.tmpl	14 Mar 2008 01:30:53 -0000	1.5
  @@ -30,14 +30,15 @@
       <table width="100%" cellspacing="0" cellpadding="0" border="0">
       [% END %]
   
  -    [%# Now output the delta header. #%]
  +    [%# Now output the delta header if its not a new file. #%]
       [% SET diff_current_filename = delta.filename %]
         <tr>
   	<td colspan="4"> </td>
         </tr>
         <tr>
  -      [% IF delta.view_old_full_url != "" %]
  -      [%# Display heading with links to retrieve the entire file #%]
  +      [% IF !delta.new_file %]
  +        [% IF delta.view_old_full_url != "" %]
  +        [%# Display heading with links to retrieve the entire file #%]
           <td class="line" colspan="2">
   	  <a href="javascript: myOpen('[% delta.view_old_full_url %]', 'Codestriker')">
   	    Line [% delta.old_linenumber %]
  @@ -56,10 +57,11 @@
   	    Parallel
   	  </a>
   	</td>
  -      [% ELSE %]
  -      [%# Just display the line numbers for the delta without any links. #%]
  +        [% ELSE %]
  +        [%# Just display the line numbers for the delta without any links. #%]
           <td class="line" colspan="2">Line [% delta.old_linenumber %]</td>
           <td class="line" colspan="2">Line [% delta.new_linenumber ...
 
[truncated message content] |