~azzar1/unity/add-show-desktop-key

443 by dcoles
Added Forum application along with unmodifed version of phpBB3 "Olympus" 3.0.0
1
<?php
2
/**
3
*
4
* @package diff
5
* @version $Id: renderer.php,v 1.8 2007/10/05 14:36:33 acydburn Exp $
6
* @copyright (c) 2006 phpBB Group
7
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8
*
9
*/
10
11
/**
12
* @ignore
13
*/
14
if (!defined('IN_PHPBB'))
15
{
16
	exit;
17
}
18
19
/**
20
* Code from pear.php.net, Text_Diff-0.2.1 (beta) package
21
* http://pear.php.net/package/Text_Diff/
22
*
23
* Modified by phpBB Group to meet our coding standards
24
* and being able to integrate into phpBB
25
*
26
* A class to render Diffs in different formats.
27
*
28
* This class renders the diff in classic diff format. It is intended that
29
* this class be customized via inheritance, to obtain fancier outputs.
30
*
31
* @package diff
32
*/
33
class diff_renderer
34
{
35
	/**
36
	* Number of leading context "lines" to preserve.
37
	*
38
	* This should be left at zero for this class, but subclasses may want to
39
	* set this to other values.
40
	*/
41
	var $_leading_context_lines = 0;
42
43
	/**
44
	* Number of trailing context "lines" to preserve.
45
	*
46
	* This should be left at zero for this class, but subclasses may want to
47
	* set this to other values.
48
	*/
49
	var $_trailing_context_lines = 0;
50
51
	/**
52
	* Constructor.
53
	*/
54
	function diff_renderer($params = array())
55
	{
56
		foreach ($params as $param => $value)
57
		{
58
			$v = '_' . $param;
59
			if (isset($this->$v))
60
			{
61
				$this->$v = $value;
62
			}
63
		}
64
	}
65
66
	/**
67
	* Get any renderer parameters.
68
	*
69
	* @return array  All parameters of this renderer object.
70
	*/
71
	function get_params()
72
	{
73
		$params = array();
74
		foreach (get_object_vars($this) as $k => $v)
75
		{
76
			if ($k[0] == '_')
77
			{
78
				$params[substr($k, 1)] = $v;
79
			}
80
		}
81
82
		return $params;
83
	}
84
85
	/**
86
	* Renders a diff.
87
	*
88
	* @param diff &$diff A diff object.
89
	*
90
	* @return string  The formatted output.
91
	*/
92
	function render(&$diff)
93
	{
94
		$xi = $yi = 1;
95
		$block = false;
96
		$context = array();
97
98
		// Create a new diff object if it is a 3-way diff
99
		if (is_a($diff, 'diff3'))
100
		{
101
			$diff3 = &$diff;
102
103
			$diff_1 = $diff3->get_original();
104
			$diff_2 = $diff3->merged_output();
105
106
			unset($diff3);
107
108
			$diff = &new diff($diff_1, $diff_2);
109
		}
110
111
		$nlead = $this->_leading_context_lines;
112
		$ntrail = $this->_trailing_context_lines;
113
114
		$output = $this->_start_diff();
115
		$diffs = $diff->get_diff();
116
117
		foreach ($diffs as $i => $edit)
118
		{
119
			if (is_a($edit, 'diff_op_copy'))
120
			{
121
				if (is_array($block))
122
				{
123
					$keep = ($i == sizeof($diffs) - 1) ? $ntrail : $nlead + $ntrail;
124
					if (sizeof($edit->orig) <= $keep)
125
					{
126
						$block[] = $edit;
127
					}
128
					else
129
					{
130
						if ($ntrail)
131
						{
132
							$context = array_slice($edit->orig, 0, $ntrail);
133
							$block[] = &new diff_op_copy($context);
134
						}
135
136
						$output .= $this->_block($x0, $ntrail + $xi - $x0, $y0, $ntrail + $yi - $y0, $block);
137
						$block = false;
138
					}
139
				}
140
				$context = $edit->orig;
141
			}
142
			else
143
			{
144
				if (!is_array($block))
145
				{
146
					$context = array_slice($context, sizeof($context) - $nlead);
147
					$x0 = $xi - sizeof($context);
148
					$y0 = $yi - sizeof($context);
149
					$block = array();
150
151
					if ($context)
152
					{
153
						$block[] = &new diff_op_copy($context);
154
					}
155
				}
156
				$block[] = $edit;
157
			}
158
159
			$xi += ($edit->orig) ? sizeof($edit->orig) : 0;
160
			$yi += ($edit->final) ? sizeof($edit->final) : 0;
161
		}
162
163
		if (is_array($block))
164
		{
165
			$output .= $this->_block($x0, $xi - $x0, $y0, $yi - $y0, $block);
166
		}
167
168
		return $output . $this->_end_diff();
169
	}
170
171
	function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
172
	{
173
		$output = $this->_start_block($this->_block_header($xbeg, $xlen, $ybeg, $ylen));
174
175
		foreach ($edits as $edit)
176
		{
177
			switch (get_class($edit))
178
			{
179
				case 'diff_op_copy':
180
					$output .= $this->_context($edit->orig);
181
				break;
182
183
				case 'diff_op_add':
184
					$output .= $this->_added($edit->final);
185
				break;
186
187
				case 'diff_op_delete':
188
					$output .= $this->_deleted($edit->orig);
189
				break;
190
191
				case 'diff_op_change':
192
					$output .= $this->_changed($edit->orig, $edit->final);
193
				break;
194
			}
195
		}
196
197
		return $output . $this->_end_block();
198
	}
199
200
	function _start_diff()
201
	{
202
		return '';
203
	}
204
205
	function _end_diff()
206
	{
207
		return '';
208
	}
209
210
	function _block_header($xbeg, $xlen, $ybeg, $ylen)
211
	{
212
		if ($xlen > 1)
213
		{
214
			$xbeg .= ',' . ($xbeg + $xlen - 1);
215
		}
216
217
		if ($ylen > 1)
218
		{
219
			$ybeg .= ',' . ($ybeg + $ylen - 1);
220
		}
221
222
		return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
223
	}
224
225
	function _start_block($header)
226
	{
227
		return $header . "\n";
228
	}
229
230
	function _end_block()
231
	{
232
		return '';
233
	}
234
235
	function _lines($lines, $prefix = ' ')
236
	{
237
		return $prefix . implode("\n$prefix", $lines) . "\n";
238
	}
239
240
	function _context($lines)
241
	{
242
		return $this->_lines($lines, '  ');
243
	}
244
245
	function _added($lines)
246
	{
247
		return $this->_lines($lines, '> ');
248
	}
249
250
	function _deleted($lines)
251
	{
252
		return $this->_lines($lines, '< ');
253
	}
254
255
	function _changed($orig, $final)
256
	{
257
		return $this->_deleted($orig) . "---\n" . $this->_added($final);
258
	}
259
260
	/**
261
	* Our function to get the diff
262
	*/
263
	function get_diff_content($diff)
264
	{
265
		return $this->render($diff);
266
	}
267
}
268
269
/**
270
* Renders a unified diff
271
* @package diff
272
*/
273
class diff_renderer_unified extends diff_renderer
274
{
275
	var $_leading_context_lines = 4;
276
	var $_trailing_context_lines = 4;
277
278
	/**
279
	* Our function to get the diff
280
	*/
281
	function get_diff_content($diff)
282
	{
283
		return nl2br($this->render($diff));
284
	}
285
286
	function _block_header($xbeg, $xlen, $ybeg, $ylen)
287
	{
288
		if ($xlen != 1)
289
		{
290
			$xbeg .= ',' . $xlen;
291
		}
292
293
		if ($ylen != 1)
294
		{
295
			$ybeg .= ',' . $ylen;
296
		}
297
		return '<div class="diff"><big class="info">@@ -' . $xbeg . ' +' . $ybeg . ' @@</big></div>';
298
	}
299
300
	function _context($lines)
301
	{
302
		return '<pre class="diff context">' . htmlspecialchars($this->_lines($lines, ' ')) . '<br /></pre>';
303
	}
304
	
305
	function _added($lines)
306
	{
307
		return '<pre class="diff added">' . htmlspecialchars($this->_lines($lines, '+')) . '<br /></pre>';
308
	}
309
310
	function _deleted($lines)
311
	{
312
		return '<pre class="diff removed">' . htmlspecialchars($this->_lines($lines, '-')) . '<br /></pre>';
313
	}
314
315
	function _changed($orig, $final)
316
	{
317
		return $this->_deleted($orig) . $this->_added($final);
318
	}
319
320
	function _start_diff()
321
	{
322
		$start = '<div class="file">';
323
324
		return $start;
325
	}
326
327
	function _end_diff()
328
	{
329
		return '</div>';
330
	}
331
332
	function _end_block()
333
	{
334
		return '';
335
	}
336
}
337
338
/**
339
* "Inline" diff renderer.
340
*
341
* This class renders diffs in the Wiki-style "inline" format.
342
*
343
* @author  Ciprian Popovici
344
* @package diff
345
*/
346
class diff_renderer_inline extends diff_renderer
347
{
348
	var $_leading_context_lines = 10000;
349
	var $_trailing_context_lines = 10000;
350
351
	// Prefix and suffix for inserted text
352
	var $_ins_prefix = '<span class="ins">';
353
	var $_ins_suffix = '</span>';
354
355
	// Prefix and suffix for deleted text
356
	var $_del_prefix = '<span class="del">';
357
	var $_del_suffix = '</span>';
358
359
	var $_block_head = '';
360
361
	// What are we currently splitting on? Used to recurse to show word-level
362
	var $_split_level = 'lines';
363
364
	/**
365
	* Our function to get the diff
366
	*/
367
	function get_diff_content($diff)
368
	{
369
		return '<pre>' . nl2br($this->render($diff)) . '<br /></pre>';
370
	}
371
372
	function _start_diff()
373
	{
374
		return '';
375
	}
376
377
	function _end_diff()
378
	{
379
		return '';
380
	}
381
382
	function _block_header($xbeg, $xlen, $ybeg, $ylen)
383
	{
384
		return $this->_block_head;
385
	}
386
387
	function _start_block($header)
388
	{
389
		return $header;
390
	}
391
392
	function _lines($lines, $prefix = ' ', $encode = true)
393
	{
394
		if ($encode)
395
		{
396
			array_walk($lines, array(&$this, '_encode'));
397
		}
398
399
		if ($this->_split_level == 'words')
400
		{
401
			return implode('', $lines);
402
		}
403
		else
404
		{
405
			return implode("\n", $lines) . "\n";
406
		}
407
	}
408
409
	function _added($lines)
410
	{
411
		array_walk($lines, array(&$this, '_encode'));
412
		$lines[0] = $this->_ins_prefix . $lines[0];
413
		$lines[sizeof($lines) - 1] .= $this->_ins_suffix;
414
		return $this->_lines($lines, ' ', false);
415
	}
416
417
	function _deleted($lines, $words = false)
418
	{
419
		array_walk($lines, array(&$this, '_encode'));
420
		$lines[0] = $this->_del_prefix . $lines[0];
421
		$lines[sizeof($lines) - 1] .= $this->_del_suffix;
422
		return $this->_lines($lines, ' ', false);
423
	}
424
425
	function _changed($orig, $final)
426
	{
427
		// If we've already split on words, don't try to do so again - just display.
428
		if ($this->_split_level == 'words')
429
		{
430
			$prefix = '';
431
			while ($orig[0] !== false && $final[0] !== false && substr($orig[0], 0, 1) == ' ' && substr($final[0], 0, 1) == ' ')
432
			{
433
				$prefix .= substr($orig[0], 0, 1);
434
				$orig[0] = substr($orig[0], 1);
435
				$final[0] = substr($final[0], 1);
436
			}
437
438
			return $prefix . $this->_deleted($orig) . $this->_added($final);
439
		}
440
441
		$text1 = implode("\n", $orig);
442
		$text2 = implode("\n", $final);
443
444
		// Non-printing newline marker.
445
		$nl = "\0";
446
447
		// We want to split on word boundaries, but we need to preserve whitespace as well.
448
		// Therefore we split on words, but include all blocks of whitespace in the wordlist.
449
		$splitted_text_1 = $this->_split_on_words($text1, $nl);
450
		$splitted_text_2 = $this->_split_on_words($text2, $nl);
451
		
452
		$diff = &new diff($splitted_text_1, $splitted_text_2);
453
		unset($splitted_text_1, $splitted_text_2);
454
455
		// Get the diff in inline format.
456
		$renderer = &new diff_renderer_inline(array_merge($this->get_params(), array('split_level' => 'words')));
457
458
		// Run the diff and get the output.
459
		return str_replace($nl, "\n", $renderer->render($diff)) . "\n";
460
	}
461
462
	function _split_on_words($string, $newline_escape = "\n")
463
	{
464
		// Ignore \0; otherwise the while loop will never finish.
465
		$string = str_replace("\0", '', $string);
466
		
467
		$words = array();
468
		$length = strlen($string);
469
		$pos = 0;
470
471
		$tab_there = true;
472
		while ($pos < $length)
473
		{
474
			// Check for tabs... do not include them
475
			if ($tab_there && substr($string, $pos, 1) === "\t")
476
			{
477
				$words[] = "\t";
478
				$pos++;
479
480
				continue;
481
			}
482
			else
483
			{
484
				$tab_there = false;
485
			}
486
487
			// Eat a word with any preceding whitespace.
488
			$spaces = strspn(substr($string, $pos), " \n");
489
			$nextpos = strcspn(substr($string, $pos + $spaces), " \n");
490
			$words[] = str_replace("\n", $newline_escape, substr($string, $pos, $spaces + $nextpos));
491
			$pos += $spaces + $nextpos;
492
		}
493
494
		return $words;
495
	}
496
497
	function _encode(&$string)
498
	{
499
		$string = htmlspecialchars($string);
500
	}
501
}
502
503
/**
504
* "raw" diff renderer.
505
* This class could be used to output a raw unified patch file
506
*
507
* @package diff
508
*/
509
class diff_renderer_raw extends diff_renderer
510
{
511
	var $_leading_context_lines = 4;
512
	var $_trailing_context_lines = 4;
513
514
	/**
515
	* Our function to get the diff
516
	*/
517
	function get_diff_content($diff)
518
	{
519
		return '<textarea style="height: 290px;" class="full">' . htmlspecialchars($this->render($diff)) . '</textarea>';
520
	}
521
522
	function _block_header($xbeg, $xlen, $ybeg, $ylen)
523
	{
524
		if ($xlen != 1)
525
		{
526
			$xbeg .= ',' . $xlen;
527
		}
528
529
		if ($ylen != 1)
530
		{
531
			$ybeg .= ',' . $ylen;
532
		}
533
		return '@@ -' . $xbeg . ' +' . $ybeg . ' @@';
534
	}
535
536
	function _context($lines)
537
	{
538
		return $this->_lines($lines, ' ');
539
	}
540
	
541
	function _added($lines)
542
	{
543
		return $this->_lines($lines, '+');
544
	}
545
546
	function _deleted($lines)
547
	{
548
		return $this->_lines($lines, '-');
549
	}
550
551
	function _changed($orig, $final)
552
	{
553
		return $this->_deleted($orig) . $this->_added($final);
554
	}
555
}
556
557
/**
558
* "chora (Horde)" diff renderer - similar style.
559
* This renderer class is a modified human_readable function from the Horde Framework.
560
*
561
* @package diff
562
*/
563
class diff_renderer_side_by_side extends diff_renderer
564
{
565
	var $_leading_context_lines = 3;
566
	var $_trailing_context_lines = 3;
567
568
	var $lines = array();
569
570
	// Hold the left and right columns of lines for change blocks.
571
	var $cols;
572
	var $state;
573
574
	var $data = false;
575
576
	/**
577
	* Our function to get the diff
578
	*/
579
	function get_diff_content($diff)
580
	{
581
		global $user;
582
583
		$output = '';
584
		$output .= '<table cellspacing="0" class="hrdiff">
585
<caption>
586
	<span class="unmodified">&nbsp;</span> ' . $user->lang['LINE_UNMODIFIED'] . '
587
	<span class="added">&nbsp;</span> ' . $user->lang['LINE_ADDED'] . '
588
	<span class="modified">&nbsp;</span> ' . $user->lang['LINE_MODIFIED'] . '
589
	<span class="removed">&nbsp;</span> ' . $user->lang['LINE_REMOVED'] . '
590
</caption>
591
<tbody>
592
';
593
594
		$this->render($diff);
595
596
		// Is the diff empty?
597
		if (!sizeof($this->lines))
598
		{
599
			$output .= '<tr><th colspan="2">' . $user->lang['NO_VISIBLE_CHANGES'] . '</th></tr>';
600
		}
601
		else
602
		{
603
			// Iterate through every header block of changes
604
			foreach ($this->lines as $header)
605
			{
606
				$output .= '<tr><th>Line ' . $header['oldline'] . '</th><th>' . $user->lang['LINE'] . ' ' . $header['newline'] . '</th></tr>';
607
608
				// Each header block consists of a number of changes (add, remove, change).
609
				$current_context = '';
610
611
				foreach ($header['contents'] as $change)
612
				{
613
					if (!empty($current_context) && $change['type'] != 'empty')
614
					{
615
						$line = $current_context;
616
						$current_context = '';
617
618
						$output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td>
619
							<td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td></tr>';
620
					}
621
622
					switch ($change['type'])
623
					{
624
						case 'add':
625
							$line = '';
626
627
							foreach ($change['lines'] as $_line)
628
							{
629
								$line .= htmlspecialchars($_line) . '<br />';
630
							}
631
632
							$output .= '<tr><td class="added_empty">&nbsp;</td><td class="added"><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td></tr>';
633
						break;
634
635
						case 'remove':
636
							$line = '';
637
638
							foreach ($change['lines'] as $_line)
639
							{
640
								$line .= htmlspecialchars($_line) . '<br />';
641
							}
642
643
							$output .= '<tr><td class="removed"><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td><td class="removed_empty">&nbsp;</td></tr>';
644
						break;
645
646
						case 'empty':
647
							$current_context .= htmlspecialchars($change['line']) . '<br />';
648
						break;
649
650
						case 'change':
651
							// Pop the old/new stacks one by one, until both are empty.
652
							$oldsize = sizeof($change['old']);
653
							$newsize = sizeof($change['new']);
654
							$left = $right = '';
655
656
							for ($row = 0, $row_max = max($oldsize, $newsize); $row < $row_max; ++$row)
657
							{
658
								$left .= isset($change['old'][$row]) ? htmlspecialchars($change['old'][$row]) : '';
659
								$left .= '<br />';
660
								$right .= isset($change['new'][$row]) ? htmlspecialchars($change['new'][$row]) : '';
661
								$right .= '<br />';
662
							}
663
664
							$output .= '<tr>';
665
666
							if (!empty($left))
667
							{
668
								$output .= '<td class="modified"><pre>' . $left . '<br /></pre></td>';
669
							}
670
							else if ($row < $oldsize)
671
							{
672
								$output .= '<td class="modified">&nbsp;</td>';
673
							}
674
							else
675
							{
676
								$output .= '<td class="unmodified">&nbsp;</td>';
677
							}
678
679
							if (!empty($right))
680
							{
681
								$output .= '<td class="modified"><pre>' . $right . '<br /></pre></td>';
682
							}
683
							else if ($row < $newsize)
684
							{
685
								$output .= '<td class="modified">&nbsp;</td>';
686
							}
687
							else
688
							{
689
								$output .= '<td class="unmodified">&nbsp;</td>';
690
							}
691
692
							$output .= '</tr>';
693
						break;
694
					}
695
				}
696
697
				if (!empty($current_context))
698
				{
699
					$line = $current_context;
700
					$current_context = '';
701
702
					$output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td>';
703
					$output .= '<td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td></tr>';
704
				}
705
			}
706
		}
707
708
		$output .= '</tbody></table>';
709
710
		return $output;
711
	}
712
713
	function _start_diff()
714
	{
715
		$this->lines = array();
716
717
		$this->data = false;
718
		$this->cols = array(array(), array());
719
		$this->state = 'empty';
720
721
		return '';
722
	}
723
724
	function _end_diff()
725
	{
726
		// Just flush any remaining entries in the columns stack.
727
		switch ($this->state)
728
		{
729
			case 'add':
730
				$this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]);
731
			break;
732
733
			case 'remove':
734
				// We have some removal lines pending in our stack, so flush them.
735
				$this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]);
