~ubuntu-branches/ubuntu/quantal/netbeans/quantal

« back to all changes in this revision

Viewing changes to diff/src/org/netbeans/modules/diff/builtin/visualizer/DiffComponent.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
6
 * The contents of this file are subject to the terms of either the GNU
 
7
 * General Public License Version 2 only ("GPL") or the Common
 
8
 * Development and Distribution License("CDDL") (collectively, the
 
9
 * "License"). You may not use this file except in compliance with the
 
10
 * License. You can obtain a copy of the License at
 
11
 * http://www.netbeans.org/cddl-gplv2.html
 
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 
13
 * specific language governing permissions and limitations under the
 
14
 * License.  When distributing the software, include this License Header
 
15
 * Notice in each file and include the License file at
 
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 
17
 * particular file as subject to the "Classpath" exception as provided
 
18
 * by Sun in the GPL Version 2 section of the License file that
 
19
 * accompanied this code. If applicable, add the following below the
 
20
 * License Header, with the fields enclosed by brackets [] replaced by
 
21
 * your own identifying information:
 
22
 * "Portions Copyrighted [year] [name of copyright owner]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * The Original Software is NetBeans. The Initial Developer of the Original
 
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 
28
 * Microsystems, Inc. All Rights Reserved.
 
29
 *
 
30
 * If you wish your version of this file to be governed by only the CDDL
 
31
 * or only the GPL Version 2, indicate your decision by adding
 
32
 * "[Contributor] elects to include this software in this distribution
 
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 
34
 * single choice of license, a recipient has the option to distribute
 
35
 * your version of this file under either the CDDL, the GPL Version 2 or
 
36
 * to extend the choice of license to its licensees as provided above.
 
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 
38
 * Version 2 license, then the option applies only if the new code is
 
39
 * made subject to such option by the copyright holder.
 
40
 */
 
41
 
 
42
package org.netbeans.modules.diff.builtin.visualizer;
 
43
 
 
44
import java.util.*;
 
45
import java.io.*;
 
46
import javax.swing.*;
 
47
import javax.swing.text.*;
 
48
import java.awt.BorderLayout;
 
49
 
 
50
import org.openide.util.HelpCtx;
 
51
import org.openide.windows.*;
 
52
 
 
53
import org.netbeans.api.diff.Difference;
 
54
import org.netbeans.modules.diff.builtin.DiffPresenter;
 
55
 
 
56
//import org.netbeans.modules.vcscore.util.Debug;
 
57
//import org.netbeans.modules.vcscore.util.TopComponentCloseListener;
 
58
 
 
59
/**
 
60
 * This class displays two editor panes with two files and marks the differences
 
61
 * by a different color.
 
62
 *
 
63
 * @author  Martin Entlicher
 
64
 */
 
