KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > gjt > sp > jedit > Registers


1 /*
2  * Registers.java - Register manager
3  * :tabSize=8:indentSize=8:noTabs=false:
4  * :folding=explicit:collapseFolds=1:
5  *
6  * Copyright (C) 1999, 2003 Slava Pestov
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */

22
23 package org.gjt.sp.jedit;
24
25 //{{{ Imports
26
import java.awt.datatransfer.*;
27 import java.awt.Toolkit JavaDoc;
28 import java.io.*;
29
30 import org.gjt.sp.jedit.buffer.JEditBuffer;
31 import org.gjt.sp.jedit.gui.HistoryModel;
32 import org.gjt.sp.jedit.textarea.TextArea;
33 import org.gjt.sp.jedit.textarea.Selection;
34 import org.gjt.sp.util.Log;
35 //}}}
36

37 /**
38  * jEdit's registers are an extension of the clipboard metaphor.<p>
39  *
40  * A {@link Registers.Register} is string of text indexed by a
41  * single character. Typically the text is taken from selected buffer text
42  * and the index character is a keyboard character selected by the user.<p>
43  *
44  * This class defines a number of static methods
45  * that give each register the properties of a virtual clipboard.<p>
46  *
47  * Two classes implement the {@link Registers.Register} interface. A
48  * {@link Registers.ClipboardRegister} is tied to the contents of the
49  * system clipboard. jEdit assigns a
50  * {@link Registers.ClipboardRegister} to the register indexed under
51  * the character <code>$</code>. A
52  * {@link Registers.StringRegister} is created for registers assigned
53  * by the user. In addition, jEdit assigns <code>%</code> to
54  * the last text segment selected in the text area. On Windows this is a
55  * {@link Registers.StringRegister}, on Unix under Java 2 version 1.4, a
56  * {@link Registers.ClipboardRegister}.
57  *
58  * @author Slava Pestov
59  * @author John Gellene (API documentation)
60  * @version $Id: Registers.java 7367 2006-10-08 21:08:04Z kpouer $
61  */

