includes/diffengine/Renderer/inline.php
changeset 1227 bdac73ed481e
parent 1 fe660c52c48f
equal deleted inserted replaced
1226:de56132c008d 1227:bdac73ed481e
    10  * @author  Ciprian Popovici
    10  * @author  Ciprian Popovici
    11  * @package Text_Diff
    11  * @package Text_Diff
    12  */
    12  */
    13 class Text_Diff_Renderer_inline extends Text_Diff_Renderer {
    13 class Text_Diff_Renderer_inline extends Text_Diff_Renderer {
    14 
    14 
    15     /**
    15 		/**
    16      * Number of leading context "lines" to preserve.
    16  		* Number of leading context "lines" to preserve.
    17      */
    17  		*/
    18     var $_leading_context_lines = 10000;
    18 		var $_leading_context_lines = 10000;
    19 
    19 
    20     /**
    20 		/**
    21      * Number of trailing context "lines" to preserve.
    21  		* Number of trailing context "lines" to preserve.
    22      */
    22  		*/
    23     var $_trailing_context_lines = 10000;
    23 		var $_trailing_context_lines = 10000;
    24 
    24 
    25     /**
    25 		/**
    26      * Prefix for inserted text.
    26  		* Prefix for inserted text.
    27      */
    27  		*/
    28     var $_ins_prefix = '<ins>';
    28 		var $_ins_prefix = '<ins>';
    29 
    29 
    30     /**
    30 		/**
    31      * Suffix for inserted text.
    31  		* Suffix for inserted text.
    32      */
    32  		*/
    33     var $_ins_suffix = '</ins>';
    33 		var $_ins_suffix = '</ins>';
    34 
    34 
    35     /**
    35 		/**
    36      * Prefix for deleted text.
    36  		* Prefix for deleted text.
    37      */
    37  		*/
    38     var $_del_prefix = '<del>';
    38 		var $_del_prefix = '<del>';
    39 
    39 
    40     /**
    40 		/**
    41      * Suffix for deleted text.
    41  		* Suffix for deleted text.
    42      */
    42  		*/
    43     var $_del_suffix = '</del>';
    43 		var $_del_suffix = '</del>';
    44 
    44 
    45     /**
    45 		/**
    46      * Header for each change block.
    46  		* Header for each change block.
    47      */
    47  		*/
    48     var $_block_header = '';
    48 		var $_block_header = '';
    49 
    49 
    50     /**
    50 		/**
    51      * What are we currently splitting on? Used to recurse to show word-level
    51  		* What are we currently splitting on? Used to recurse to show word-level
    52      * changes.
    52  		* changes.
    53      */
    53  		*/
    54     var $_split_level = 'words';
    54 		var $_split_level = 'words';
    55 
    55 
    56     function _blockHeader($xbeg, $xlen, $ybeg, $ylen)
    56 		function _blockHeader($xbeg, $xlen, $ybeg, $ylen)
    57     {
    57 		{
    58         return $this->_block_header;
    58 				return $this->_block_header;
    59     }
    59 		}
    60 
    60 
    61     function _startBlock($header)
    61 		function _startBlock($header)
    62     {
    62 		{
    63         return $header;
    63 				return $header;
    64     }
    64 		}
    65 
    65 
    66     function _lines($lines, $prefix = ' ', $encode = true)
    66 		function _lines($lines, $prefix = ' ', $encode = true)
    67     {
    67 		{
    68         if ($encode) {
    68 				if ($encode) {
    69             array_walk($lines, array(&$this, '_encode'));
    69 						array_walk($lines, array(&$this, '_encode'));
    70         }
    70 				}
    71 
    71 
    72         if ($this->_split_level == 'words') {
    72 				if ($this->_split_level == 'words') {
    73             return implode('', $lines);
    73 						return implode('', $lines);
    74         } else {
    74 				} else {
    75             return implode("\n", $lines) . "\n";
    75 						return implode("\n", $lines) . "\n";
    76         }
    76 				}
    77     }
    77 		}
    78 
    78 
    79     function _added($lines)
    79 		function _added($lines)
    80     {
    80 		{
    81         array_walk($lines, array(&$this, '_encode'));
    81 				array_walk($lines, array(&$this, '_encode'));
    82         $lines[0] = $this->_ins_prefix . $lines[0];
    82 				$lines[0] = $this->_ins_prefix . $lines[0];
    83         $lines[count($lines) - 1] .= $this->_ins_suffix;
    83 				$lines[count($lines) - 1] .= $this->_ins_suffix;
    84         return $this->_lines($lines, ' ', false);
    84 				return $this->_lines($lines, ' ', false);
    85     }
    85 		}
    86 
    86 
    87     function _deleted($lines, $words = false)
    87 		function _deleted($lines, $words = false)
    88     {
    88 		{
    89         array_walk($lines, array(&$this, '_encode'));
    89 				array_walk($lines, array(&$this, '_encode'));
    90         $lines[0] = $this->_del_prefix . $lines[0];
    90 				$lines[0] = $this->_del_prefix . $lines[0];
    91         $lines[count($lines) - 1] .= $this->_del_suffix;
    91 				$lines[count($lines) - 1] .= $this->_del_suffix;
    92         return $this->_lines($lines, ' ', false);
    92 				return $this->_lines($lines, ' ', false);
    93     }
    93 		}
    94     
    94 		
    95     function _context($lines)
    95 		function _context($lines)
    96     {
    96 		{
    97         return "<!-- Start context -->\n<tr><td></td><td class=\"diff-context\">".$this->_lines($lines).'</td></tr>'."\n<!-- End context -->\n\n";
    97 				return "<!-- Start context -->\n<tr><td></td><td class=\"diff-context\">".$this->_lines($lines).'</td></tr>'."\n<!-- End context -->\n\n";
    98     }
    98 		}
    99 
    99 
   100     function _changed($orig, $final)
   100 		function _changed($orig, $final)
   101     {
   101 		{
   102         /* If we've already split on words, don't try to do so again - just
   102 				/* If we've already split on words, don't try to do so again - just
   103          * display. */
   103  				* display. */
   104         if ($this->_split_level == 'words') {
   104 				if ($this->_split_level == 'words') {
   105             $prefix = '';
   105 						$prefix = '';
   106             while ($orig[0] !== false && $final[0] !== false &&
   106 						while ($orig[0] !== false && $final[0] !== false &&
   107                    substr($orig[0], 0, 1) == ' ' &&
   107  									substr($orig[0], 0, 1) == ' ' &&
   108                    substr($final[0], 0, 1) == ' ') {
   108  									substr($final[0], 0, 1) == ' ') {
   109                 $prefix .= substr($orig[0], 0, 1);
   109 								$prefix .= substr($orig[0], 0, 1);
   110                 $orig[0] = substr($orig[0], 1);
   110 								$orig[0] = substr($orig[0], 1);
   111                 $final[0] = substr($final[0], 1);
   111 								$final[0] = substr($final[0], 1);
   112             }
   112 						}
   113             return $prefix . $this->_deleted($orig) . $this->_added($final);
   113 						return $prefix . $this->_deleted($orig) . $this->_added($final);
   114         }
   114 				}
   115 
   115 
   116         $text1 = implode("\n", $orig);
   116 				$text1 = implode("\n", $orig);
   117         $text2 = implode("\n", $final);
   117 				$text2 = implode("\n", $final);
   118 
   118 
   119         /* Non-printing newline marker. */
   119 				/* Non-printing newline marker. */
   120         $nl = "\0";
   120 				$nl = "\0";
   121 
   121 
   122         /* We want to split on word boundaries, but we need to
   122 				/* We want to split on word boundaries, but we need to
   123          * preserve whitespace as well. Therefore we split on words,
   123  				* preserve whitespace as well. Therefore we split on words,
   124          * but include all blocks of whitespace in the wordlist. */
   124  				* but include all blocks of whitespace in the wordlist. */
   125         $diff = &new Text_Diff($this->_splitOnWords($text1, $nl),
   125 				$diff = &new Text_Diff($this->_splitOnWords($text1, $nl),
   126                                $this->_splitOnWords($text2, $nl));
   126  															$this->_splitOnWords($text2, $nl));
   127 
   127 
   128         /* Get the diff in inline format. */
   128 				/* Get the diff in inline format. */
   129         $renderer = &new Text_Diff_Renderer_inline(array_merge($this->getParams(),
   129 				$renderer = &new Text_Diff_Renderer_inline(array_merge($this->getParams(),
   130                                                                array('split_level' => 'words')));
   130  																															array('split_level' => 'words')));
   131 
   131 
   132         /* Run the diff and get the output. */
   132 				/* Run the diff and get the output. */
   133         return str_replace($nl, "\n", $renderer->render($diff)) . "\n";
   133 				return str_replace($nl, "\n", $renderer->render($diff)) . "\n";
   134     }
   134 		}
   135 
   135 
   136     function _splitOnWords($string, $newlineEscape = "\n")
   136 		function _splitOnWords($string, $newlineEscape = "\n")
   137     {
   137 		{
   138         $words = array();
   138 				$words = array();
   139         $length = strlen($string);
   139 				$length = strlen($string);
   140         $pos = 0;
   140 				$pos = 0;
   141 
   141 
   142         while ($pos < $length) {
   142 				while ($pos < $length) {
   143             // Eat a word with any preceding whitespace.
   143 						// Eat a word with any preceding whitespace.
   144             $spaces = strspn(substr($string, $pos), " \n");
   144 						$spaces = strspn(substr($string, $pos), " \n");
   145             $nextpos = strcspn(substr($string, $pos + $spaces), " \n");
   145 						$nextpos = strcspn(substr($string, $pos + $spaces), " \n");
   146             $words[] = str_replace("\n", $newlineEscape, substr($string, $pos, $spaces + $nextpos));
   146 						$words[] = str_replace("\n", $newlineEscape, substr($string, $pos, $spaces + $nextpos));
   147             $pos += $spaces + $nextpos;
   147 						$pos += $spaces + $nextpos;
   148         }
   148 				}
   149 
   149 
   150         return $words;
   150 				return $words;
   151     }
   151 		}
   152 
   152 
   153     function _encode(&$string)
   153 		function _encode(&$string)
   154     {
   154 		{
   155         $string = htmlspecialchars($string);
   155 				$string = htmlspecialchars($string);
   156     }
   156 		}
   157 
   157 
   158 }
   158 }