65
public class DiffComponent extends org.openide.windows.TopComponent {
 
66
 
 
67
    public static final java.awt.Color COLOR_MISSING = new java.awt.Color(255, 160, 180);
 
68
    public static final java.awt.Color COLOR_ADDED = new java.awt.Color(180, 255, 180);
 
69
    public static final java.awt.Color COLOR_CHANGED = new java.awt.Color(160, 200, 255);
 
70
    
 
71
    //private AbstractDiff diff = null;
 
72
    private Difference[] diffs = null;
 
73
    /** The shift of differences */
 
74
    private int[][] diffShifts;
 
75
    private DiffPanel diffPanel = null;
 
76
    
 
77
    private java.awt.Color colorMissing = COLOR_MISSING;
 
78
    private java.awt.Color colorAdded = COLOR_ADDED;
 
79
    private java.awt.Color colorChanged = COLOR_CHANGED;
 
80
    
 
81
    //private ArrayList closeListeners = new ArrayList();
 
82
    private int currentDiffLine = -1;
 
83
    
 
84
    /**
 
85
     * Used for deserialization.
 
86
     */
 
87
    private boolean diffSetSuccess = true;
 
88
 
 
89
    static final long serialVersionUID =3683458237532937983L;
 
90
    
 
91
    /**
 
92
     * An empty constructor needed by deserialization process.
 
93
     */
 
94
    public DiffComponent() {
 
95
        putClientProperty("PersistenceType", "Never");
 
96
    }
 
97
    
 
98
    /** Creates new DiffComponent from list of Difference objects */
 
99
    public DiffComponent(final Difference[] diffs, final String mainTitle, final String mimeType,
 
100
                         final String sourceName1, final String sourceName2,
 
101
                         final String title1, final String title2,
 
102
                         final Reader r1, final Reader r2) {
 
103
        this(diffs, mainTitle, mimeType, sourceName1, sourceName2, title1, title2,
 
104
             r1, r2, null);
 
105
    }
 
106
    
 
107
    /** Creates new DiffComponent from list of Difference objects */
 
108
    public DiffComponent(final Difference[] diffs, final String mainTitle, final String mimeType,
 
109
                         final String sourceName1, final String sourceName2,
 
110
                         final String title1, final String title2,
 
111
                         final Reader r1, final Reader r2, java.awt.Color[] colors) {
 
112
        this.diffs = diffs;
 
113
        diffShifts = new int[diffs.length][2];
 
114
        setLayout(new BorderLayout());
 
115
        diffPanel = new DiffPanel();
 
116
        putClientProperty(DiffPresenter.PROP_TOOLBAR, diffPanel.getClientProperty(DiffPresenter.PROP_TOOLBAR));
 
117
        diffPanel.addPrevLineButtonListener(new java.awt.event.ActionListener() {
 
118
            public void actionPerformed(java.awt.event.ActionEvent evt) {
 
119
                if (diffs.length == 0) return ;
 
120
                currentDiffLine--;
 
121
                if (currentDiffLine < 0) currentDiffLine = diffs.length - 1;
 
122
                showCurrentLine();
 
123
            }
 
124
        });
 
125
        diffPanel.addNextLineButtonListener(new java.awt.event.ActionListener() {
 
126
            public void actionPerformed(java.awt.event.ActionEvent evt) {
 
127
                if (diffs.length == 0) return ;
 
128
                currentDiffLine++;
 
129
                if (currentDiffLine >= diffs.length) currentDiffLine = 0;
 
130
                showCurrentLine();
 
131
            }
 
132
        });
 
133
        add(diffPanel, BorderLayout.CENTER);
 
134
        
 
135
        if (colors != null && colors.length >= 3) {
 
136
            colorMissing = colors[0];
 
137
            colorAdded = colors[1];
 
138
            colorChanged = colors[2];
 
139
        }
 
140
//        initComponents ();
 
141
        //setTitle(org.openide.util.NbBundle.getBundle(DiffComponent.class).getString("DiffComponent.title"));
 
142
        if (mainTitle == null) {
 
143
            setName(org.openide.util.NbBundle.getBundle(DiffComponent.class).getString("DiffComponent.title"));
 
144
        } else {
 
145
            setName(mainTitle);
 
146
        }
 
147
        setIcon(org.openide.util.Utilities.loadImage("org/netbeans/modules/diff/diffSettingsIcon.gif", true));
 
148
        initContent(mimeType, sourceName1, sourceName2, title1, title2, r1, r2);
 
149
        //HelpCtx.setHelpIDString (getRootPane (), DiffComponent.class.getName ());
 
150
        putClientProperty("PersistenceType", "Never");
 
151
    }
 
152
    
 
153
    public HelpCtx getHelpCtx() {
 
154
        return new HelpCtx(DiffComponent.class);
 
155
    }
 
156
 
 
157
 
 
158
 
 
159
    private void showCurrentLine() {
 
160
        if (currentDiffLine >= diffs.length) return;
 
161
        Difference diff = diffs[currentDiffLine];
 
162
        int line = diff.getFirstStart() + diffShifts[currentDiffLine][0];
 
163
        if (diff.getType() == Difference.ADD) line++;
 
164
        int lf1 = diff.getFirstEnd() - diff.getFirstStart() + 1;
 
165
        int lf2 = diff.getSecondEnd() - diff.getSecondStart() + 1;
 
166
        int length = Math.max(lf1, lf2);
 
167
        diffPanel.setCurrentLine(line, length);
 
168
    }
 
169
    
 
170
    private void initContent(String mimeType, String sourceName1, String sourceName2,
 
171
                             String title1, String title2, Reader r1, Reader r2) {
 
172
        setMimeType1(mimeType);
 
173
        setMimeType2(mimeType);
 
174
        try {
 
175
            setSource1(r1);
 
176
            setSource2(r2);
 
177
        } catch (IOException ioex) {
 
178
            org.openide.ErrorManager.getDefault().notify(ioex);
 
179
        }
 
180
        setSource1Title(title1);
 
181
        setSource2Title(title2);
 
182
        insertEmptyLines(true);
 
183
        setDiffHighlight(true);
 
184
        insertEmptyLinesNotReported();
 
185
    }
 
186
 
 
187
    @Deprecated
 
188
    public void open(Workspace workspace) {
 
189
        super.open(workspace);
 
190
        diffPanel.open();
 
191
        if (currentDiffLine < 0) {
 
192
            currentDiffLine = 0;
 
193
            showCurrentLine();
 
194
        }
 
195
    }
 
196
    
 
197
    /**
 
198
     * Transfer the focus to the diff panel.
 
199
     */
 
200
    @Deprecated
 
201
    public void requestFocus() {
 
202
        super.requestFocus();
 
203
        diffPanel.requestFocus();
 
204
    }
 
205
    
 
206
    /**
 
207
     * Transfer the focus to the diff panel.
 
208
     */
 
209
    @Deprecated
 
210
    public boolean requestFocusInWindow() {
 
211
        super.requestFocusInWindow();
 
212
        return diffPanel.requestFocusInWindow();
 
213
    }
 
214
    
 
215
    public void addNotify() {
 
216
        super.addNotify();
 
217
        if (currentDiffLine < 0) {
 
218
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
 
219
                public void run() {
 
220
                    diffPanel.open();
 
221
                    javax.swing.SwingUtilities.invokeLater(new Runnable() {
 
222
                        public void run() {
 
223
                            java.awt.Toolkit.getDefaultToolkit().sync();
 
224
                            javax.swing.SwingUtilities.invokeLater(new Runnable() {
 
225
                                public void run() {
 
226
                                    if (currentDiffLine < 0) {
 
227
                                        currentDiffLine = 0;
 
228
                                        showCurrentLine();
 
229
                                    }
 
230
                                }
 
231
                            });
 
232
                        }
 
233
                    });
 
234
                }
 
235
            });
 
236
        }
 
