Initial patch.
[vuplus_webkit] / Websites / webkit.org / blog / wp-includes / Text / Diff / Renderer.php
diff --git a/Websites/webkit.org/blog/wp-includes/Text/Diff/Renderer.php b/Websites/webkit.org/blog/wp-includes/Text/Diff/Renderer.php
new file mode 100644 (file)
index 0000000..5d226b4
--- /dev/null
@@ -0,0 +1,237 @@
+<?php
+/**
+ * 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.
+ *
+ * $Horde: framework/Text_Diff/Diff/Renderer.php,v 1.21 2008/01/04 10:07:50 jan Exp $
+ *
+ * Copyright 2004-2008 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did
+ * not receive this file, see http://opensource.org/licenses/lgpl-license.php.
+ *
+ * @package Text_Diff
+ */
+class Text_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 Text_Diff_Renderer($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 getParams()
+    {
+        $params = array();
+        foreach (get_object_vars($this) as $k => $v) {
+            if ($k[0] == '_') {
+                $params[substr($k, 1)] = $v;
+            }
+        }
+
+        return $params;
+    }
+
+    /**
+     * Renders a diff.
+     *
+     * @param Text_Diff $diff  A Text_Diff object.
+     *
+     * @return string  The formatted output.
+     */
+    function render($diff)
+    {
+        $xi = $yi = 1;
+        $block = false;
+        $context = array();
+
+        $nlead = $this->_leading_context_lines;
+        $ntrail = $this->_trailing_context_lines;
+
+        $output = $this->_startDiff();
+
+        $diffs = $diff->getDiff();
+        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, 'Text_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 == count($diffs) - 1 ? $ntrail : $nlead + $ntrail;
+                    if (count($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 Text_Diff_Op_copy($context);
+                        }
+                        /* @todo */
+                        $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, count($context) - $nlead);
+                    $x0 = $xi - count($context);
+                    $y0 = $yi - count($context);
+                    $block = array();
+                    if ($context) {
+                        $block[] = &new Text_Diff_Op_copy($context);
+                    }
+                }
+                $block[] = $edit;
+            }
+
+            if ($edit->orig) {
+                $xi += count($edit->orig);
+            }
+            if ($edit->final) {
+                $yi += count($edit->final);
+            }
+        }
+
+        if (is_array($block)) {
+            $output .= $this->_block($x0, $xi - $x0,
+                                     $y0, $yi - $y0,
+                                     $block);
+        }
+
+        return $output . $this->_endDiff();
+    }
+
+    function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
+    {
+        $output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen));
+
+        foreach ($edits as $edit) {
+            switch (strtolower(get_class($edit))) {
+            case 'text_diff_op_copy':
+                $output .= $this->_context($edit->orig);
+                break;
+
+            case 'text_diff_op_add':
+                $output .= $this->_added($edit->final);
+                break;
+
+            case 'text_diff_op_delete':
+                $output .= $this->_deleted($edit->orig);
+                break;
+
+            case 'text_diff_op_change':
+                $output .= $this->_changed($edit->orig, $edit->final);
+                break;
+            }
+        }
+
+        return $output . $this->_endBlock();
+    }
+
+    function _startDiff()
+    {
+        return '';
+    }
+
+    function _endDiff()
+    {
+        return '';
+    }
+
+    function _blockHeader($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--;
+        } elseif (!$xlen) {
+            $xbeg--;
+        }
+
+        return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
+    }
+
+    function _startBlock($header)
+    {
+        return $header . "\n";
+    }
+
+    function _endBlock()
+    {
+        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);
+    }
+
+}