KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * RegionCommands.java
3  *
4  * Copyright (C) 1998-2003 Peter Graves
5  * $Id: RegionCommands.java,v 1.3 2003/06/28 16:11:54 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 gnu.regexp.RE;
25 import gnu.regexp.REMatch;
26 import gnu.regexp.UncheckedRE;
27 import java.io.IOException JavaDoc;
28 import java.io.OutputStream JavaDoc;
29 import javax.swing.undo.CompoundEdit JavaDoc;
30 import org.armedbear.j.mail.Base64Decoder;
31
32 public final class RegionCommands
33 {
34     public static void detabRegion()
35     {
36         detabOrEntabRegion(false);
37     }
38
39     public static void entabRegion()
40     {
41         detabOrEntabRegion(true);
42     }
43
44     private static void detabOrEntabRegion(boolean entab)
45     {
46         final Editor editor = Editor.currentEditor();
47         final Position mark = editor.getMark(); // Alias, not copy.
48
if (mark == null)
49             return;
50         editor.setWaitCursor();
51         final Buffer buffer = editor.getBuffer();
52         final int count = Editor.getEditorCount();
53         Editor[] editors = new Editor[count];
54         int[] dotCol = new int[count];
55         int[] markCol = new int[count];
56         int i = 0;
57         for (EditorIterator it = new EditorIterator(); it.hasNext();) {
58             Editor ed = it.nextEditor();
59             editors[i] = ed;
60             if (ed.getBuffer() == buffer) {
61                 dotCol[i] = ed.getDotCol();
62                 if (ed.getMark() != null)
63                     markCol[i] = buffer.getCol(ed.getMark());
64             }
65             ++i;
66         }
67         final Region r = new Region(editor);
68         final int tabWidth = buffer.getTabWidth();
69         try {
70             buffer.lockWrite();
71         }
72         catch (InterruptedException JavaDoc e) {
73             Log.error(e);
74             return;
75         }
76         try {
77             detabOrEntabRegion(editor, buffer, r, entab, tabWidth);
78         }
79         finally {
80             buffer.unlockWrite();
81         }
82         for (i = 0; i < count; i++) {
83             Editor ed = editors[i];
84             if (ed.getBuffer() == buffer) {
85                 ed.moveDotToCol(dotCol[i]);
86                 if (ed.getMark() != null)
87                     ed.getMark().moveToCol(markCol[i], tabWidth);
88             }
89         }
90         buffer.repaint();
91         editor.setDefaultCursor();
92     }
93
94     private static void detabOrEntabRegion(Editor editor, Buffer buffer,
95         Region r, boolean entab, int tabWidth)
96     {
97         CompoundEdit JavaDoc compoundEdit = new CompoundEdit JavaDoc();
98         compoundEdit.addEdit(new UndoMove(editor));
99         boolean changed = false;
100         final Line beginLine = r.getBeginLine();
101         final int beginOffset = r.getBeginOffset();
102         final Line endLine = r.getEndLine();
103         final int endOffset = r.getEndOffset();
104         final int startCol = buffer.getCol(beginLine, beginOffset);
105         if (beginLine == endLine) {
106             final String JavaDoc oldText = beginLine.getText();
107             final String JavaDoc head = oldText.substring(0, beginOffset);
108             final String JavaDoc toBeChanged = oldText.substring(beginOffset,
109                 endOffset);
110             final String JavaDoc tail = oldText.substring(endOffset);
111             FastStringBuffer sb = new FastStringBuffer(head);
112             if (entab)
113                 sb.append(Utilities.entab(toBeChanged, tabWidth, startCol));
114             else
115                 sb.append(Utilities.detab(toBeChanged, tabWidth, startCol));
116             sb.append(tail);
117             final String JavaDoc newText = sb.toString();
118             if (!newText.equals(oldText)) {
119                 compoundEdit.addEdit(new UndoLineEdit(buffer, beginLine));
120                 beginLine.setText(newText);
121                 changed = true;
122             }
123         } else {
124             // Begin line.
125
String JavaDoc oldText = beginLine.getText();
126             final String JavaDoc head = oldText.substring(0, beginOffset);
127             String JavaDoc toBeChanged = oldText.substring(beginOffset);
128             FastStringBuffer sb = new FastStringBuffer(head);
129             if (entab)
130                 sb.append(Utilities.entab(toBeChanged, tabWidth, startCol));
131             else
132                 sb.append(Utilities.detab(toBeChanged, tabWidth, startCol));
133             String JavaDoc newText = sb.toString();
134             if (!newText.equals(oldText)) {
135                 compoundEdit.addEdit(new UndoLineEdit(buffer, beginLine));
136                 beginLine.setText(newText);
137                 changed = true;
138             }
139
140             // Lines in middle of region.
141
Line line = beginLine.next();
142             while (line != null && line != endLine) {
143                 oldText = line.getText();
144                 if (entab)
145                     newText = Utilities.entab(oldText, tabWidth);
146                 else
147                     newText = Utilities.detab(oldText, tabWidth);
148                 if (!newText.equals(oldText)) {
149                     compoundEdit.addEdit(new UndoLineEdit(buffer, line));
150                     line.setText(newText);
151                     changed = true;
152                 }
153                 line = line.next();
154             }
155
156             // End line.
157
oldText = endLine.getText();
158             toBeChanged = oldText.substring(0, endOffset);
159             final String JavaDoc tail = oldText.substring(endOffset);
160             sb.setLength(0);
161             if (entab)
162                 sb.append(Utilities.entab(toBeChanged, tabWidth));
163             else
164                 sb.append(Utilities.detab(toBeChanged, tabWidth));
165             sb.append(tail);
166             newText = sb.toString();
167             if (!newText.equals(oldText)) {
168                 compoundEdit.addEdit(new UndoLineEdit(buffer, endLine));
169                 endLine.setText(newText);
170                 changed = true;
171             }
172         }
173         if (changed) {
174             compoundEdit.end();
175             buffer.addEdit(compoundEdit);
176             buffer.modified();
177         }
178     }
179
180     public static void upperCaseRegion()
181     {
182         final Editor editor = Editor.currentEditor();
183         editor.setWaitCursor();
184         changeCaseRegion(editor, true);
185         editor.setDefaultCursor();
186     }
187
188     public static void lowerCaseRegion()
189     {
190         final Editor editor = Editor.currentEditor();
191         editor.setWaitCursor();
192         changeCaseRegion(editor, false);
193         editor.setDefaultCursor();
194     }
195
196     private static void changeCaseRegion(Editor editor, boolean toUpper)
197     {
198         if (!editor.checkReadOnly())
199             return;
200         if (editor.getDot() == null || editor.getMark() == null)
201             return;
202         if (editor.getDot().equals(editor.getMark()))
203             return;
204         final Buffer buffer = editor.getBuffer();
205
206         // A hard update is only necessary if the region spans a line boundary.
207
boolean hard = editor.getDotLine() != editor.getMarkLine();
208
209         try {
210             buffer.lockWrite();
211         }
212         catch (InterruptedException JavaDoc e) {
213             Log.error(e);
214             return;
215         }
216         try {
217             CompoundEdit JavaDoc compoundEdit = editor.beginCompoundEdit();
218             editor.addUndo(SimpleEdit.MOVE);
219             final Region r = new Region(editor);
220             final String JavaDoc s = r.toString();
221             editor.getDot().moveTo(r.getBegin());
222
223             // Save undo information before calling Region.delete so modified
224
// flag will be correct if we revert.
225
editor.addUndoDeleteRegion(r);
226
227             // Sets buffer modified flag.
228
r.delete();
229
230             editor.addUndo(SimpleEdit.INSERT_STRING);
231             editor.insertStringInternal(toUpper ? s.toUpperCase() : s.toLowerCase());
232             editor.endCompoundEdit(compoundEdit);
233             editor.moveCaretToDotCol();
234             if (hard)
235                 buffer.repaint();
236             else
237                 Editor.updateInAllEditors(editor.getDotLine());
238             editor.setMark(null);
239         }
240         finally {
241             buffer.unlockWrite();
242         }
243     }
244
245     public static void decodeRegion()
246     {
247         final Editor editor = Editor.currentEditor();
248         ByteBuffer bb = new ByteBuffer();
249         if (editor.getMark() != null) {
250             if (editor.getMarkOffset() == 0 && editor.getDotOffset() == 0) {
251                 Region r = new Region(editor);
252                 for (Line line = r.getBeginLine(); line != r.getEndLine(); line = line.next()) {
253                     byte[] decodedBytes = decodeLine(line);
254                     if (decodedBytes == null) {
255                         MessageDialog.showMessageDialog("Unable to decode region", "Decode Region");
256                         return;
257                     }
258                     bb.append(decodedBytes);
259                 }
260             } else {
261                 MessageDialog.showMessageDialog("Region must consist of whole lines only.", "Decode Region");
262                 return;
263             }
264         } else {
265             byte[] decodedBytes = decodeLine(editor.getDotLine());
266             if (decodedBytes == null) {
267                 MessageDialog.showMessageDialog("Unable to decode region", "Decode Region");
268                 return;
269             }
270             bb.append(decodedBytes);
271         }
272         byte[] bytes = bb.getBytes();
273         final int length = bb.length();
274         boolean isBinary = false;
275         for (int i = 0; i < length; i++) {
276             byte b = bytes[i];
277             if (b == 0) {
278                 isBinary = true;
279                 break;
280             }
281         }
282         if (isBinary) {
283             SaveFileDialog d = new SaveFileDialog(editor, "Save As");
284             editor.centerDialog(d);
285             d.show();
286             File saveAs = d.getDestination();
287             if (saveAs == null)
288                 return;
289             // At this point, if the target file exists, the user has said
290
// it's OK to overwrite it.
291
try {
292                 OutputStream JavaDoc out = saveAs.getOutputStream();
293                 if (out != null) {
294                     out.write(bytes, 0, length);
295                     out.flush();
296                     out.close();
297                 }
298             }
299             catch (IOException JavaDoc e) {
300                 Log.error(e);
301             }
302         } else {
303             Buffer buf = new Buffer(0);
304             buf.setText(new String JavaDoc(bytes, 0, length));
305             editor.makeNext(buf);
306             editor.activate(buf);
307         }
308     }
309
310     private static final byte[] decodeLine(Line line)
311     {
312         return Base64Decoder.decode(line.trim());
313     }
314
315     public static void renumberRegion()
316     {
317         renumberRegion(null);
318     }
319
320     public static void renumberRegion(String JavaDoc arg)
321     {
322         final Editor editor = Editor.currentEditor();
323         if (editor.getMark() == null)
324             return;
325         final Region region = new Region(editor);
326         if (region.getEndLineNumber() - region.getBeginLineNumber() < 2)
327             return;
328         if (!editor.checkReadOnly())
329             return;
330         int start = -1;
331         if (arg != null) {
332             try {
333                 start = Integer.parseInt(arg);
334             }
335             catch (NumberFormatException JavaDoc e) {
336                 MessageDialog.showMessageDialog(
337                     "Invalid number \"" + arg + '"',
338                     "Error");
339                 return;
340             }
341         }
342         final Buffer buffer = editor.getBuffer();
343         try {
344             buffer.lockWrite();
345         }
346         catch (InterruptedException JavaDoc e) {
347             Log.error(e);
348             return;
349         }
350         try {
351             _renumberRegion(editor, buffer, region, start);
352         }
353         finally {
354             buffer.unlockWrite();
355         }
356     }
357
358     private static void _renumberRegion(Editor editor, Buffer buffer,
359         Region region, int start)
360     {
361         CompoundEdit JavaDoc compoundEdit = null;
362         if (start < 0) {
363             for (Line line = region.getBeginLine(); line != region.getEndLine(); line = line.next()) {
364                 final String JavaDoc text = line.getText();
365                 int index = findNumber(text, buffer.getMode());
366                 if (index >= 0) {
367                     FastStringBuffer sb = new FastStringBuffer();
368                     while (index < text.length()) {
369                         char c = text.charAt(index++);
370                         if (c >= '0' && c <= '9')
371                             sb.append(c);
372                         else
373                             break;
374                     }
375                     try {
376                         int n = Integer.parseInt(sb.toString());
377                         if (start < 0)
378                             start = n;
379                         else if (n < start)
380                             start = n;
381                     }
382                     catch (NumberFormatException JavaDoc e) {
383                         Log.error(e);
384                     }
385                 }
386             }
387         }
388         for (Line line = region.getBeginLine(); line != region.getEndLine(); line = line.next()) {
389             final String JavaDoc text = line.getText();
390             int index = findNumber(text, buffer.getMode());
391             if (index < 0)
392                 continue;
393             FastStringBuffer sb = new FastStringBuffer(text.substring(0, index));
394             while (index < text.length() && Character.isDigit(text.charAt(index)))
395                 ++index;
396             sb.append(start++);
397             sb.append(text.substring(index));
398             String JavaDoc newText = sb.toString();
399             if (!newText.equals(text)) {
400                 if (compoundEdit == null) {
401                     compoundEdit = new CompoundEdit JavaDoc();
402                     compoundEdit.addEdit(new UndoMove(editor));
403                 }
404                 compoundEdit.addEdit(new UndoLineEdit(buffer, line));
405                 line.setText(newText);
406             }
407         }
408         if (compoundEdit != null) {
409             compoundEdit.end();
410             buffer.addEdit(compoundEdit);
411             buffer.modified();
412         }
413         buffer.setNeedsParsing(true);
414         buffer.getFormatter().parseBuffer();
415         buffer.repaint();
416     }
417
418     private static int findNumber(String JavaDoc text, Mode mode)
419     {
420         RE re = new UncheckedRE("[0-9]+");
421         int index = 0;
422         int limit = text.length();
423         while (index <= limit) {
424             REMatch match = re.getMatch(text, index);
425             if (match == null)
426                 return -1;
427             if (isDelimited(text, match.getStartIndex(), match.toString().length(), mode))
428                 return match.getStartIndex();
429             index = match.getStartIndex() + 1;
430         }
431         return -1;
432     }
433
434     private static boolean isDelimited(String JavaDoc text, int index, int length, Mode mode)
435     {
436         final int before = index - 1;
437         if (before >= 0 && mode.isIdentifierPart(text.charAt(before)))
438             return false;
439         final int after = index + length;
440         if (after < text.length() && mode.isIdentifierPart(text.charAt(after)))
441             return false;
442         return true;
443     }
444
445     public void doShellCommandOnRegion()
446     {
447         if (!Editor.checkExperimental())
448             return;
449         final Editor editor = Editor.currentEditor();
450         if (!editor.checkReadOnly())
451             return;
452         if (editor.getMark() == null) {
453             MessageDialog.showMessageDialog(editor, "No region selected",
454                                             "Error");
455             return;
456         }
457         InputDialog d = new InputDialog(editor, "Command:",
458                                         "Do Shell Command On Region", null);
459         d.setHistory(new History("doShellCommandOnRegion"));
460         editor.centerDialog(d);
461         d.show();
462         String JavaDoc command = d.getInput();
463         if (command == null || command.length() == 0)
464             return;
465         editor.setWaitCursor();
466         Region r = new Region(editor);
467         // BUG! We should pass the contents of the region line by line in case
468
// it's big.
469
ShellCommand shellCommand =
470             new ShellCommand(command, null, r.toString());
471         shellCommand.run();
472         String JavaDoc output = shellCommand.getOutput();
473         if (output != null && output.length() > 0) {
474             CompoundEdit JavaDoc compoundEdit = editor.beginCompoundEdit();
475             editor.deleteRegion();
476             editor.addUndo(SimpleEdit.INSERT_STRING);
477             editor.insertStringInternal(output);
478             editor.moveCaretToDotCol();
479             editor.endCompoundEdit(compoundEdit);
480             if (editor.getFormatter().parseBuffer())
481                 editor.getBuffer().repaint();
482         }
483         editor.setDefaultCursor();
484     }
485 }
486
Popular Tags