237
    }
 
238
    
 
239
    /**
 
240
     * Override for clean up reasons.
 
241
     * Will be moved to the appropriate method when will be made.
 
242
     */
 
243
    @Deprecated
 
244
    public boolean canClose(Workspace workspace, boolean last) {
 
245
        boolean can = super.canClose(workspace, last);
 
246
        if (last && can) {
 
247
            exitForm(null);
 
248
        }
 
249
        return can;
 
250
    }
 
251
    /*
 
252
    public void removeNotify() {
 
253
        System.out.println("removeNotify() called");
 
254
        exitForm(null);
 
255
        super.removeNotify();
 
256
    }
 
257
     */
 
258
    
 
259
    public void setSource1(Reader r) throws IOException {
 
260
        diffPanel.setSource1(r);
 
261
    }
 
262
    
 
263
    public void setSource2(Reader r) throws IOException {
 
264
        diffPanel.setSource2(r);
 
265
    }
 
266
    
 
267
    public void setSource1Title(String title) {
 
268
        diffPanel.setSource1Title(title);
 
269
    }
 
270
    
 
271
    public void setSource2Title(String title) {
 
272
        diffPanel.setSource2Title(title);
 
273
    }
 
274
    
 
275
    public void setMimeType1(String mime) {
 
276
        diffPanel.setMimeType1(mime);
 
277
    }
 
278
    
 
279
    public void setMimeType2(String mime) {
 
280
        diffPanel.setMimeType2(mime);
 
281
    }
 
282
    
 
283
    public void setDocument1(Document doc) {
 
284
        diffPanel.setDocument1(doc);
 
285
    }
 
286
    
 
287
    public void setDocument2(Document doc) {
 
288
        diffPanel.setDocument2(doc);
 
289
    }
 
290
    
 
291
    public void unhighlightAll() {
 
292
        diffPanel.unhighlightAll();
 
293
    }
 
