1 package gnu.jemacs.swing;
2 import gnu.jemacs.buffer.*;
3 import javax.swing.text.*;
4 import javax.swing.undo.*;
5 import gnu.lists.*;
6 
7 /** A Content class that supports Emacs-style Markers.
8  * The standard GapContent is close, but unfortunately it only
9  * supports inserting *before* marks, which is not the Emacs default.
10  * This provides a superset of the Position functionality (except for undo).
11  */
12 
13 public class BufferContent extends gnu.kawa.swingviews.SwingContent
14 {
BufferContent()15   public BufferContent()
16   {
17     this(100);
18   }
19 
BufferContent(int initialSize)20   public BufferContent(int initialSize)
21   {
22     super(initialSize);
23   }
24 
indexOf(char[] buffer, int start, int limit, char ch)25   public static int indexOf(char[] buffer, int start, int limit, char ch)
26   {
27     for (int i = start; i < limit; i++)
28       {
29         if (buffer[i] == ch)
30           return i;
31       }
32     return -1;
33   }
34 
35   /** Search for the last occurrence of a character
36    * in buffer[limit..start]. */
lastIndexOf(char[] buffer, int start, int limit, char ch)37   public static int lastIndexOf(char[] buffer, int start, int limit, char ch)
38   {
39     for (int i = start; i >= limit; i--)
40       {
41         if (buffer[i] == ch)
42           return i;
43       }
44     return -1;
45   }
46 
47     /** Search in BUF for COUNT instances of the character TARGET between START and END.
48      * If COUNT is positive, search forwards; requires {@code END >= START}.
49      * If COUNT is negative, search backwards for the -COUNTth instance;
50      *   requires {@code END <= START}.
51      * If COUNT is zero, do anything you please; run rogue, for all I care.
52      * START and END are both 0-origin.
53    *
54    * If we find COUNT instances, SHORTAGE is zero, and return the
55    * (0-origin) position after the COUNTth match.  Note that for reverse motion
56    * this is not the same as the usual convention for Emacs motion commands.
57 
58    * If we don't find COUNT instances before reaching END, set SHORTAGE
59    * to the number of TARGETs left unfound, and return {@code (shortage<<32|END)}.
60    * @return {@code(SHORTAGE<<32|POS)}
61    */
scan(char target, int start, int end, int count, boolean allowQuit)62     public final long scan(char target, int start, int end,
63                            int count, boolean allowQuit) {
64         CharBuffer b = buffer;
65         if (count > 0) {
66             while (start < end && count > 0) {
67                 char[] data = b.getBuffer();
68                 long result = b.getSegment(start);
69                 int where = (int) result;
70                 int size = (int) (result >> 32);
71                 if (size > (end-start))
72                     size = end-start;
73                 if (allowQuit) {
74                     if (size > 10000)
75                         size = 10000;
76                     Signal.checkQuit();
77                 }
78                 int i = indexOf(data, where, where+size, target);
79                 if (i >= 0) {
80                     count--;
81                     start += i + 1;
82                 } else
83                     start += size;
84             }
85             return ((long) count << 32) | start;
86         } else {
87             int sinceCheck = 0;
88             while (start > end && count < 0) {
89                 char ch = b.charAt(--start);
90                 if (ch == target) {
91                     count++;
92                 }
93                 if (allowQuit && ++sinceCheck > 10000) {
94                     Signal.checkQuit();
95                     sinceCheck = 0;
96                 }
97             }
98 
99             if (count != 0)
100                 return ((long) (- count) << 32) | end;
101             else {
102                 // We found the character we were looking for; we have to
103                 // return the position *after* it due to the strange way
104                 // that the return value is defined.
105                 return start + 1;
106             }
107         }
108     }
109 }
110