mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
Fix #1450
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
package processing.app.syntax;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonathan Feinberg <jdf@pobox.com>
|
||||
*
|
||||
*/
|
||||
public class Brackets {
|
||||
private volatile List<Integer> offsets = null;
|
||||
|
||||
public void invalidate() {
|
||||
offsets = null;
|
||||
}
|
||||
|
||||
public int findMatchingBracket(final String text, final int pos) {
|
||||
if (offsets == null)
|
||||
parse(text);
|
||||
// find this bracket
|
||||
int p;
|
||||
for (p = 0; p < offsets.size(); p++)
|
||||
if (offsets.get(p) == pos)
|
||||
break;
|
||||
if (p == offsets.size()) {
|
||||
return -1;
|
||||
}
|
||||
final int direction;
|
||||
final char alpha = text.charAt(offsets.get(p));
|
||||
final char beta;
|
||||
switch (alpha) {
|
||||
case '(':
|
||||
beta = ')';
|
||||
direction = 1;
|
||||
break;
|
||||
case ')':
|
||||
beta = '(';
|
||||
direction = -1;
|
||||
break;
|
||||
case '[':
|
||||
beta = ']';
|
||||
direction = 1;
|
||||
break;
|
||||
case ']':
|
||||
beta = '[';
|
||||
direction = -1;
|
||||
break;
|
||||
case '{':
|
||||
beta = '}';
|
||||
direction = 1;
|
||||
break;
|
||||
case '}':
|
||||
beta = '{';
|
||||
direction = -1;
|
||||
break;
|
||||
default:
|
||||
System.err.println("Unexpected char " + alpha + " at position " + p);
|
||||
return -1;
|
||||
}
|
||||
int depth = 1;
|
||||
for (p += direction; p >= 0 && p < offsets.size(); p += direction) {
|
||||
final int offset = offsets.get(p);
|
||||
final char c = text.charAt(offset);
|
||||
if (c == alpha)
|
||||
depth++;
|
||||
else if (c == beta)
|
||||
depth--;
|
||||
if (depth == 0)
|
||||
return offset;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pos;
|
||||
|
||||
private void parse(final String text) {
|
||||
offsets = new ArrayList<Integer>();
|
||||
final int len = text.length();
|
||||
for (pos = 0; pos < len; pos++) {
|
||||
final char c = text.charAt(pos);
|
||||
if (c == '/' && (pos < len - 1)) {
|
||||
final char d = text.charAt(++pos);
|
||||
if (d == '/') {
|
||||
readComment(text);
|
||||
} else if (d == '*') {
|
||||
readMLComment(text);
|
||||
}
|
||||
} else if (c == '"' || c == '\'') {
|
||||
readString(text, c);
|
||||
} else if (c == '{' || c == '[' || c == '(' || c == '}' || c == ']'
|
||||
|| c == ')') {
|
||||
offsets.add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readString(final String text, final char q) {
|
||||
final int len = text.length();
|
||||
for (pos++; pos < len; pos++) {
|
||||
final char c = text.charAt(pos);
|
||||
if (c == q) {
|
||||
return;
|
||||
}
|
||||
if (c == '\\') {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readComment(final String text) {
|
||||
final int len = text.length();
|
||||
for (pos++; pos < len; pos++)
|
||||
if (text.charAt(pos) == '\n') {
|
||||
pos++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void readMLComment(final String text) {
|
||||
final int len = text.length();
|
||||
for (pos++; pos < len; pos++) {
|
||||
final char c = text.charAt(pos);
|
||||
if (c == '*' && (pos < len - 1)) {
|
||||
pos++;
|
||||
final char d = text.charAt(pos);
|
||||
if (d == '/') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,6 +129,8 @@ public class JEditTextArea extends JComponent
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Brackets bracketHelper = new Brackets();
|
||||
|
||||
/**
|
||||
* Inline Input Method Support for Japanese.
|
||||
@@ -1714,8 +1716,8 @@ public class JEditTextArea extends JComponent
|
||||
|
||||
try
|
||||
{
|
||||
int offset = TextUtilities.findMatchingBracket(
|
||||
document,newCaretPosition - 1);
|
||||
int offset = bracketHelper.findMatchingBracket(document.getText(0,
|
||||
document.getLength()), newCaretPosition - 1);
|
||||
if(offset != -1)
|
||||
{
|
||||
bracketLine = getLineOfOffset(offset);
|
||||
@@ -1733,6 +1735,8 @@ public class JEditTextArea extends JComponent
|
||||
|
||||
protected void documentChanged(DocumentEvent evt)
|
||||
{
|
||||
bracketHelper.invalidate();
|
||||
|
||||
DocumentEvent.ElementChange ch =
|
||||
evt.getChange(document.getDefaultRootElement());
|
||||
|
||||
@@ -2112,7 +2116,7 @@ public class JEditTextArea extends JComponent
|
||||
return;
|
||||
|
||||
try {
|
||||
int bracket = TextUtilities.findMatchingBracket(document,
|
||||
int bracket = bracketHelper.findMatchingBracket(document.getText(0, document.getLength()),
|
||||
Math.max(0,dot - 1));
|
||||
if (bracket != -1) {
|
||||
int mark = getMarkPosition();
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
package processing.app.syntax;
|
||||
|
||||
import javax.swing.text.*;
|
||||
|
||||
/**
|
||||
* Class with several utility functions used by the text area component.
|
||||
@@ -18,113 +17,6 @@ import javax.swing.text.*;
|
||||
*/
|
||||
public class TextUtilities
|
||||
{
|
||||
/**
|
||||
* Returns the offset of the bracket matching the one at the
|
||||
* specified offset of the document, or -1 if the bracket is
|
||||
* unmatched (or if the character is not a bracket).
|
||||
* @param doc The document
|
||||
* @param offset The offset
|
||||
* @exception BadLocationException If an out-of-bounds access
|
||||
* was attempted on the document text
|
||||
*/
|
||||
public static int findMatchingBracket(Document doc, int offset)
|
||||
throws BadLocationException
|
||||
{
|
||||
if(doc.getLength() == 0)
|
||||
return -1;
|
||||
char c = doc.getText(offset,1).charAt(0);
|
||||
char cprime; // c` - corresponding character
|
||||
boolean direction; // true = back, false = forward
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case '(': cprime = ')'; direction = false; break;
|
||||
case ')': cprime = '('; direction = true; break;
|
||||
case '[': cprime = ']'; direction = false; break;
|
||||
case ']': cprime = '['; direction = true; break;
|
||||
case '{': cprime = '}'; direction = false; break;
|
||||
case '}': cprime = '{'; direction = true; break;
|
||||
default: return -1;
|
||||
}
|
||||
|
||||
int count;
|
||||
|
||||
// How to merge these two cases is left as an exercise
|
||||
// for the reader.
|
||||
|
||||
// Go back or forward
|
||||
if(direction)
|
||||
{
|
||||
// Count is 1 initially because we have already
|
||||
// `found' one closing bracket
|
||||
count = 1;
|
||||
|
||||
// Get text[0,offset-1];
|
||||
String text = doc.getText(0,offset);
|
||||
|
||||
// Scan backwards
|
||||
for(int i = offset - 1; i >= 0; i--)
|
||||
{
|
||||
// If text[i] == c, we have found another
|
||||
// closing bracket, therefore we will need
|
||||
// two opening brackets to complete the
|
||||
// match.
|
||||
char x = text.charAt(i);
|
||||
if(x == c)
|
||||
count++;
|
||||
|
||||
// If text[i] == cprime, we have found a
|
||||
// opening bracket, so we return i if
|
||||
// --count == 0
|
||||
else if(x == cprime)
|
||||
{
|
||||
if(--count == 0)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Count is 1 initially because we have already
|
||||
// `found' one opening bracket
|
||||
count = 1;
|
||||
|
||||
// So we don't have to + 1 in every loop
|
||||
offset++;
|
||||
|
||||
// Number of characters to check
|
||||
int len = doc.getLength() - offset;
|
||||
|
||||
// Get text[offset+1,len];
|
||||
String text = doc.getText(offset,len);
|
||||
|
||||
// Scan forwards
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
// If text[i] == c, we have found another
|
||||
// opening bracket, therefore we will need
|
||||
// two closing brackets to complete the
|
||||
// match.
|
||||
char x = text.charAt(i);
|
||||
|
||||
if(x == c)
|
||||
count++;
|
||||
|
||||
// If text[i] == cprime, we have found an
|
||||
// closing bracket, so we return i if
|
||||
// --count == 0
|
||||
else if(x == cprime)
|
||||
{
|
||||
if(--count == 0)
|
||||
return i + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing found
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the start of the word at the specified position.
|
||||
* @param line The text
|
||||
|
||||
Reference in New Issue
Block a user