294
    
 
295
    public void highlightRegion1(int line1, int line2, java.awt.Color color) {
 
296
        //D.deb("Highlight region 1"); // NOI18N
 
297
        diffPanel.highlightRegion1(line1, line2, color);
 
298
    }
 
299
    
 
300
    public void highlightRegion2(int line1, int line2, java.awt.Color color) {
 
301
        //D.deb("Highlight region 2"); // NOI18N
 
302
        diffPanel.highlightRegion2(line1, line2, color);
 
303
    }
 
304
    
 
305
    public void addEmptyLines1(int line, int numLines) {
 
306
        diffPanel.addEmptyLines1(line, numLines);
 
307
    }
 
308
    
 
309
    public void addEmptyLines2(int line, int numLines) {
 
310
        diffPanel.addEmptyLines2(line, numLines);
 
311
    }
 
312
        
 
313
    public void writeExternal(ObjectOutput out) throws IOException {
 
314
        super.writeExternal(out);
 
315
        //try {
 
316
        out.writeObject(diffs);
 
317
        /*
 
318
        } catch (IOException exc) {
 
319
            System.out.println("exc = "+exc);
 
320
            exc.printStackTrace();
 
321
            throw exc;
 
322
        }
 
323
         */
 
324
    }
 
325
    
 
326
    private void insertEmptyLines(boolean updateActionLines) {
 
327
        int n = diffs.length;
 
328
        //int ins1 = 0;
 
329
        //int ins2 = 0;
 
330
        //D.deb("insertEmptyLines():"); // NOI18N
 
331
        for(int i = 0; i < n; i++) {
 
332
            Difference action = diffs[i];
 
333
            int n1 = action.getFirstStart() + diffShifts[i][0];
 
334
            int n2 = action.getFirstEnd() + diffShifts[i][0];
 
335
            int n3 = action.getSecondStart() + diffShifts[i][1];
 
336
            int n4 = action.getSecondEnd() + diffShifts[i][1];
 
337
            //System.out.println("Action = "+action);
 
338
            //System.out.println("ins1 = "+diffShifts[i][0]+", ins2 = "+diffShifts[i][1]);
 
339
            if (updateActionLines && i < n - 1) {
 
340
                diffShifts[i + 1][0] = diffShifts[i][0];
 
341
                diffShifts[i + 1][1] = diffShifts[i][1];
 
342
            }
 
343
            switch (action.getType()) {
 
344
                case Difference.DELETE:
 
345
                    addEmptyLines2(n3, n2 - n1 + 1);
 
346
                    if (updateActionLines && i < n - 1) {
 
347
                        diffShifts[i+1][1] += n2 - n1 + 1;
 
348
                    }
 
349
                    //ins2 += n2 - n1 + 1;
 
350
                    break;
 
351
                case Difference.ADD:
 
352
                    addEmptyLines1(n1, n4 - n3 + 1);
 
353
                    if (updateActionLines && i < n - 1) {
 
354
                        diffShifts[i+1][0] += n4 - n3 + 1;
 
355
                    }
 
356
                    //ins1 += n4 - n3 + 1;
 
357
                    break;
 
358
                case Difference.CHANGE:
 
359
                    int r1 = n2 - n1;
 
360
                    int r2 = n4 - n3;
 
361
                    if (r1 < r2) {
 
362
                        addEmptyLines1(n2, r2 - r1);
 
363
                        if (updateActionLines && i < n - 1) {
 
364
                            diffShifts[i+1][0] += r2 - r1;
 
365
                        }
 
366
                        //ins1 += r2 - r1;
 
367
                    } else if (r1 > r2) {
 
368
                        addEmptyLines2(n4, r1 - r2);
 
369
                        if (updateActionLines && i < n - 1) {
 
370
                            diffShifts[i+1][1] += r1 - r2;
 
371
                        }
 
372
                        //ins2 += r1 - r2;
 
373
                    }
 
374
                    break;
 
375
            }
 
376
        }
 
377
    }
 