736
			break;
737
738
			case 'change':
739
				// We have both remove and addition lines, so this is a change block.
740
				$this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]);
741
			break;
742
		}
743
744
		if ($this->data !== false)
745
		{
746
			$this->lines[] = $this->data;
747
		}
748
749
		return '';
750
	}
751
752
	function _block_header($xbeg, $xlen, $ybeg, $ylen)
753
	{
754
		// Push any previous header information to the return stack.
755
		if ($this->data !== false)
756
		{
757
			$this->lines[] = $this->data;
758
		}
759
760
		$this->data = array('type' => 'header', 'oldline' => $xbeg, 'newline' => $ybeg, 'contents' => array());
761
		$this->state = 'dump';
762
	}
763
764
	function _added($lines)
765
	{
766
		array_walk($lines, array(&$this, '_perform_add'));
767
	}
768
769
	function _perform_add($line)
770
	{
771
		if ($this->state == 'empty')
772
		{
773
			return '';
774
		}
775
776
		// This is just an addition line.
777
		if ($this->state == 'dump' || $this->state == 'add')
778
		{
779
			// Start adding to the addition stack.
780
			$this->cols[0][] = $line;
781
			$this->state = 'add';
782
		}
783
		else
784
		{
785
			// This is inside a change block, so start accumulating lines.
786
			$this->state = 'change';
787
			$this->cols[1][] = $line;
788
		}
789
	}
790
791
	function _deleted($lines)
792
	{
793
		array_walk($lines, array(&$this, '_perform_delete'));
794
	}
795
796
	function _perform_delete($line)
797
	{
798
		// This is a removal line.
799
		$this->state = 'remove';
800
		$this->cols[0][] = $line;
801
	}
802
803
	function _context($lines)
804
	{
805
		array_walk($lines, array(&$this, '_perform_context'));
806
	}
807
808
	function _perform_context($line)
809
	{
810
		// An empty block with no action.
811
		switch ($this->state)
812
		{
813
			case 'add':
814
				$this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]);
815
			break;
816
817
			case 'remove':
818
				// We have some removal lines pending in our stack, so flush them.
819
				$this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]);
820
			break;
821
822
			case 'change':
823
				// We have both remove and addition lines, so this is a change block.
824
				$this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]);
825
			break;
826
		}
827
828
		$this->cols = array(array(), array());
829
		$this->data['contents'][] = array('type' => 'empty', 'line' => $line);
830
		$this->state = 'dump';
831
	}
832
833
	function _changed($orig, $final)
834
	{
835
		return $this->_deleted($orig) . $this->_added($final);
836
	}
837
838
}
839
840
?>