62 public class Registers
63 {
64     //{{{ copy() method
65
/**
66      * Copies the text selected in the text area into the specified register.
67      * This will replace the existing contents of the designated register.
68      *
69      * @param textArea The text area
70      * @param register The register
71      * @since jEdit 2.7pre2
72      */

73     public static void copy(TextArea textArea, char register)
74     {
75         String JavaDoc selection = textArea.getSelectedText();
76         if(selection == null)
77             return;
78
79         setRegister(register,selection);
80         HistoryModel.getModel("clipboard").addItem(selection);
81
82     } //}}}
83

84     //{{{ cut() method
85
/**
86      * Copies the text selected in the text area into the specified
87      * register, and then removes it from the buffer.
88      *
89      * @param textArea The text area
90      * @param register The register
91      * @since jEdit 2.7pre2
92      */

93     public static void cut(TextArea textArea, char register)
94     {
95         if(textArea.isEditable())
96         {
97             String JavaDoc selection = textArea.getSelectedText();
98             if(selection == null)
99                 return;
100
101             setRegister(register,selection);
102             HistoryModel.getModel("clipboard").addItem(selection);
103
104             textArea.setSelectedText("");
105         }
106         else
107             textArea.getToolkit().beep();
108     } //}}}
109

110     //{{{ append() method
111
/**
112      * Appends the text selected in the text area to the specified register,
113      * with a newline between the old and new text.
114      * @param textArea The text area
115      * @param register The register
116      */

117     public static void append(TextArea textArea, char register)
118     {
119         append(textArea,register,"\n",false);
120     } //}}}
121

122     //{{{ append() method
123
/**
124      * Appends the text selected in the text area to the specified register.
125      * @param textArea The text area
126      * @param register The register
127      * @param separator The separator to insert between the old and new text
128      */

129     public static void append(TextArea textArea, char register,
130         String JavaDoc separator)
131     {
132         append(textArea,register,separator,false);
133     } //}}}
134

135     //{{{ append() method
136
/**
137      * Appends the text selected in the text area to the specified register.
138      * @param textArea The text area
139      * @param register The register
140      * @param separator The text to insert between the old and new text
141      * @param cut Should the current selection be removed?
142      * @since jEdit 3.2pre1
143      */

144     public static void append(TextArea textArea, char register,
145         String JavaDoc separator, boolean cut)
146     {
147         if(cut && !textArea.isEditable())
148         {
149             textArea.getToolkit().beep();
150             return;
151         }
152
153         String JavaDoc selection = textArea.getSelectedText();
154         if(selection == null)
155             return;
156
157         Register reg = getRegister(register);
158
159         if(reg != null)
160         {
161             String JavaDoc registerContents = reg.toString();
162             if(registerContents != null)
163             {
164                 if(registerContents.endsWith(separator))
165                     selection = registerContents + selection;
166                 else
167                     selection = registerContents + separator + selection;
168             }
169         }
170
171         setRegister(register,selection);
172         HistoryModel.getModel("clipboard").addItem(selection);
173
174         if(cut)
175             textArea.setSelectedText("");
176     } //}}}
177

178     //{{{ paste() method
179
/**
180      * Insets the contents of the specified register into the text area.
181      * @param textArea The text area
182      * @param register The register
183      * @since jEdit 2.7pre2
184      */

185     public static void paste(TextArea textArea, char register)
186     {
187         paste(textArea,register,false);
188     } //}}}
189

190     //{{{ paste() method
191
/**
192      * Inserts the contents of the specified register into the text area.
193      * @param textArea The text area
194      * @param register The register
195      * @param vertical Vertical (columnar) paste
196      * @since jEdit 4.1pre1
197      */

198     public static void paste(TextArea textArea, char register,
199         boolean vertical)
200     {
201         if(!textArea.isEditable())
202         {
203             textArea.getToolkit().beep();
204             return;
205         }
206
207         Register reg = getRegister(register);
208
209         if(reg == null)
210         {
211             textArea.getToolkit().beep();
212             return;
213         }
214
215         String JavaDoc selection = reg.toString();
216         if(selection == null)
217         {
218             textArea.getToolkit().beep();
219             return;
220         }
221         JEditBuffer buffer = textArea.getBuffer();
222         try
223         {
224             buffer.beginCompoundEdit();
225
226             /* vertical paste */
227             if(vertical && textArea.getSelectionCount() == 0)
228             {
229                 int caret = textArea.getCaretPosition();
230                 int caretLine = textArea.getCaretLine();
231                 Selection.Rect rect = new Selection.Rect(
232                     caretLine,caret,caretLine,caret);
233                 textArea.setSelectedText(rect,selection);
234                 caretLine = textArea.getCaretLine();
235
236                 if(caretLine != textArea.getLineCount() - 1)
237                 {
238                     int startColumn = rect.getStartColumn(
239                         buffer);
240                     int offset = buffer
241                         .getOffsetOfVirtualColumn(
242                         caretLine + 1,startColumn,null);
243                     if(offset == -1)
244                     {
245                         buffer.insertAtColumn(caretLine + 1,startColumn,"");
246                         textArea.setCaretPosition(
247                             buffer.getLineEndOffset(
248                             caretLine + 1) - 1);
249                     }
250                     else
251                     {
252                         textArea.setCaretPosition(
253                             buffer.getLineStartOffset(
254                             caretLine + 1) + offset);
255                     }
256                 }
257             }
258             else /* Regular paste */
259             {
260                 textArea.replaceSelection(selection);
261             }
262         }
263         finally {
264             buffer.endCompoundEdit();
265         }
266         HistoryModel.getModel("clipboard").addItem(selection);
267     } //}}}
268

269     //{{{ getRegister() method
270
/**
271      * Returns the specified register.
272      * @param name The name
273      */

274     public static Register getRegister(char name)
275     {
276         if(name != '$' && name != '%')
277         {
278             if(!loaded)
279                 loadRegisters();
280         }
281
282         if(registers == null || name >= registers.length)
283             return null;
284         else
285             return registers[name];
286     } //}}}
287

288     //{{{ setRegister() method
289
/**
290      * Sets the specified register.
291      * @param name The name
292      * @param newRegister The new value
293      */

294     public static void setRegister(char name, Register newRegister)
295     {
296         touchRegister(name);
297
298         if(name >= registers.length)
299         {
300             Register[] newRegisters = new Register[
301                 Math.min(1<<16, name<<1)];
302             System.arraycopy(registers,0,newRegisters,0,
303                 registers.length);
304             registers = newRegisters;
305         }
306
307         registers[name] = newRegister;
308         if (listener != null)
309             listener.registerChanged(name);
310     } //}}}
311

312     //{{{ setRegister() method
313
/**
314      * Sets the specified register.
315      * @param name The name
316      * @param value The new value
317      */

318     public static void setRegister(char name, String JavaDoc value)
319     {
320         touchRegister(name);
321         Register register = getRegister(name);
322         if(register != null)
323         {
324             register.setValue(value);
325             if (listener != null)
326                 listener.registerChanged(name);
327         }
328         else
329             setRegister(name,new StringRegister(value));
330     } //}}}
331

332     //{{{ clearRegister() method
333
/**
334      * Sets the value of the specified register to <code>null</code>.
335      * @param name The register name
336      */

337     public static void clearRegister(char name)
338     {
339         if(name >= registers.length)
340             return;
341
342         Register register = registers[name];
343         if(name == '$' || name == '%')
344             register.setValue("");
345         else
346         {
347             registers[name] = null;
348             modified = true;
349         }
350     } //}}}
351

352     //{{{ getRegisters() method
353
/**
354      * Returns an array of all available registers. Some of the elements
355      * of this array might be <code>null</code>.
356      */

357     public static Register[] getRegisters()
358     {
359         if(!loaded)
360             loadRegisters();
361         return registers;
362     } //}}}
363

364     //{{{ getRegisterStatusPrompt() method
365
/**
366      * Returns the status prompt for the given register action. Only
367      * intended to be called from <code>actions.xml</code>.
368      * @since jEdit 4.2pre2
369      */

370     public static String JavaDoc getRegisterStatusPrompt(String JavaDoc action)
371     {
372         String JavaDoc registerNameString = getRegisterNameString();
373         return jEdit.getProperty("view.status." + action,
374             new String JavaDoc[] {registerNameString == null ?
375                       jEdit.getProperty("view.status.no-registers") :
376                       registerNameString});
377     } //}}}
378

379     //{{{ getRegisterNameString() method
380
/**
381      * Returns a string of all defined registers, used by the status bar
382      * (eg, "a b $ % ^").
383      * @since jEdit 4.2pre2
384      */

385     public static String JavaDoc getRegisterNameString()
386     {
387         if(!loaded)
388             loadRegisters();
389
390         StringBuilder JavaDoc buf = new StringBuilder JavaDoc(registers.length << 1);
391         for(int i = 0; i < registers.length; i++)
392         {
393             if(registers[i] != null)
394             {
395                 if(buf.length() != 0)
396                     buf.append(' ');
397                 buf.append((char)i);
398             }
399         }
400
401         if(buf.length() == 0)
402             return null;
403         else
404             return buf.toString();
405     } //}}}
406

407     //{{{ saveRegisters() method
408
public static void saveRegisters()
409     {
410         if(!loaded || !modified)
411             return;
412
413         if (saver != null)
414         {
415             saver.saveRegisters();
416             modified = false;
417         }
418     } //}}}
419

420     //{{{ setListener() method
421
public static void setListener(RegistersListener listener)
422     {
423         Registers.listener = listener;
424     } //}}}
425

426     //{{{ setSaver() method
427
public static void setSaver(RegisterSaver saver)
428     {
429         Registers.saver = saver;
430     } //}}}
431

432     //{{{ isLoading() method
433
public static boolean isLoading()
434     {
435         return loading;
436     } //}}}
437

438     //{{{ setLoading() method
439
public static void setLoading(boolean loading)
440     {
441         Registers.loading = loading;
442     } //}}}
443

444     //{{{ Private members
445
private static Register[] registers;
446     private static boolean loaded, loading;
447     private static RegisterSaver saver;
448     private static RegistersListener listener;
449     /**
450      * Flag that tell if a register has been modified (except for '%' and '$' registers that aren't
451      * saved to the xml file).
452      */

453     private static boolean modified;
454
455     private Registers() {}
456
457     static
458     {
459         registers = new Register[256];
460         Toolkit JavaDoc toolkit = Toolkit.getDefaultToolkit();
461         registers['$'] = new ClipboardRegister(
462             toolkit.getSystemClipboard());
463         Clipboard selection = toolkit.getSystemSelection();
464         if(selection != null)
465             registers['%'] = new ClipboardRegister(selection);
466     }
467
468     //{{{ touchRegister() method
469
private static void touchRegister(char name)
470     {
471         if(name == '%' || name == '$')
472             return;
473
474         if(!loaded)
475             loadRegisters();
476
477         if(!loading)
478             modified = true;
479     } //}}}
480

481     //{{{ loadRegisters() method
482
private static void loadRegisters()
483     {
484         if (saver != null)
485         {
486             loaded = true;
487             saver.loadRegisters();
488         }
489     } //}}}
490

491     //}}}
492

493     //{{{ Inner classes
494

495     //{{{ Register interface
496
/**
497      * A register.
498      */

499     public interface Register
500     {
501         /**
502          * Converts to a string.
503          */

504         String JavaDoc toString();
505
506         /**
507          * Sets the register contents.
508          */

509         void setValue(String JavaDoc value);
510     } //}}}
511

512     //{{{ ClipboardRegister class
513
/**
514      * A clipboard register. Register "$" should always be an
515      * instance of this.
516      */

517     public static class ClipboardRegister implements Register
518     {
519         Clipboard clipboard;
520
521         public ClipboardRegister(Clipboard clipboard)
522         {
523             this.clipboard = clipboard;
524         }
525
526         /**
527          * Sets the clipboard contents.
528          */

529         public void setValue(String JavaDoc value)
530         {
531             StringSelection selection = new StringSelection(value);
532             clipboard.setContents(selection,null);
533         }
534
535         /**
536          * Returns the clipboard contents.
537          */

538         public String JavaDoc toString()
539         {
540             try
541             {
542
543                 if (false) {
544                     /*
545                         This is to debug clipboard problems.
546
547                         Apparently, jEdit is unable to copy text from clipbard into the current
548                         text buffer if the clipboard was filles using the command
549                             echo test | xselection CLIPBOARD -
550                         under Linux. However, it seems that Java does not offer any
551                         data flavor for this clipboard content (under J2RE 1.5.0_06-b05)
552                         Thus, copying from clipboard seems to be plainly impossible.
553                     */

554                     Log.log(Log.DEBUG,this,"clipboard.getContents(this)="+clipboard.getContents(this)+'.');
555                     debugListDataFlavors(clipboard.getContents(this));
556                 }
557
558                 String JavaDoc selection = (String JavaDoc)clipboard
559                     .getContents(this).getTransferData(
560                     DataFlavor.stringFlavor);
561
562                 boolean trailingEOL = selection.endsWith("\n")
563                     || selection.endsWith(System.getProperty(
564                     "line.separator"));
565
566                 // Some Java versions return the clipboard
567
// contents using the native line separator,
568
// so have to convert it here
569
BufferedReader in = new BufferedReader(
570                     new StringReader(selection));
571                 StringBuilder JavaDoc buf = new StringBuilder JavaDoc();
572                 String JavaDoc line;
573                 while((line = in.readLine()) != null)
574                 {
575                     // broken Eclipse workaround!
576
// 24 Febuary 2004
577
if(line.endsWith("\0"))
578                     {
579                         line = line.substring(0,
580                             line.length() - 1);
581                     }
582                     buf.append(line);
583                     buf.append('\n');
584                 }
585                 // remove trailing \n
586
if(!trailingEOL && buf.length() != 0)
587                     buf.setLength(buf.length() - 1);
588                 return buf.toString();
589             }
590             catch(Exception JavaDoc e)
591             {
592                 Log.log(Log.NOTICE,this,e);
593                 return null;
594             }
595         }
596     } //}}}
597

598     protected static void debugListDataFlavors(Transferable transferable) {
599         DataFlavor[] dataFlavors = transferable.getTransferDataFlavors();
600
601         for (int i = 0;i<dataFlavors.length;i++) {
602             DataFlavor dataFlavor = dataFlavors[i];
603
604             Log.log(Log.DEBUG,Registers.class,"debugListDataFlavors(): dataFlavor="+dataFlavor+'.');
605
606         }
607
608         if (dataFlavors.length==0) {
609             Log.log(Log.DEBUG,Registers.class,"debugListDataFlavors(): no dataFlavor supported.");
610         }
611     }
612
613     //{{{ StringRegister class
614
/**
615      * Register that stores a string.
616      */

617     public static class StringRegister implements Register
618     {
619         private String JavaDoc value;
620
621         /**
622          * Creates a new string register.
623          * @param value The contents
624          */

625         public StringRegister(String JavaDoc value)
626         {
627             this.value = value;
628         }
629
630         /**
631          * Sets the register contents.
632          */

633         public void setValue(String JavaDoc value)
634         {
635             this.value = value;
636         }
637
638         /**
639          * Converts to a string.
640          */

641         public String JavaDoc toString()
642         {
643             return value;
644         }
645
646         /**
647          * Called when this register is no longer available. This
648          * implementation does nothing.
649          */

650         public void dispose() {}
651     } //}}}
652

653     //}}}
654
}
655
Popular Tags