378
    
 
379
    private void setDiffHighlight(boolean set) {
 
380
        int n = diffs.length;
 
381
        //D.deb("Num Actions = "+n); // NOI18N
 
382
        for(int i = 0; i < n; i++) {
 
383
            Difference action = diffs[i];
 
384
            int n1 = action.getFirstStart() + diffShifts[i][0];
 
385
            int n2 = action.getFirstEnd() + diffShifts[i][0];
 
386
            int n3 = action.getSecondStart() + diffShifts[i][1];
 
387
            int n4 = action.getSecondEnd() + diffShifts[i][1];
 
388
            //D.deb("Action: "+action.getAction()+": ("+n1+","+n2+","+n3+","+n4+")"); // NOI18N
 
389
            switch (action.getType()) {
 
390
            case Difference.DELETE:
 
391
                if (set) highlightRegion1(n1, n2, colorMissing);
 
392
                else highlightRegion1(n1, n2, java.awt.Color.white);
 
393
                break;
 
394
            case Difference.ADD:
 
395
                if (set) highlightRegion2(n3, n4, colorAdded);
 
396
                else highlightRegion2(n3, n4, java.awt.Color.white);
 
397
                break;
 
398
            case Difference.CHANGE:
 
399
                if (set) {
 
400
                    highlightRegion1(n1, n2, colorChanged);
 
401
                    highlightRegion2(n3, n4, colorChanged);
 
402
                } else {
 
403
                    highlightRegion1(n1, n2, java.awt.Color.white);
 
404
                    highlightRegion2(n3, n4, java.awt.Color.white);
 
405
                }
 
406
                break;
 
407
            }
 
408
        }
 
409
    }
 
410
    
 
411
    /**
 
412
     * Read one line from the given text, from the given position. It returns
 
413
     * the end position of this line and the beginning of the next one.
 
414
     * @param begin Contains just one value - IN: the beginning of the line to read.
 
415
     *              OUT: the start of the next line.
 
416
     * @param end Contains just one value - OUT: the end of the line.
 
417
     * @param text The text to read.
 
418
     * @return The line.
 
419
     */
 
420
    private static String readLine(int[] begin, int[] end, String text) {
 
421
        int n = text.length();
 
422
        for (int i = begin[0]; i < n; i++) {
 
423
            char c = text.charAt(i);
 
424
            if (c == '\n' || c == '\r') {
 
425
                end[0] = i;
 
426
                break;
 
427
            }
 
428
        }
 
429
        if (end[0] < begin[0]) end[0] = n;
 
430
        String line = text.substring(begin[0], end[0]);
 
431
        begin[0] = end[0] + 1;
 
432
        if (begin[0] < n && text.charAt(end[0]) == '\r' && text.charAt(begin[0]) == '\n') begin[0]++;
 
433
        return line;
 
434
    }
 
435
    
 
436
    /**
 
437
     * Find the first diff, that is on or below the given line number.
 
438
     * @return The index of the desired difference in the supplied array or
 
439
     *         a value, that is bigger then the array size if such a diff does
 
440
     *         not exist.
 
441
     */
 
442
    private static int findDiffForLine(int lineNumber, int diffIndex, Difference[] diffs, int[][] diffShifts) {
 
443
        while (diffIndex < diffs.length) {
 
444
            if ((diffs[diffIndex].getFirstEnd() + diffShifts[diffIndex][0]) >= lineNumber ||
 
445
                (diffs[diffIndex].getSecondEnd() + diffShifts[diffIndex][1]) >= lineNumber) break;
 
446
            diffIndex++;
 
447
        }
 
448
        return diffIndex;
 
449
    }
 
450
    
 
451
    /**
 
452
     * Find out whether the line lies in the difference.
 
453
     * @param lineNumber The number of the line.
 
454
     * @param diff The difference
 
455
     * @param diffShifts The shifts of the difference in the current document
 
456
     * @return true if the line lies in the difference, false if does not.
 
457
     */
 
458
    private static boolean isLineInDiff(int lineNumber, Difference diff, int[] diffShifts) {
 
459
        int l1 = diff.getFirstStart() + diffShifts[0];
 
460
        int l2 = diff.getFirstEnd() + diffShifts[0];
 
461
        int l3 = diff.getSecondStart() + diffShifts[1];
 
462
        int l4 = diff.getSecondEnd() + diffShifts[1];
 
463
        return (l1 <= lineNumber && ((l2 >= l1) ? (l2 >= lineNumber) : false)) ||
 
464
               (l3 <= lineNumber && ((l4 >= l3) ? (l4 >= lineNumber) : false));
 
465
    }
 
