KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > DiffMode


1 /*
2  * DiffMode.java
3  *
4  * Copyright (C) 1998-2004 Peter Graves
5  * $Id: DiffMode.java,v 1.12 2004/08/08 00:54:04 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 import java.awt.AWTEvent JavaDoc;
25 import java.awt.event.KeyEvent JavaDoc;
26 import java.awt.event.MouseEvent JavaDoc;
27 import java.util.List JavaDoc;
28
29 public final class DiffMode extends AbstractMode implements Constants, Mode
30 {
31     private static final DiffMode mode = new DiffMode();
32
33     private DiffMode()
34     {
35         super(DIFF_MODE, DIFF_MODE_NAME);
36     }
37
38     public static final DiffMode getMode()
39     {
40         return mode;
41     }
42
43     public Formatter getFormatter(Buffer buffer)
44     {
45         return new DiffFormatter(buffer);
46     }
47
48     protected void setKeyMapDefaults( KeyMap km )
49     {
50         km.mapKey(KeyEvent.VK_ENTER, 0, "diffGotoFile");
51         km.mapKey(KeyEvent.VK_G, CTRL_MASK | SHIFT_MASK, "diffGotoFile");
52         km.mapKey(VK_DOUBLE_MOUSE_1, 0, "diffGotoFile");
53         km.mapKey(VK_MOUSE_2, 0, "diffGotoFile");
54     }
55
56     public static void diff()
57     {
58         final Editor editor = Editor.currentEditor();
59         final Buffer buffer = editor.getBuffer();
60         File file = buffer.getFile();
61         if (file.isLocal() && file.isFile()) {
62             File patchFile = buffer.getPatchFile();
63             if (patchFile != null && patchFile.isFile()) {
64                 boolean save = false;
65                 if (buffer.isModified()) {
66                     int response =
67                         ConfirmDialog.showConfirmDialogWithCancelButton(editor,
68                             CHECK_SAVE_PROMPT, "diff");
69                     switch (response) {
70                         case RESPONSE_YES:
71                             save = true;
72                             break;
73                         case RESPONSE_NO:
74                             break;
75                         case RESPONSE_CANCEL:
76                             return;
77                     }
78                     editor.repaintNow();
79                 }
80                 editor.setWaitCursor();
81                 if (!save || buffer.save()) {
82                     FastStringBuffer sb = new FastStringBuffer("-u \"");
83                     sb.append(patchFile.canonicalPath());
84                     sb.append("\" \"");
85                     sb.append(file.canonicalPath());
86                     sb.append('"');
87                     diff(sb.toString());
88                 }
89                 return;
90             }
91         }
92         diff("--help");
93     }
94
95     public static void diff(String JavaDoc args)
96     {
97         final Editor editor = Editor.currentEditor();
98         final Buffer parentBuffer = editor.getBuffer();
99         String JavaDoc defaultOptions = "-u ";
100         List JavaDoc argList = Utilities.tokenize(args);
101         for (int i = 0; i < argList.size(); i++) {
102             String JavaDoc arg = (String JavaDoc) argList.get(i);
103             if (arg.equals("%")) {
104                 File file = parentBuffer.getFile();
105                 if (file == null) {
106                     MessageDialog.showMessageDialog(
107                         "There is no file associated with the current buffer.",
108                         "Error");
109                     return;
110                 }
111                 if (file.isRemote()) {
112                     MessageDialog.showMessageDialog(
113                         file.netPath() + " is a remote file.",
114                         "Error");
115                     return;
116                 }
117                 if (file.isDirectory()) {
118                     MessageDialog.showMessageDialog(
119                         file.canonicalPath() + " is a directory.",
120                         "Error");
121                     return;
122                 }
123                 // OK.
124
argList.set(i, file.canonicalPath());
125             } else if (arg.startsWith("-")) {
126                 defaultOptions = null;
127             } else {
128                 File file = File.getInstance(editor.getCurrentDirectory(), arg);
129                 if (file.exists())
130                     argList.set(i, file.canonicalPath());
131             }
132         }
133         editor.setWaitCursor();
134         FastStringBuffer sb = new FastStringBuffer("diff ");
135         if (defaultOptions != null)
136             sb.append(defaultOptions);
137         for (int i = 0; i < argList.size(); i++) {
138             String JavaDoc s = (String JavaDoc) argList.get(i);
139             if (s.indexOf(' ') >= 0) {
140                 sb.append('"');
141                 sb.append(s);
142                 sb.append('"');
143             } else
144                 sb.append(s);
145             sb.append(' ');
146         }
147         String JavaDoc cmdline = sb.toString().trim();
148         ShellCommand shellCommand = new ShellCommand(cmdline);
149         shellCommand.run();
150         String JavaDoc output = shellCommand.getOutput();
151         if (output.length() == 0)
152             MessageDialog.showMessageDialog(editor, "No changes", "diff");
153         else {
154             DiffOutputBuffer buf = new DiffOutputBuffer(parentBuffer, output, 0);
155             buf.setTitle(cmdline);
156             editor.makeNext(buf);
157             editor.activateInOtherWindow(buf);
158             editor.setDefaultCursor();
159         }
160     }
161
162     public static void gotoFile()
163     {
164         final Editor editor = Editor.currentEditor();
165         if (editor.getDot() == null)
166             return;
167         final Buffer buffer = editor.getBuffer();
168         if (!(buffer instanceof DiffOutputBuffer))
169             return;
170
171         // If this method is invoked via a mouse event mapping, move dot to
172
// location of mouse click first.
173
AWTEvent JavaDoc e = editor.getDispatcher().getLastEvent();
174         if (e instanceof MouseEvent JavaDoc)
175             editor.mouseMoveDotToPoint((MouseEvent JavaDoc) e);
176
177         DiffOutputBuffer diffOutputBuffer = (DiffOutputBuffer) buffer;
178         int vcType = diffOutputBuffer.getVCType();
179         switch (vcType) {
180             case VC_P4:
181                 p4GotoFile(editor, diffOutputBuffer);
182                 break;
183             case VC_CVS:
184                 cvsGotoFile(editor, diffOutputBuffer);
185                 break;
186             default:
187                 localGotoFile(editor, diffOutputBuffer);
188                 break;
189         }
190     }
191
192     private static void cvsGotoFile(Editor editor, DiffOutputBuffer diffOutputBuffer)
193     {
194         final Line dotLine = editor.getDotLine();
195         final int dotOffset = editor.getDotOffset();
196         final String JavaDoc text = dotLine.getText();
197         if (text.startsWith("? ") || text.startsWith("Index: ")) {
198             String JavaDoc filename = text.substring(text.indexOf(' ')+1);
199             File file = File.getInstance(diffOutputBuffer.getDirectory(),
200                 filename);
201             Buffer buf = editor.getBuffer(file);
202             if (buf != null) {
203                 if (editor.getOtherEditor() != null) {
204                     editor.activateInOtherWindow(buf);
205                 } else {
206                     editor.makeNext(buf);
207                     editor.activate(buf);
208                 }
209             }
210             return;
211         }
212         int lineNumber = 0;
213         int count = 0;
214         Line line = dotLine;
215         if (line.getText().startsWith("@@")) {
216             lineNumber = parseLineNumber(line);
217         } else {
218             line = line.previous();
219             while (line != null && !line.getText().startsWith("@@")) {
220                 if (!line.getText().startsWith("-"))
221                     ++count;
222                 line = line.previous();
223             }
224             if (line == null)
225                 return;
226             Debug.assertTrue(line.getText().startsWith("@@"));
227             lineNumber = parseLineNumber(line);
228         }
229         // Our line numbers are zero-based.
230
if (--lineNumber < 0)
231             return;
232         lineNumber += count;
233         Buffer parentBuffer = diffOutputBuffer.getParentBuffer();
234         File dir;
235         if (parentBuffer != null)
236             dir = parentBuffer.getCurrentDirectory();
237         else
238             dir = diffOutputBuffer.getDirectory();
239
240         line = line.previous();
241         while (line != null && !line.getText().startsWith("Index: "))
242             line = line.previous();
243         if (line == null)
244             return;
245         if (line.getText().startsWith("Index: ")) {
246             String JavaDoc filename = line.getText().substring(7);
247             File file = File.getInstance(dir, filename);
248             if (file != null && file.isFile()) {
249                 Buffer buf = editor.getBuffer(file);
250                 if (buf != null)
251                     gotoLocation(editor, buf, lineNumber,
252                         dotOffset > 0 ? dotOffset-1 : 0);
253             }
254         } else
255             Debug.bug();
256     }
257
258     private static void p4GotoFile(Editor editor,
259         DiffOutputBuffer diffOutputBuffer)
260     {
261         final Line dotLine = editor.getDotLine();
262         final int dotOffset = editor.getDotOffset();
263         final String JavaDoc text = dotLine.getText();
264         int lineNumber = 0;
265         int count = 0;
266         Line line = dotLine;
267         if (line.getText().startsWith("@@")) {
268             lineNumber = parseLineNumber(line);
269         } else {
270             line = line.previous();
271             while (line != null && !line.getText().startsWith("@@")) {
272                 if (!line.getText().startsWith("-"))
273                     ++count;
274                 line = line.previous();
275             }
276             if (line == null)
277                 return;
278             Debug.assertTrue(line.getText().startsWith("@@"));
279             lineNumber = parseLineNumber(line);
280         }
281         // Our line numbers are zero-based.
282
if (--lineNumber < 0)
283             return;
284         lineNumber += count;
285         Buffer parentBuffer = diffOutputBuffer.getParentBuffer();
286         File dir;
287         if (parentBuffer != null)
288             dir = parentBuffer.getCurrentDirectory();
289         else
290             dir = diffOutputBuffer.getDirectory();
291         line = line.previous();
292         while (line != null && !line.getText().endsWith(" ===="))
293             line = line.previous();
294         if (line == null)
295             return;
296         int index = line.getText().lastIndexOf(" - ");
297         if (index >= 0) {
298             String JavaDoc filename = line.getText().substring(index+3);
299             if (filename.endsWith(" ===="))
300                 filename = filename.substring(0, filename.length()-5);
301             File file = File.getInstance(dir, filename);
302             if (file != null && file.isFile()) {
303                 Buffer buf = editor.getBuffer(file);
304                 if (buf != null)
305                     gotoLocation(editor, buf, lineNumber,
306                         dotOffset > 0 ? dotOffset-1 : 0);
307             }
308         }
309     }
310
311     private static void localGotoFile(Editor editor,
312         DiffOutputBuffer diffOutputBuffer)
313     {
314         final Line dotLine = editor.getDotLine();
315         String JavaDoc filename1 = null;
316         String JavaDoc filename2 = null;;
317         for (Line line = dotLine; line != null; line = line.previous()) {
318             String JavaDoc text = line.getText();
319             if (text.startsWith("+++ ")) {
320                 filename2 = extractFilename(text);
321             } else if (text.startsWith("--- ")) {
322                 filename1 = extractFilename(text);
323                 if (filename2 == null) {
324                     line = line.next();
325                     if (line != null)
326                         filename2 = extractFilename(line.getText());
327                 }
328                 break;
329             }
330         }
331         final String JavaDoc text = dotLine.getText();
332         if (text.startsWith("---")) {
333             Buffer buf = editor.getBuffer(File.getInstance(filename1));
334             if (buf != null) {
335                 editor.makeNext(buf);
336                 editor.activateInOtherWindow(buf);
337             }
338             return;
339         }
340         if (text.startsWith("+++")) {
341             Buffer buf = editor.getBuffer(File.getInstance(filename2));
342             if (buf != null) {
343                 editor.makeNext(buf);
344                 editor.activateInOtherWindow(buf);
345             }
346             return;
347         }
348         int oldLineNumber = -1;
349         int newLineNumber = -1;
350         int oldLines = 0;
351         int newLines = 0;
352         int unchangedLines = 0;
353         Line line = dotLine;
354         if (line.getText().startsWith("@@")) {
355             oldLineNumber = parseLineNumber(line, '-');
356             newLineNumber = parseLineNumber(line, '+');
357         } else {
358             line = line.previous();
359             while (line != null && !line.getText().startsWith("@@")) {
360                 if (line.getText().startsWith("-"))
361                     ++oldLines;
362                 else if (line.getText().startsWith("+"))
363                     ++newLines;
364                 else
365                     ++unchangedLines;
366                 line = line.previous();
367             }
368             if (line == null)
369                 return;
370             Debug.assertTrue(line.getText().startsWith("@@"));
371             oldLineNumber = parseLineNumber(line, '-');
372             newLineNumber = parseLineNumber(line, '+');
373         }
374         // Our line numbers are zero-based.
375
--oldLineNumber;
376         --newLineNumber;
377         String JavaDoc filename = filename2;
378         if (text.startsWith("-")) {
379             oldLineNumber += unchangedLines + oldLines;
380             newLineNumber += unchangedLines;
381             filename = filename1;
382         } else if (text.startsWith("+")) {
383             oldLineNumber += unchangedLines;
384             newLineNumber += unchangedLines + newLines;
385             filename = filename2;
386         } else {
387             // Context line.
388
oldLineNumber = oldLineNumber + unchangedLines + oldLines;
389             newLineNumber = newLineNumber + unchangedLines + newLines;
390             File parentFile = diffOutputBuffer.getParentBuffer().getFile();
391             if (parentFile != null) {
392                 String JavaDoc cp = parentFile.canonicalPath();
393                 if (cp != null) {
394                     if (cp.equals(filename1))
395                         filename = filename1;
396                 }
397             }
398         }
399         File dir = null;
400         Buffer parentBuffer = diffOutputBuffer.getParentBuffer();
401         if (parentBuffer != null)
402             dir = parentBuffer.getCurrentDirectory();
403         final File file;
404         if (dir != null)
405             file = File.getInstance(dir, filename);
406         else
407             file = File.getInstance(filename);
408         if (file != null && file.isFile()) {
409             Buffer buf = editor.getBuffer(file);
410             if (buf != null) {
411                 int lineNumber =
412                     (filename == filename1) ? oldLineNumber : newLineNumber;
413                 final int offset = editor.getDotOffset();
414                 gotoLocation(editor, buf, lineNumber,
415                     offset > 0 ? offset-1 : 0);
416             }
417         }
418     }
419
420     private static String JavaDoc extractFilename(String JavaDoc s)
421     {
422         if (s.startsWith("+++ ") || s.startsWith("--- "))
423             s = s.substring(4);
424         int index = s.indexOf('\t');
425         return index >= 0 ? s.substring(0, index) : s;
426     }
427
428     private static void gotoLocation(Editor editor, Buffer buf, int lineNumber,
429         int offset)
430     {
431         if (buf != null) {
432             editor.makeNext(buf);
433             Editor ed = editor.activateInOtherWindow(buf);
434             Position pos = buf.findOriginal(lineNumber, offset);
435             ed.moveDotTo(pos);
436             ed.setUpdateFlag(REFRAME);
437             ed.updateDisplay();
438         }
439     }
440
441     private static int parseLineNumber(Line line)
442     {
443         return parseLineNumber(line, '+');
444     }
445
446     private static int parseLineNumber(Line line, char c)
447     {
448         String JavaDoc s = line.getText();
449         int index = s.indexOf(c);
450         if (index < 0)
451             return 0;
452         try {
453             return Utilities.parseInt(s.substring(index+1));
454         }
455         catch (NumberFormatException JavaDoc e) {
456             Log.error(e);
457             return 0;
458         }
459     }
460 }
461
Popular Tags