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

« back to all changes in this revision

Viewing changes to www/php/phpBB3/includes/diff/renderer.php

Merge setup-stuff.

phpBB is gone, configuration, setup and jail building are completely redone.

Please read doc/setup/install_proc.txt, or you'll not get far.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
?>
 
 
b'\\ No newline at end of file'