466
    
 
467
    private static int numEmptyLines(int beginLine, String text, int endLine) {
 
468
        if (endLine >= 0 && endLine <= beginLine) return 0;
 
469
        int numLines = 0;
 
470
        int[] begin = { beginLine };
 
471
        int[] end = { 0 };
 
472
        do {
 
473
            String line = readLine(begin, end, text);
 
474
            if (line.trim().length() > 0) break;
 
475
            numLines++;
 
476
        } while ((endLine < 0 || beginLine + numLines < endLine) && begin[0] < text.length());
 
477
        return numLines;
 
478
    }
 
479
    
 
480
    /**
 
481
     * We have to keep the balance of lines from the first and the second document,
 
482
     * so that corresponding lines will have the same line number in the document.
 
483
     * Because some diff providers can be set not to report changes in empty lines,
 
484
     * we have to use heuristics to balance the corresponding lines manually
 
485
     * if they do not match.
 
486
     * <p>
 
487
     * This method goes through both documents and finds unreported differences
 
488
     * in empty lines. Whenever it encounters an empty line with a corresponding
 
489
     * non-empty line, which in not inside a difference (== unreported),
 
490
     * it checks whether the following lines match (because there can be unreported
 
491
     * difference in the amount of space rather than a missing or added line).
 
492
     * If following lines "match", then silently add an empty line to the other
 
493
     * document. This added line is not highlighted, since it was not reported
 
494
     * as a difference.
 
495
     */
 
496
    private void insertEmptyLinesNotReported() {
 
497
        String docText1 = diffPanel.getDocumentText1();
 
498
        String docText2 = diffPanel.getDocumentText2();
 
499
        int[] begin1 = { 0 };
 
500
        int[] end1 = { -1 };
 
501
        int[] begin2 = { 0 };
 
502
        int[] end2 = { -1 };
 
503
        int n1 = docText1.length();
 
504
        int n2 = docText2.length();
 
505
        int lineNumber = 1;
 
506
        int diffIndex = 0;
 
507
        do {
 
508
            int lastBegin1 = begin1[0];
 
509
            int lastBegin2 = begin2[0];
 
510
            String line1 = readLine(begin1, end1, docText1);
 
511
            String line2 = readLine(begin2, end2, docText2);
 
512
            if (line1.length() == 0 && line2.length() > 0) {
 
513
                //System.out.println("Detected empty line LEFT "+lineNumber);
 
514
                diffIndex = findDiffForLine(lineNumber, diffIndex, diffs, diffShifts);
 
515
                if (diffIndex >= diffs.length || !isLineInDiff(lineNumber, diffs[diffIndex], diffShifts[diffIndex])) {
 
516
                    boolean addMissingLine;
 
517
                    if (line2.trim().length() == 0) {
 
518
                        int emptyLines1 = numEmptyLines(begin1[0], docText1, (diffIndex < diffs.length) ? diffs[diffIndex].getFirstStart() : -1);
 
519
                        int emptyLines2 = numEmptyLines(begin2[0], docText2, (diffIndex < diffs.length) ? diffs[diffIndex].getSecondStart() : -1);
 
520
                        addMissingLine = emptyLines1 > emptyLines2;
 
521
                        //System.out.println("emptyLines1 = "+emptyLines1+", emptyLines2 = "+emptyLines2);
 
522
                    } else {
 
523
                        addMissingLine = true;
 
524
                    }
 
525
                    if (addMissingLine) {
 
526
                        addEmptyLines2(lineNumber - 1, 1);
 
527
                        //highlightRegion2(lineNumber, lineNumber, colorAdded);
 
528
                        shiftDiffs(false, lineNumber);
 
529
                        begin2[0] = lastBegin2;
 
530
                        end2[0] = lastBegin2 - 1;
 
531
                    }
 
532
                }
 
533
            } else if (line2.length() == 0 && line1.length() > 0) {
 
534
                //System.out.println("Detected empty line RIGHT "+lineNumber);
 
535
                diffIndex = findDiffForLine(lineNumber, diffIndex, diffs, diffShifts);
 
536
                if (diffIndex >= diffs.length || !isLineInDiff(lineNumber, diffs[diffIndex], diffShifts[diffIndex])) {
 
537
                    boolean addMissingLine;
 
538
                    if (line1.trim().length() == 0) {
 
539
                        int emptyLines1 = numEmptyLines(begin1[0], docText1, (diffIndex < diffs.length) ? diffs[diffIndex].getFirstStart() : -1);
 
540
                        int emptyLines2 = numEmptyLines(begin2[0], docText2, (diffIndex < diffs.length) ? diffs[diffIndex].getSecondStart() : -1);
 
541
                        addMissingLine = emptyLines2 > emptyLines1;
 
542
                        //System.out.println("emptyLines1 = "+emptyLines1+", emptyLines2 = "+emptyLines2);
 
543
                    } else {
 
544
                        addMissingLine = true;
 
545
                    }
 
546
                    if (addMissingLine) {
 
547
                        addEmptyLines1(lineNumber - 1, 1);
 
548
                        //highlightRegion1(lineNumber, lineNumber, colorMissing);
 
549
                        shiftDiffs(true, lineNumber);
 
550
                        begin1[0] = lastBegin1;
 
551
                        end1[0] = lastBegin1 - 1;
 
552
                    }
 
553
                }
 
554
            }
 
555
            lineNumber++;
 
556
        } while (begin1[0] < n1 && begin2[0] < n2);
 
557
    }
 
