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

« back to all changes in this revision

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

  • Committer: William Grant
  • Date: 2009-02-23 23:47:02 UTC
  • mfrom: (1099.1.211 new-dispatch)
  • Revision ID: grantw@unimelb.edu.au-20090223234702-db4b1llly46ignwo
Merge from lp:~ivle-dev/ivle/new-dispatch.

Pretty much everything changes. Reread the setup docs. Backup your databases.
Every file is now in a different installed location, the configuration system
is rewritten, the dispatch system is rewritten, URLs are different, the
database is different, worksheets and exercises are no longer on the
filesystem, we use a templating engine, jail service protocols are rewritten,
we don't repeat ourselves, we have authorization rewritten, phpBB is gone,
and probably lots of other things that I cannot remember.

This is certainly the biggest commit I have ever made, and hopefully
the largest I ever will.

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'