aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes/diff
diff options
context:
space:
mode:
authorMeik Sievertsen <acydburn@phpbb.com>2009-06-07 18:00:37 +0000
committerMeik Sievertsen <acydburn@phpbb.com>2009-06-07 18:00:37 +0000
commit96fcbd972bb9e1bfb1398da14539dee447a20e7d (patch)
treed43db2926c6724473bc79a7265c2cf9ae7026f96 /phpBB/includes/diff
parent56122028f001381b7238a5234731954fc00fe966 (diff)
downloadforums-96fcbd972bb9e1bfb1398da14539dee447a20e7d.tar
forums-96fcbd972bb9e1bfb1398da14539dee447a20e7d.tar.gz
forums-96fcbd972bb9e1bfb1398da14539dee447a20e7d.tar.bz2
forums-96fcbd972bb9e1bfb1398da14539dee447a20e7d.tar.xz
forums-96fcbd972bb9e1bfb1398da14539dee447a20e7d.zip
moved diff
git-svn-id: file:///svn/phpbb/trunk@9556 89ea8834-ac86-4346-8a33-228a782c2dd0
Diffstat (limited to 'phpBB/includes/diff')
-rw-r--r--phpBB/includes/diff/diff.php823
-rw-r--r--phpBB/includes/diff/engine.php536
-rw-r--r--phpBB/includes/diff/renderer.php858
3 files changed, 0 insertions, 2217 deletions
diff --git a/phpBB/includes/diff/diff.php b/phpBB/includes/diff/diff.php
deleted file mode 100644
index c5249ee3c1..0000000000
--- a/phpBB/includes/diff/diff.php
+++ /dev/null
@@ -1,823 +0,0 @@
-<?php
-/**
-*
-* @package diff
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from pear.php.net, Text_Diff-1.1.0 package
-* http://pear.php.net/package/Text_Diff/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* General API for generating and formatting diffs - the differences between
-* two sequences of strings.
-*
-* Copyright 2004 Geoffrey T. Dairiki <dairiki@dairiki.org>
-* Copyright 2004-2008 The Horde Project (http://www.horde.org/)
-*
-* @package diff
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-*/
-class diff
-{
- /**
- * Array of changes.
- * @var array
- */
- var $_edits;
-
- /**
- * Computes diffs between sequences of strings.
- *
- * @param array $from_lines An array of strings. Typically these are lines from a file.
- * @param array $to_lines An array of strings.
- */
- function __construct(&$from_content, &$to_content, $preserve_cr = true)
- {
- $diff_engine = new diff_engine();
- $this->_edits = $diff_engine->diff($from_content, $to_content, $preserve_cr);
- }
-
- /**
- * Returns the array of differences.
- */
- function get_diff()
- {
- return $this->_edits;
- }
-
- /**
- * returns the number of new (added) lines in a given diff.
- *
- * @since Text_Diff 1.1.0
- *
- * @return integer The number of new lines
- */
- function count_added_lines()
- {
- $count = 0;
-
- foreach ($this->_edits as $edit)
- {
- if (is_a($edit, 'diff_op_add') || is_a($edit, 'diff_op_change'))
- {
- $count += $edit->nfinal();
- }
- }
- return $count;
- }
-
- /**
- * Returns the number of deleted (removed) lines in a given diff.
- *
- * @since Text_Diff 1.1.0
- *
- * @return integer The number of deleted lines
- */
- function count_deleted_lines()
- {
- $count = 0;
-
- foreach ($this->_edits as $edit)
- {
- if (is_a($edit, 'diff_op_delete') || is_a($edit, 'diff_op_change'))
- {
- $count += $edit->norig();
- }
- }
- return $count;
- }
-
- /**
- * Computes a reversed diff.
- *
- * Example:
- * <code>
- * $diff = new diff($lines1, $lines2);
- * $rev = $diff->reverse();
- * </code>
- *
- * @return diff A Diff object representing the inverse of the original diff.
- * Note that we purposely don't return a reference here, since
- * this essentially is a clone() method.
- */
- function reverse()
- {
- if (version_compare(zend_version(), '2', '>'))
- {
- $rev = clone($this);
- }
- else
- {
- $rev = $this;
- }
-
- $rev->_edits = array();
-
- foreach ($this->_edits as $edit)
- {
- $rev->_edits[] = $edit->reverse();
- }
-
- return $rev;
- }
-
- /**
- * Checks for an empty diff.
- *
- * @return boolean True if two sequences were identical.
- */
- function is_empty()
- {
- foreach ($this->_edits as $edit)
- {
- if (!is_a($edit, 'diff_op_copy'))
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Computes the length of the Longest Common Subsequence (LCS).
- *
- * This is mostly for diagnostic purposes.
- *
- * @return integer The length of the LCS.
- */
- function lcs()
- {
- $lcs = 0;
-
- foreach ($this->_edits as $edit)
- {
- if (is_a($edit, 'diff_op_copy'))
- {
- $lcs += sizeof($edit->orig);
- }
- }
- return $lcs;
- }
-
- /**
- * Gets the original set of lines.
- *
- * This reconstructs the $from_lines parameter passed to the constructor.
- *
- * @return array The original sequence of strings.
- */
- function get_original()
- {
- $lines = array();
-
- foreach ($this->_edits as $edit)
- {
- if ($edit->orig)
- {
- array_splice($lines, sizeof($lines), 0, $edit->orig);
- }
- }
- return $lines;
- }
-
- /**
- * Gets the final set of lines.
- *
- * This reconstructs the $to_lines parameter passed to the constructor.
- *
- * @return array The sequence of strings.
- */
- function get_final()
- {
- $lines = array();
-
- foreach ($this->_edits as $edit)
- {
- if ($edit->final)
- {
- array_splice($lines, sizeof($lines), 0, $edit->final);
- }
- }
- return $lines;
- }
-
- /**
- * Removes trailing newlines from a line of text. This is meant to be used with array_walk().
- *
- * @param string &$line The line to trim.
- * @param integer $key The index of the line in the array. Not used.
- */
- function trim_newlines(&$line, $key)
- {
- $line = str_replace(array("\n", "\r"), '', $line);
- }
-
- /**
- * Checks a diff for validity.
- *
- * This is here only for debugging purposes.
- */
- function _check($from_lines, $to_lines)
- {
- if (serialize($from_lines) != serialize($this->get_original()))
- {
- trigger_error("[diff] Reconstructed original doesn't match", E_USER_ERROR);
- }
-
- if (serialize($to_lines) != serialize($this->get_final()))
- {
- trigger_error("[diff] Reconstructed final doesn't match", E_USER_ERROR);
- }
-
- $rev = $this->reverse();
-
- if (serialize($to_lines) != serialize($rev->get_original()))
- {
- trigger_error("[diff] Reversed original doesn't match", E_USER_ERROR);
- }
-
- if (serialize($from_lines) != serialize($rev->get_final()))
- {
- trigger_error("[diff] Reversed final doesn't match", E_USER_ERROR);
- }
-
- $prevtype = null;
-
- foreach ($this->_edits as $edit)
- {
- if ($prevtype == get_class($edit))
- {
- trigger_error("[diff] Edit sequence is non-optimal", E_USER_ERROR);
- }
- $prevtype = get_class($edit);
- }
-
- return true;
- }
-}
-
-/**
-* @package diff
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-*/
-class mapped_diff extends diff
-{
- /**
- * Computes a diff between sequences of strings.
- *
- * This can be used to compute things like case-insensitve diffs, or diffs
- * which ignore changes in white-space.
- *
- * @param array $from_lines An array of strings.
- * @param array $to_lines An array of strings.
- * @param array $mapped_from_lines This array should have the same size number of elements as $from_lines.
- * The elements in $mapped_from_lines and $mapped_to_lines are what is actually
- * compared when computing the diff.
- * @param array $mapped_to_lines This array should have the same number of elements as $to_lines.
- */
- function mapped_diff(&$from_lines, &$to_lines, &$mapped_from_lines, &$mapped_to_lines)
- {
- if (sizeof($from_lines) != sizeof($mapped_from_lines) || sizeof($to_lines) != sizeof($mapped_to_lines))
- {
- return false;
- }
-
- parent::diff($mapped_from_lines, $mapped_to_lines);
-
- $xi = $yi = 0;
- for ($i = 0; $i < sizeof($this->_edits); $i++)
- {
- $orig = &$this->_edits[$i]->orig;
- if (is_array($orig))
- {
- $orig = array_slice($from_lines, $xi, sizeof($orig));
- $xi += sizeof($orig);
- }
-
- $final = &$this->_edits[$i]->final;
- if (is_array($final))
- {
- $final = array_slice($to_lines, $yi, sizeof($final));
- $yi += sizeof($final);
- }
- }
- }
-}
-
-/**
-* @package diff
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-*
-* @access private
-*/
-class diff_op
-{
- var $orig;
- var $final;
-
- function &reverse()
- {
- trigger_error('[diff] Abstract method', E_USER_ERROR);
- }
-
- function norig()
- {
- return ($this->orig) ? sizeof($this->orig) : 0;
- }
-
- function nfinal()
- {
- return ($this->final) ? sizeof($this->final) : 0;
- }
-}
-
-/**
-* @package diff
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-*
-* @access private
-*/
-class diff_op_copy extends diff_op
-{
- function diff_op_copy($orig, $final = false)
- {
- if (!is_array($final))
- {
- $final = $orig;
- }
- $this->orig = $orig;
- $this->final = $final;
- }
-
- function &reverse()
- {
- $reverse = new diff_op_copy($this->final, $this->orig);
- return $reverse;
- }
-}
-
-/**
-* @package diff
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-*
-* @access private
-*/
-class diff_op_delete extends diff_op
-{
- function diff_op_delete($lines)
- {
- $this->orig = $lines;
- $this->final = false;
- }
-
- function &reverse()
- {
- $reverse = new diff_op_add($this->orig);
- return $reverse;
- }
-}
-
-/**
-* @package diff
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-*
-* @access private
-*/
-class diff_op_add extends diff_op
-{
- function diff_op_add($lines)
- {
- $this->final = $lines;
- $this->orig = false;
- }
-
- function &reverse()
- {
- $reverse = new diff_op_delete($this->final);
- return $reverse;
- }
-}
-
-/**
-* @package diff
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-*
-* @access private
-*/
-class diff_op_change extends diff_op
-{
- function diff_op_change($orig, $final)
- {
- $this->orig = $orig;
- $this->final = $final;
- }
-
- function &reverse()
- {
- $reverse = new diff_op_change($this->final, $this->orig);
- return $reverse;
- }
-}
-
-
-/**
-* A class for computing three way diffs.
-*
-* @package diff
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-*/
-class diff3 extends diff
-{
- /**
- * Conflict counter.
- * @var integer
- */
- var $_conflicting_blocks = 0;
-
- /**
- * Computes diff between 3 sequences of strings.
- *
- * @param array $orig The original lines to use.
- * @param array $final1 The first version to compare to.
- * @param array $final2 The second version to compare to.
- */
- function diff3(&$orig, &$final1, &$final2)
- {
- $diff_engine = new diff_engine();
-
- $diff_1 = $diff_engine->diff($orig, $final1);
- $diff_2 = $diff_engine->diff($orig, $final2);
-
- unset($engine);
-
- $this->_edits = $this->_diff3($diff_1, $diff_2);
- }
-
- /**
- * Return number of conflicts
- */
- function get_num_conflicts()
- {
- $conflicts = 0;
-
- foreach ($this->_edits as $edit)
- {
- if ($edit->is_conflict())
- {
- $conflicts++;
- }
- }
-
- return $conflicts;
- }
-
- /**
- * Get conflicts content for download. This is generally a merged file, but preserving conflicts and adding explanations to it.
- * A user could then go through this file, search for the conflicts and changes the code accordingly.
- *
- * @param string $label1 the cvs file version/label from the original set of lines
- * @param string $label2 the cvs file version/label from the new set of lines
- * @param string $label_sep the explanation between label1 and label2 - more of a helper for the user
- *
- * @return mixed the merged output
- */
- function get_conflicts_content($label1 = 'CURRENT_FILE', $label2 = 'NEW_FILE', $label_sep = 'DIFF_SEP_EXPLAIN')
- {
- $label1 = (!empty(phpbb::$user->lang[$label1])) ? phpbb::$user->lang[$label1] : $label1;
- $label2 = (!empty(phpbb::$user->lang[$label2])) ? phpbb::$user->lang[$label2] : $label2;
- $label_sep = (!empty(phpbb::$user->lang[$label_sep])) ? phpbb::$user->lang[$label_sep] : $label_sep;
-
- $lines = array();
-
- foreach ($this->_edits as $edit)
- {
- if ($edit->is_conflict())
- {
- // Start conflict label
- $label_start = array('<<<<<<< ' . $label1);
- $label_mid = array('======= ' . $label_sep);
- $label_end = array('>>>>>>> ' . $label2);
-
- $lines = array_merge($lines, $label_start, $edit->final1, $label_mid, $edit->final2, $label_end);
- }
- else
- {
- $lines = array_merge($lines, $edit->merged());
- }
- }
-
- return $lines;
- }
-
- /**
- * Merge the output and use the new file code for conflicts
- */
- function merged_new_output()
- {
- $lines = array();
-
- foreach ($this->_edits as $edit)
- {
- if ($edit->is_conflict())
- {
- $lines = array_merge($lines, $edit->final2);
- }
- else
- {
- $lines = array_merge($lines, $edit->merged());
- }
- }
-
- return $lines;
- }
-
- /**
- * Merge the output and use the original file code for conflicts
- */
- function merged_orig_output()
- {
- $lines = array();
-
- foreach ($this->_edits as $edit)
- {
- if ($edit->is_conflict())
- {
- $lines = array_merge($lines, $edit->final1);
- }
- else
- {
- $lines = array_merge($lines, $edit->merged());
- }
- }
-
- return $lines;
- }
-
- /**
- * Get conflicting block(s)
- */
- function get_conflicts()
- {
- $conflicts = array();
-
- foreach ($this->_edits as $edit)
- {
- if ($edit->is_conflict())
- {
- $conflicts[] = array($edit->final1, $edit->final2);
- }
- }
-
- return $conflicts;
- }
-
- /**
- * @access private
- */
- function _diff3(&$edits1, &$edits2)
- {
- $edits = array();
- $bb = new diff3_block_builder();
-
- $e1 = current($edits1);
- $e2 = current($edits2);
-
- while ($e1 || $e2)
- {
- if ($e1 && $e2 && is_a($e1, 'diff_op_copy') && is_a($e2, 'diff_op_copy'))
- {
- // We have copy blocks from both diffs. This is the (only) time we want to emit a diff3 copy block.
- // Flush current diff3 diff block, if any.
- if ($edit = $bb->finish())
- {
- $edits[] = $edit;
- }
-
- $ncopy = min($e1->norig(), $e2->norig());
- $edits[] = new diff3_op_copy(array_slice($e1->orig, 0, $ncopy));
-
- if ($e1->norig() > $ncopy)
- {
- array_splice($e1->orig, 0, $ncopy);
- array_splice($e1->final, 0, $ncopy);
- }
- else
- {
- $e1 = next($edits1);
- }
-
- if ($e2->norig() > $ncopy)
- {
- array_splice($e2->orig, 0, $ncopy);
- array_splice($e2->final, 0, $ncopy);
- }
- else
- {
- $e2 = next($edits2);
- }
- }
- else
- {
- if ($e1 && $e2)
- {
- if ($e1->orig && $e2->orig)
- {
- $norig = min($e1->norig(), $e2->norig());
- $orig = array_splice($e1->orig, 0, $norig);
- array_splice($e2->orig, 0, $norig);
- $bb->input($orig);
- }
- else
- {
- $norig = 0;
- }
-
- if (is_a($e1, 'diff_op_copy'))
- {
- $bb->out1(array_splice($e1->final, 0, $norig));
- }
-
- if (is_a($e2, 'diff_op_copy'))
- {
- $bb->out2(array_splice($e2->final, 0, $norig));
- }
- }
-
- if ($e1 && ! $e1->orig)
- {
- $bb->out1($e1->final);
- $e1 = next($edits1);
- }
-
- if ($e2 && ! $e2->orig)
- {
- $bb->out2($e2->final);
- $e2 = next($edits2);
- }
- }
- }
-
- if ($edit = $bb->finish())
- {
- $edits[] = $edit;
- }
-
- return $edits;
- }
-}
-
-/**
-* @package diff
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-*
-* @access private
-*/
-class diff3_op
-{
- function __construct($orig = false, $final1 = false, $final2 = false)
- {
- $this->orig = $orig ? $orig : array();
- $this->final1 = $final1 ? $final1 : array();
- $this->final2 = $final2 ? $final2 : array();
- }
-
- function merged()
- {
- if (!isset($this->_merged))
- {
- if ($this->final1 === $this->final2)
- {
- $this->_merged = &$this->final1;
- }
- else if ($this->final1 === $this->orig)
- {
- $this->_merged = &$this->final2;
- }
- else if ($this->final2 === $this->orig)
- {
- $this->_merged = &$this->final1;
- }
- else
- {
- $this->_merged = false;
- }
- }
-
- return $this->_merged;
- }
-
- function is_conflict()
- {
- return ($this->merged() === false) ? true : false;
- }
-}
-
-/**
-* @package diff
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-*
-* @access private
-*/
-class diff3_op_copy extends diff3_op
-{
- function diff3_op_copy($lines = false)
- {
- $this->orig = $lines ? $lines : array();
- $this->final1 = &$this->orig;
- $this->final2 = &$this->orig;
- }
-
- function merged()
- {
- return $this->orig;
- }
-
- function is_conflict()
- {
- return false;
- }
-}
-
-/**
-* @package diff
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-*
-* @access private
-*/
-class diff3_block_builder
-{
- function __construct()
- {
- $this->_init();
- }
-
- function input($lines)
- {
- if ($lines)
- {
- $this->_append($this->orig, $lines);
- }
- }
-
- function out1($lines)
- {
- if ($lines)
- {
- $this->_append($this->final1, $lines);
- }
- }
-
- function out2($lines)
- {
- if ($lines)
- {
- $this->_append($this->final2, $lines);
- }
- }
-
- function is_empty()
- {
- return !$this->orig && !$this->final1 && !$this->final2;
- }
-
- function finish()
- {
- if ($this->is_empty())
- {
- return false;
- }
- else
- {
- $edit = new diff3_op($this->orig, $this->final1, $this->final2);
- $this->_init();
- return $edit;
- }
- }
-
- function _init()
- {
- $this->orig = $this->final1 = $this->final2 = array();
- }
-
- function _append(&$array, $lines)
- {
- array_splice($array, sizeof($array), 0, $lines);
- }
-}
-
-?> \ No newline at end of file
diff --git a/phpBB/includes/diff/engine.php b/phpBB/includes/diff/engine.php
deleted file mode 100644
index eb0dcce395..0000000000
--- a/phpBB/includes/diff/engine.php
+++ /dev/null
@@ -1,536 +0,0 @@
-<?php
-/**
-*
-* @package diff
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from pear.php.net, Text_Diff-1.1.0 package
-* http://pear.php.net/package/Text_Diff/ (native engine)
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Class used internally by Text_Diff to actually compute the diffs. This
-* class is implemented using native PHP code.
-*
-* The algorithm used here is mostly lifted from the perl module
-* Algorithm::Diff (version 1.06) by Ned Konz, which is available at:
-* http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip
-*
-* More ideas are taken from: http://www.ics.uci.edu/~eppstein/161/960229.html
-*
-* Some ideas (and a bit of code) are taken from analyze.c, of GNU
-* diffutils-2.7, which can be found at:
-* ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz
-*
-* Some ideas (subdivision by NCHUNKS > 2, and some optimizations) are from
-* Geoffrey T. Dairiki <dairiki@dairiki.org>. The original PHP version of this
-* code was written by him, and is used/adapted with his permission.
-*
-* Copyright 2004-2008 The Horde Project (http://www.horde.org/)
-*
-* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
-* @package diff
-*
-* @access private
-*/
-class diff_engine
-{
- function diff(&$from_lines, &$to_lines, $preserve_cr = true)
- {
- // Remove empty lines...
- // If preserve_cr is true, we basically only change \r\n and bare \r to \n to get the same carriage returns for both files
- // If it is false, we try to only use \n once per line and ommit all empty lines to be able to get a proper data diff
-
- if (is_array($from_lines))
- {
- $from_lines = implode("\n", $from_lines);
- }
-
- if (is_array($to_lines))
- {
- $to_lines = implode("\n", $to_lines);
- }
-
- if ($preserve_cr)
- {
- $from_lines = explode("\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $from_lines)));
- $to_lines = explode("\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $to_lines)));
- }
- else
- {
- $from_lines = explode("\n", preg_replace('#[\n\r]+#', "\n", $from_lines));
- $to_lines = explode("\n", preg_replace('#[\n\r]+#', "\n", $to_lines));
- }
-
- $n_from = sizeof($from_lines);
- $n_to = sizeof($to_lines);
-
- $this->xchanged = $this->ychanged = $this->xv = $this->yv = $this->xind = $this->yind = array();
- unset($this->seq, $this->in_seq, $this->lcs);
-
- // Skip leading common lines.
- for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++)
- {
- if ($from_lines[$skip] !== $to_lines[$skip])
- {
- break;
- }
- $this->xchanged[$skip] = $this->ychanged[$skip] = false;
- }
-
- // Skip trailing common lines.
- $xi = $n_from;
- $yi = $n_to;
-
- for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++)
- {
- if ($from_lines[$xi] !== $to_lines[$yi])
- {
- break;
- }
- $this->xchanged[$xi] = $this->ychanged[$yi] = false;
- }
-
- // Ignore lines which do not exist in both files.
- for ($xi = $skip; $xi < $n_from - $endskip; $xi++)
- {
- $xhash[$from_lines[$xi]] = 1;
- }
-
- for ($yi = $skip; $yi < $n_to - $endskip; $yi++)
- {
- $line = $to_lines[$yi];
-
- if (($this->ychanged[$yi] = empty($xhash[$line])))
- {
- continue;
- }
- $yhash[$line] = 1;
- $this->yv[] = $line;
- $this->yind[] = $yi;
- }
-
- for ($xi = $skip; $xi < $n_from - $endskip; $xi++)
- {
- $line = $from_lines[$xi];
-
- if (($this->xchanged[$xi] = empty($yhash[$line])))
- {
- continue;
- }
- $this->xv[] = $line;
- $this->xind[] = $xi;
- }
-
- // Find the LCS.
- $this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv));
-
- // Merge edits when possible.
- $this->_shift_boundaries($from_lines, $this->xchanged, $this->ychanged);
- $this->_shift_boundaries($to_lines, $this->ychanged, $this->xchanged);
-
- // Compute the edit operations.
- $edits = array();
- $xi = $yi = 0;
-
- while ($xi < $n_from || $yi < $n_to)
- {
- // Skip matching "snake".
- $copy = array();
-
- while ($xi < $n_from && $yi < $n_to && !$this->xchanged[$xi] && !$this->ychanged[$yi])
- {
- $copy[] = $from_lines[$xi++];
- $yi++;
- }
-
- if ($copy)
- {
- $edits[] = new diff_op_copy($copy);
- }
-
- // Find deletes & adds.
- $delete = array();
- while ($xi < $n_from && $this->xchanged[$xi])
- {
- $delete[] = $from_lines[$xi++];
- }
-
- $add = array();
- while ($yi < $n_to && $this->ychanged[$yi])
- {
- $add[] = $to_lines[$yi++];
- }
-
- if ($delete && $add)
- {
- $edits[] = new diff_op_change($delete, $add);
- }
- else if ($delete)
- {
- $edits[] = new diff_op_delete($delete);
- }
- else if ($add)
- {
- $edits[] = new diff_op_add($add);
- }
- }
-
- return $edits;
- }
-
- /**
- * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF,
- * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized segments.
- *
- * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of
- * NCHUNKS+1 (X, Y) indexes giving the diving points between sub
- * sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1),
- * the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) ==
- * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM).
- *
- * This function assumes that the first lines of the specified portions of
- * the two files do not match, and likewise that the last lines do not
- * match. The caller must trim matching lines from the beginning and end
- * of the portions it is going to specify.
- */
- function _diag($xoff, $xlim, $yoff, $ylim, $nchunks)
- {
- $flip = false;
-
- if ($xlim - $xoff > $ylim - $yoff)
- {
- // Things seems faster (I'm not sure I understand why) when the shortest sequence is in X.
- $flip = true;
- list($xoff, $xlim, $yoff, $ylim) = array($yoff, $ylim, $xoff, $xlim);
- }
-
- if ($flip)
- {
- for ($i = $ylim - 1; $i >= $yoff; $i--)
- {
- $ymatches[$this->xv[$i]][] = $i;
- }
- }
- else
- {
- for ($i = $ylim - 1; $i >= $yoff; $i--)
- {
- $ymatches[$this->yv[$i]][] = $i;
- }
- }
-
- $this->lcs = 0;
- $this->seq[0]= $yoff - 1;
- $this->in_seq = array();
- $ymids[0] = array();
-
- $numer = $xlim - $xoff + $nchunks - 1;
- $x = $xoff;
-
- for ($chunk = 0; $chunk < $nchunks; $chunk++)
- {
- if ($chunk > 0)
- {
- for ($i = 0; $i <= $this->lcs; $i++)
- {
- $ymids[$i][$chunk - 1] = $this->seq[$i];
- }
- }
-
- $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks);
-
- for (; $x < $x1; $x++)
- {
- $line = $flip ? $this->yv[$x] : $this->xv[$x];
- if (empty($ymatches[$line]))
- {
- continue;
- }
- $matches = $ymatches[$line];
-
- reset($matches);
- while (list(, $y) = each($matches))
- {
- if (empty($this->in_seq[$y]))
- {
- $k = $this->_lcs_pos($y);
- $ymids[$k] = $ymids[$k - 1];
- break;
- }
- }
-
- // no reset() here
- while (list(, $y) = each($matches))
- {
- if ($y > $this->seq[$k - 1])
- {
- // Optimization: this is a common case: next match is just replacing previous match.
- $this->in_seq[$this->seq[$k]] = false;
- $this->seq[$k] = $y;
- $this->in_seq[$y] = 1;
- }
- else if (empty($this->in_seq[$y]))
- {
- $k = $this->_lcs_pos($y);
- $ymids[$k] = $ymids[$k - 1];
- }
- }
- }
- }
-
- $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff);
- $ymid = $ymids[$this->lcs];
-
- for ($n = 0; $n < $nchunks - 1; $n++)
- {
- $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks);
- $y1 = $ymid[$n] + 1;
- $seps[] = $flip ? array($y1, $x1) : array($x1, $y1);
- }
- $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim);
-
- return array($this->lcs, $seps);
- }
-
- function _lcs_pos($ypos)
- {
- $end = $this->lcs;
-
- if ($end == 0 || $ypos > $this->seq[$end])
- {
- $this->seq[++$this->lcs] = $ypos;
- $this->in_seq[$ypos] = 1;
- return $this->lcs;
- }
-
- $beg = 1;
- while ($beg < $end)
- {
- $mid = (int)(($beg + $end) / 2);
- if ($ypos > $this->seq[$mid])
- {
- $beg = $mid + 1;
- }
- else
- {
- $end = $mid;
- }
- }
-
- $this->in_seq[$this->seq[$end]] = false;
- $this->seq[$end] = $ypos;
- $this->in_seq[$ypos] = 1;
-
- return $end;
- }
-
- /**
- * Finds LCS of two sequences.
- *
- * The results are recorded in the vectors $this->{x,y}changed[], by
- * storing a 1 in the element for each line that is an insertion or
- * deletion (ie. is not in the LCS).
- *
- * The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1.
- *
- * Note that XLIM, YLIM are exclusive bounds. All line numbers are
- * origin-0 and discarded lines are not counted.
- */
- function _compareseq($xoff, $xlim, $yoff, $ylim)
- {
- // Slide down the bottom initial diagonal.
- while ($xoff < $xlim && $yoff < $ylim && $this->xv[$xoff] == $this->yv[$yoff])
- {
- ++$xoff;
- ++$yoff;
- }
-
- // Slide up the top initial diagonal.
- while ($xlim > $xoff && $ylim > $yoff && $this->xv[$xlim - 1] == $this->yv[$ylim - 1])
- {
- --$xlim;
- --$ylim;
- }
-
- if ($xoff == $xlim || $yoff == $ylim)
- {
- $lcs = 0;
- }
- else
- {
- // This is ad hoc but seems to work well.
- // $nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5);
- // $nchunks = max(2,min(8,(int)$nchunks));
- $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1;
- list($lcs, $seps) = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks);
- }
-
- if ($lcs == 0)
- {
- // X and Y sequences have no common subsequence: mark all changed.
- while ($yoff < $ylim)
- {
- $this->ychanged[$this->yind[$yoff++]] = 1;
- }
-
- while ($xoff < $xlim)
- {
- $this->xchanged[$this->xind[$xoff++]] = 1;
- }
- }
- else
- {
- // Use the partitions to split this problem into subproblems.
- reset($seps);
- $pt1 = $seps[0];
-
- while ($pt2 = next($seps))
- {
- $this->_compareseq($pt1[0], $pt2[0], $pt1[1], $pt2[1]);
- $pt1 = $pt2;
- }
- }
- }
-
- /**
- * Adjusts inserts/deletes of identical lines to join changes as much as possible.
- *
- * We do something when a run of changed lines include a line at one end
- * and has an excluded, identical line at the other. We are free to
- * choose which identical line is included. 'compareseq' usually chooses
- * the one at the beginning, but usually it is cleaner to consider the
- * following identical line to be the "change".
- *
- * This is extracted verbatim from analyze.c (GNU diffutils-2.7).
- */
- function _shift_boundaries($lines, &$changed, $other_changed)
- {
- $i = 0;
- $j = 0;
-
- $len = sizeof($lines);
- $other_len = sizeof($other_changed);
-
- while (1)
- {
- // Scan forward to find the beginning of another run of
- // changes. Also keep track of the corresponding point in the other file.
- //
- // Throughout this code, $i and $j are adjusted together so that
- // the first $i elements of $changed and the first $j elements of
- // $other_changed both contain the same number of zeros (unchanged lines).
- //
- // Furthermore, $j is always kept so that $j == $other_len or $other_changed[$j] == false.
- while ($j < $other_len && $other_changed[$j])
- {
- $j++;
- }
-
- while ($i < $len && ! $changed[$i])
- {
- $i++;
- $j++;
-
- while ($j < $other_len && $other_changed[$j])
- {
- $j++;
- }
- }
-
- if ($i == $len)
- {
- break;
- }
-
- $start = $i;
-
- // Find the end of this run of changes.
- while (++$i < $len && $changed[$i])
- {
- continue;
- }
-
- do
- {
- // Record the length of this run of changes, so that we can later determine whether the run has grown.
- $runlength = $i - $start;
-
- // Move the changed region back, so long as the previous unchanged line matches the last changed one.
- // This merges with previous changed regions.
- while ($start > 0 && $lines[$start - 1] == $lines[$i - 1])
- {
- $changed[--$start] = 1;
- $changed[--$i] = false;
-
- while ($start > 0 && $changed[$start - 1])
- {
- $start--;
- }
-
- while ($other_changed[--$j])
- {
- continue;
- }
- }
-
- // Set CORRESPONDING to the end of the changed run, at the last point where it corresponds to a changed run in the
- // other file. CORRESPONDING == LEN means no such point has been found.
- $corresponding = $j < $other_len ? $i : $len;
-
- // Move the changed region forward, so long as the first changed line matches the following unchanged one.
- // This merges with following changed regions.
- // Do this second, so that if there are no merges, the changed region is moved forward as far as possible.
- while ($i < $len && $lines[$start] == $lines[$i])
- {
- $changed[$start++] = false;
- $changed[$i++] = 1;
-
- while ($i < $len && $changed[$i])
- {
- $i++;
- }
-
- $j++;
- if ($j < $other_len && $other_changed[$j])
- {
- $corresponding = $i;
- while ($j < $other_len && $other_changed[$j])
- {
- $j++;
- }
- }
- }
- }
- while ($runlength != $i - $start);
-
- // If possible, move the fully-merged run of changes back to a corresponding run in the other file.
- while ($corresponding < $i)
- {
- $changed[--$start] = 1;
- $changed[--$i] = 0;
-
- while ($other_changed[--$j])
- {
- continue;
- }
- }
- }
- }
-}
-
-?> \ No newline at end of file
diff --git a/phpBB/includes/diff/renderer.php b/phpBB/includes/diff/renderer.php
deleted file mode 100644
index 2d3ab88a26..0000000000
--- a/phpBB/includes/diff/renderer.php
+++ /dev/null
@@ -1,858 +0,0 @@
-<?php
-/**
-*
-* @package diff
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from pear.php.net, Text_Diff-1.1.0 package
-* http://pear.php.net/package/Text_Diff/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* A class to render Diffs in different formats.
-*
-* This class renders the diff in classic diff format. It is intended that
-* this class be customized via inheritance, to obtain fancier outputs.
-*
-* Copyright 2004-2008 The Horde Project (http://www.horde.org/)
-*
-* @package diff
-*/
-class diff_renderer
-{
- /**
- * Number of leading context "lines" to preserve.
- *
- * This should be left at zero for this class, but subclasses may want to
- * set this to other values.
- */
- var $_leading_context_lines = 0;
-
- /**
- * Number of trailing context "lines" to preserve.
- *
- * This should be left at zero for this class, but subclasses may want to
- * set this to other values.
- */
- var $_trailing_context_lines = 0;
-
- /**
- * Constructor.
- */
- function __construct($params = array())
- {
- foreach ($params as $param => $value)
- {
- $v = '_' . $param;
- if (isset($this->$v))
- {
- $this->$v = $value;
- }
- }
- }
-
- /**
- * Get any renderer parameters.
- *
- * @return array All parameters of this renderer object.
- */
- function get_params()
- {
- $params = array();
- foreach (get_object_vars($this) as $k => $v)
- {
- if ($k[0] == '_')
- {
- $params[substr($k, 1)] = $v;
- }
- }
-
- return $params;
- }
-
- /**
- * Renders a diff.
- *
- * @param diff &$diff A diff object.
- *
- * @return string The formatted output.
- */
- function render(&$diff)
- {
- $xi = $yi = 1;
- $block = false;
- $context = array();
-
- // Create a new diff object if it is a 3-way diff
- if (is_a($diff, 'diff3'))
- {
- $diff3 = &$diff;
-
- $diff_1 = $diff3->get_original();
- $diff_2 = $diff3->merged_output();
-
- unset($diff3);
-
- $diff = new diff($diff_1, $diff_2);
- }
-
- $nlead = $this->_leading_context_lines;
- $ntrail = $this->_trailing_context_lines;
-
- $output = $this->_start_diff();
- $diffs = $diff->get_diff();
-
- foreach ($diffs as $i => $edit)
- {
- // If these are unchanged (copied) lines, and we want to keep leading or trailing context lines, extract them from the copy block.
- if (is_a($edit, 'diff_op_copy'))
- {
- // Do we have any diff blocks yet?
- if (is_array($block))
- {
- // How many lines to keep as context from the copy block.
- $keep = ($i == sizeof($diffs) - 1) ? $ntrail : $nlead + $ntrail;
- if (sizeof($edit->orig) <= $keep)
- {
- // We have less lines in the block than we want for context => keep the whole block.
- $block[] = $edit;
- }
- else
- {
- if ($ntrail)
- {
- // Create a new block with as many lines as we need for the trailing context.
- $context = array_slice($edit->orig, 0, $ntrail);
- $block[] = new diff_op_copy($context);
- }
-
- $output .= $this->_block($x0, $ntrail + $xi - $x0, $y0, $ntrail + $yi - $y0, $block);
- $block = false;
- }
- }
- // Keep the copy block as the context for the next block.
- $context = $edit->orig;
- }
- else
- {
- // Don't we have any diff blocks yet?
- if (!is_array($block))
- {
- // Extract context lines from the preceding copy block.
- $context = array_slice($context, sizeof($context) - $nlead);
- $x0 = $xi - sizeof($context);
- $y0 = $yi - sizeof($context);
- $block = array();
-
- if ($context)
- {
- $block[] = new diff_op_copy($context);
- }
- }
- $block[] = $edit;
- }
-
- $xi += ($edit->orig) ? sizeof($edit->orig) : 0;
- $yi += ($edit->final) ? sizeof($edit->final) : 0;
- }
-
- if (is_array($block))
- {
- $output .= $this->_block($x0, $xi - $x0, $y0, $yi - $y0, $block);
- }
-
- return $output . $this->_end_diff();
- }
-
- function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
- {
- $output = $this->_start_block($this->_block_header($xbeg, $xlen, $ybeg, $ylen));
-
- foreach ($edits as $edit)
- {
- switch (get_class($edit))
- {
- case 'diff_op_copy':
- $output .= $this->_context($edit->orig);
- break;
-
- case 'diff_op_add':
- $output .= $this->_added($edit->final);
- break;
-
- case 'diff_op_delete':
- $output .= $this->_deleted($edit->orig);
- break;
-
- case 'diff_op_change':
- $output .= $this->_changed($edit->orig, $edit->final);
- break;
- }
- }
-
- return $output . $this->_end_block();
- }
-
- function _start_diff()
- {
- return '';
- }
-
- function _end_diff()
- {
- return '';
- }
-
- function _block_header($xbeg, $xlen, $ybeg, $ylen)
- {
- if ($xlen > 1)
- {
- $xbeg .= ',' . ($xbeg + $xlen - 1);
- }
-
- if ($ylen > 1)
- {
- $ybeg .= ',' . ($ybeg + $ylen - 1);
- }
-
- // this matches the GNU Diff behaviour
- if ($xlen && !$ylen)
- {
- $ybeg--;
- }
- else if (!$xlen)
- {
- $xbeg--;
- }
-
- return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
- }
-
- function _start_block($header)
- {
- return $header . "\n";
- }
-
- function _end_block()
- {
- return '';
- }
-
- function _lines($lines, $prefix = ' ')
- {
- return $prefix . implode("\n$prefix", $lines) . "\n";
- }
-
- function _context($lines)
- {
- return $this->_lines($lines, ' ');
- }
-
- function _added($lines)
- {
- return $this->_lines($lines, '> ');
- }
-
- function _deleted($lines)
- {
- return $this->_lines($lines, '< ');
- }
-
- function _changed($orig, $final)
- {
- return $this->_deleted($orig) . "---\n" . $this->_added($final);
- }
-
- /**
- * Our function to get the diff
- */
- function get_diff_content($diff)
- {
- return $this->render($diff);
- }
-}
-
-/**
-* Renders a unified diff
-* @package diff
-*/
-class diff_renderer_unified extends diff_renderer
-{
- var $_leading_context_lines = 4;
- var $_trailing_context_lines = 4;
-
- /**
- * Our function to get the diff
- */
- function get_diff_content($diff)
- {
- return nl2br($this->render($diff));
- }
-
- function _block_header($xbeg, $xlen, $ybeg, $ylen)
- {
- if ($xlen != 1)
- {
- $xbeg .= ',' . $xlen;
- }
-
- if ($ylen != 1)
- {
- $ybeg .= ',' . $ylen;
- }
- return '<div class="diff"><big class="info">@@ -' . $xbeg . ' +' . $ybeg . ' @@</big></div>';
- }
-
- function _context($lines)
- {
- return '<pre class="diff context">' . htmlspecialchars($this->_lines($lines, ' ')) . '<br /></pre>';
- }
-
- function _added($lines)
- {
- return '<pre class="diff added">' . htmlspecialchars($this->_lines($lines, '+')) . '<br /></pre>';
- }
-
- function _deleted($lines)
- {
- return '<pre class="diff removed">' . htmlspecialchars($this->_lines($lines, '-')) . '<br /></pre>';
- }
-
- function _changed($orig, $final)
- {
- return $this->_deleted($orig) . $this->_added($final);
- }
-
- function _start_diff()
- {
- $start = '<div class="file">';
-
- return $start;
- }
-
- function _end_diff()
- {
- return '</div>';
- }
-
- function _end_block()
- {
- return '';
- }
-}
-
-/**
-* "Inline" diff renderer.
-*
-* This class renders diffs in the Wiki-style "inline" format.
-*
-* @author Ciprian Popovici
-* @package diff
-*/
-class diff_renderer_inline extends diff_renderer
-{
- var $_leading_context_lines = 10000;
- var $_trailing_context_lines = 10000;
-
- // Prefix and suffix for inserted text
- var $_ins_prefix = '<span class="ins">';
- var $_ins_suffix = '</span>';
-
- // Prefix and suffix for deleted text
- var $_del_prefix = '<span class="del">';
- var $_del_suffix = '</span>';
-
- var $_block_head = '';
-
- // What are we currently splitting on? Used to recurse to show word-level
- var $_split_level = 'lines';
-
- /**
- * Our function to get the diff
- */
- function get_diff_content($diff)
- {
- return '<pre>' . nl2br($this->render($diff)) . '<br /></pre>';
- }
-
- function _start_diff()
- {
- return '';
- }
-
- function _end_diff()
- {
- return '';
- }
-
- function _block_header($xbeg, $xlen, $ybeg, $ylen)
- {
- return $this->_block_head;
- }
-
- function _start_block($header)
- {
- return $header;
- }
-
- function _lines($lines, $prefix = ' ', $encode = true)
- {
- if ($encode)
- {
- array_walk($lines, array(&$this, '_encode'));
- }
-
- if ($this->_split_level == 'words')
- {
- return implode('', $lines);
- }
- else
- {
- return implode("\n", $lines) . "\n";
- }
- }
-
- function _added($lines)
- {
- array_walk($lines, array(&$this, '_encode'));
- $lines[0] = $this->_ins_prefix . $lines[0];
- $lines[sizeof($lines) - 1] .= $this->_ins_suffix;
- return $this->_lines($lines, ' ', false);
- }
-
- function _deleted($lines, $words = false)
- {
- array_walk($lines, array(&$this, '_encode'));
- $lines[0] = $this->_del_prefix . $lines[0];
- $lines[sizeof($lines) - 1] .= $this->_del_suffix;
- return $this->_lines($lines, ' ', false);
- }
-
- function _changed($orig, $final)
- {
- // If we've already split on words, don't try to do so again - just display.
- if ($this->_split_level == 'words')
- {
- $prefix = '';
- while ($orig[0] !== false && $final[0] !== false && substr($orig[0], 0, 1) == ' ' && substr($final[0], 0, 1) == ' ')
- {
- $prefix .= substr($orig[0], 0, 1);
- $orig[0] = substr($orig[0], 1);
- $final[0] = substr($final[0], 1);
- }
-
- return $prefix . $this->_deleted($orig) . $this->_added($final);
- }
-
- $text1 = implode("\n", $orig);
- $text2 = implode("\n", $final);
-
- // Non-printing newline marker.
- $nl = "\0";
-
- // We want to split on word boundaries, but we need to preserve whitespace as well.
- // Therefore we split on words, but include all blocks of whitespace in the wordlist.
- $splitted_text_1 = $this->_split_on_words($text1, $nl);
- $splitted_text_2 = $this->_split_on_words($text2, $nl);
-
- $diff = new diff($splitted_text_1, $splitted_text_2);
- unset($splitted_text_1, $splitted_text_2);
-
- // Get the diff in inline format.
- $renderer = new diff_renderer_inline(array_merge($this->get_params(), array('split_level' => 'words')));
-
- // Run the diff and get the output.
- return str_replace($nl, "\n", $renderer->render($diff)) . "\n";
- }
-
- function _split_on_words($string, $newline_escape = "\n")
- {
- // Ignore \0; otherwise the while loop will never finish.
- $string = str_replace("\0", '', $string);
-
- $words = array();
- $length = strlen($string);
- $pos = 0;
-
- $tab_there = true;
- while ($pos < $length)
- {
- // Check for tabs... do not include them
- if ($tab_there && substr($string, $pos, 1) === "\t")
- {
- $words[] = "\t";
- $pos++;
-
- continue;
- }
- else
- {
- $tab_there = false;
- }
-
- // Eat a word with any preceding whitespace.
- $spaces = strspn(substr($string, $pos), " \n");
- $nextpos = strcspn(substr($string, $pos + $spaces), " \n");
- $words[] = str_replace("\n", $newline_escape, substr($string, $pos, $spaces + $nextpos));
- $pos += $spaces + $nextpos;
- }
-
- return $words;
- }
-
- function _encode(&$string)
- {
- $string = htmlspecialchars($string);
- }
-}
-
-/**
-* "raw" diff renderer.
-* This class could be used to output a raw unified patch file
-*
-* @package diff
-*/
-class diff_renderer_raw extends diff_renderer
-{
- var $_leading_context_lines = 4;
- var $_trailing_context_lines = 4;
-
- /**
- * Our function to get the diff
- */
- function get_diff_content($diff)
- {
- return '<textarea style="height: 290px;" class="full">' . htmlspecialchars($this->render($diff)) . '</textarea>';
- }
-
- function _block_header($xbeg, $xlen, $ybeg, $ylen)
- {
- if ($xlen != 1)
- {
- $xbeg .= ',' . $xlen;
- }
-
- if ($ylen != 1)
- {
- $ybeg .= ',' . $ylen;
- }
- return '@@ -' . $xbeg . ' +' . $ybeg . ' @@';
- }
-
- function _context($lines)
- {
- return $this->_lines($lines, ' ');
- }
-
- function _added($lines)
- {
- return $this->_lines($lines, '+');
- }
-
- function _deleted($lines)
- {
- return $this->_lines($lines, '-');
- }
-
- function _changed($orig, $final)
- {
- return $this->_deleted($orig) . $this->_added($final);
- }
-}
-
-/**
-* "chora (Horde)" diff renderer - similar style.
-* This renderer class is a modified human_readable function from the Horde Framework.
-*
-* @package diff
-*/
-class diff_renderer_side_by_side extends diff_renderer
-{
- var $_leading_context_lines = 3;
- var $_trailing_context_lines = 3;
-
- var $lines = array();
-
- // Hold the left and right columns of lines for change blocks.
- var $cols;
- var $state;
-
- var $data = false;
-
- /**
- * Our function to get the diff
- */
- function get_diff_content($diff)
- {
- $output = '';
- $output .= '<table cellspacing="0" class="hrdiff">
-<caption>
- <span class="unmodified">&nbsp;</span> ' . phpbb::$user->lang['LINE_UNMODIFIED'] . '
- <span class="added">&nbsp;</span> ' . phpbb::$user->lang['LINE_ADDED'] . '
- <span class="modified">&nbsp;</span> ' . phpbb::$user->lang['LINE_MODIFIED'] . '
- <span class="removed">&nbsp;</span> ' . phpbb::$user->lang['LINE_REMOVED'] . '
-</caption>
-<tbody>
-';
-
- $this->render($diff);
-
- // Is the diff empty?
- if (!sizeof($this->lines))
- {
- $output .= '<tr><th colspan="2">' . phpbb::$user->lang['NO_VISIBLE_CHANGES'] . '</th></tr>';
- }
- else
- {
- // Iterate through every header block of changes
- foreach ($this->lines as $header)
- {
- $output .= '<tr><th>' . phpbb::$user->lang['LINE'] . ' ' . $header['oldline'] . '</th><th>' . phpbb::$user->lang['LINE'] . ' ' . $header['newline'] . '</th></tr>';
-
- // Each header block consists of a number of changes (add, remove, change).
- $current_context = '';
-
- foreach ($header['contents'] as $change)
- {
- if (!empty($current_context) && $change['type'] != 'empty')
- {
- $line = $current_context;
- $current_context = '';
-
- $output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td>
- <td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td></tr>';
- }
-
- switch ($change['type'])
- {
- case 'add':
- $line = '';
-
- foreach ($change['lines'] as $_line)
- {
- $line .= htmlspecialchars($_line) . '<br />';
- }
-
- $output .= '<tr><td class="added_empty">&nbsp;</td><td class="added"><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td></tr>';
- break;
-
- case 'remove':
- $line = '';
-
- foreach ($change['lines'] as $_line)
- {
- $line .= htmlspecialchars($_line) . '<br />';
- }
-
- $output .= '<tr><td class="removed"><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td><td class="removed_empty">&nbsp;</td></tr>';
- break;
-
- case 'empty':
- $current_context .= htmlspecialchars($change['line']) . '<br />';
- break;
-
- case 'change':
- // Pop the old/new stacks one by one, until both are empty.
- $oldsize = sizeof($change['old']);
- $newsize = sizeof($change['new']);
- $left = $right = '';
-
- for ($row = 0, $row_max = max($oldsize, $newsize); $row < $row_max; ++$row)
- {
- $left .= isset($change['old'][$row]) ? htmlspecialchars($change['old'][$row]) : '';
- $left .= '<br />';
- $right .= isset($change['new'][$row]) ? htmlspecialchars($change['new'][$row]) : '';
- $right .= '<br />';
- }
-
- $output .= '<tr>';
-
- if (!empty($left))
- {
- $output .= '<td class="modified"><pre>' . $left . '<br /></pre></td>';
- }
- else if ($row < $oldsize)
- {
- $output .= '<td class="modified">&nbsp;</td>';
- }
- else
- {
- $output .= '<td class="unmodified">&nbsp;</td>';
- }
-
- if (!empty($right))
- {
- $output .= '<td class="modified"><pre>' . $right . '<br /></pre></td>';
- }
- else if ($row < $newsize)
- {
- $output .= '<td class="modified">&nbsp;</td>';
- }
- else
- {
- $output .= '<td class="unmodified">&nbsp;</td>';
- }
-
- $output .= '</tr>';
- break;
- }
- }
-
- if (!empty($current_context))
- {
- $line = $current_context;
- $current_context = '';
-
- $output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td>';
- $output .= '<td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td></tr>';
- }
- }
- }
-
- $output .= '</tbody></table>';
-
- return $output;
- }
-
- function _start_diff()
- {
- $this->lines = array();
-
- $this->data = false;
- $this->cols = array(array(), array());
- $this->state = 'empty';
-
- return '';
- }
-
- function _end_diff()
- {
- // Just flush any remaining entries in the columns stack.
- switch ($this->state)
- {
- case 'add':
- $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]);
- break;
-
- case 'remove':
- // We have some removal lines pending in our stack, so flush them.
- $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]);
- break;
-
- case 'change':
- // We have both remove and addition lines, so this is a change block.
- $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]);
- break;
- }
-
- if ($this->data !== false)
- {
- $this->lines[] = $this->data;
- }
-
- return '';
- }
-
- function _block_header($xbeg, $xlen, $ybeg, $ylen)
- {
- // Push any previous header information to the return stack.
- if ($this->data !== false)
- {
- $this->lines[] = $this->data;
- }
-
- $this->data = array('type' => 'header', 'oldline' => $xbeg, 'newline' => $ybeg, 'contents' => array());
- $this->state = 'dump';
- }
-
- function _added($lines)
- {
- array_walk($lines, array(&$this, '_perform_add'));
- }
-
- function _perform_add($line)
- {
- if ($this->state == 'empty')
- {
- return '';
- }
-
- // This is just an addition line.
- if ($this->state == 'dump' || $this->state == 'add')
- {
- // Start adding to the addition stack.
- $this->cols[0][] = $line;
- $this->state = 'add';
- }
- else
- {
- // This is inside a change block, so start accumulating lines.
- $this->state = 'change';
- $this->cols[1][] = $line;
- }
- }
-
- function _deleted($lines)
- {
- array_walk($lines, array(&$this, '_perform_delete'));
- }
-
- function _perform_delete($line)
- {
- // This is a removal line.
- $this->state = 'remove';
- $this->cols[0][] = $line;
- }
-
- function _context($lines)
- {
- array_walk($lines, array(&$this, '_perform_context'));
- }
-
- function _perform_context($line)
- {
- // An empty block with no action.
- switch ($this->state)
- {
- case 'add':
- $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]);
- break;
-
- case 'remove':
- // We have some removal lines pending in our stack, so flush them.
- $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]);
- break;
-
- case 'change':
- // We have both remove and addition lines, so this is a change block.
- $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]);
- break;
- }
-
- $this->cols = array(array(), array());
- $this->data['contents'][] = array('type' => 'empty', 'line' => $line);
- $this->state = 'dump';
- }
-
- function _changed($orig, $final)
- {
- return $this->_deleted($orig) . $this->_added($final);
- }
-
-}
-
-?> \ No newline at end of file