558
    
 
559
    /**
 
560
     * Shift the differences by one in the first or the second document from the given line.
 
561
     * @param inFirstDoc True to shift differences the first document, false for the second.
 
562
     * @param fromLine The starting line. Shift all differences after this line.
 
563
     */
 
564
    private void shiftDiffs(boolean inFirstDoc, int fromLine) {
 
565
        int n = diffs.length;
 
566
        for(int i = 0; i < n; i++) {
 
567
            Difference action = diffs[i];
 
568
            if (inFirstDoc) {
 
569
                if (action.getFirstStart() + diffShifts[i][0] >= fromLine) {
 
570
                    diffShifts[i][0]++;
 
571
                }
 
572
            } else {
 
573
                if (action.getSecondStart() + diffShifts[i][1] >= fromLine) {
 
574
                    diffShifts[i][1]++;
 
575
                }
 
576
            }
 
577
        }        
 
578
    }
 
579
 
 
580
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
 
581
        super.readExternal(in);
 
582
        Object obj = in.readObject();
 
583
        diffs = (Difference[]) obj;
 
584
        diffPanel = new DiffPanel();
 
585
        //this.diffSetSuccess = diff.setDiffComponent(this);
 
586
    }
 
587
    
 
588
    private Object readResolve() throws ObjectStreamException {
 
589
        if (this.diffSetSuccess) return this;
 
590
        else return null;
 
591
    }
 
592
    
 
593
    /**
 
594
     * Disable serialization.
 
595
     */
 
596
    protected Object writeReplace () throws java.io.ObjectStreamException {
 
597
        exitForm(null);
 
598
        return null;
 
599
    }
 
600
    
 
601
       /** Exit the Application */
 
602
    private void exitForm(java.awt.event.WindowEvent evt) {
 
603
        SwingUtilities.invokeLater(new Runnable() {
 
604
            public void run() {
 
605
                diffPanel = null;
 
606
                diffs = null;
 
607
                removeAll();
 
608
            }
 
609
        });
 
610
        /*
 
611
        try {
 
612
            org.netbeans.editor.Settings.setValue(null, org.netbeans.editor.SettingsNames.LINE_NUMBER_VISIBLE, lineNumbersVisible);
 
613
        } catch (Throwable exc) {
 
614
            // editor module not found
 
615
        }
 
616
         */
 
617
        //System.out.println("exitForm() called.");
 
618
        //diff.closing();
 
619
        //close();
 
620
        //dispose ();
 
621
        /*
 
622
        for(Iterator it = closeListeners.iterator(); it.hasNext(); ) {
 
623
            ((TopComponentCloseListener) it.next()).closing();
 
624
        }
 
625
         */
 
626
 
 
627
    }
 
628
 
 
629
}