// Filename: SyntaxDocument.java // http://forums.sun.com/thread.jspa?threadID=743407&messageID=9497681 // http://www.dound.com/src/MultiSyntaxDocument.java /** * (C) camickr (primary author; java sun forums user) * (C) David Underhill * (C) 2009 University of Waikato, Hamilton, New Zealand */ package weka.gui.scripting; import weka.gui.visualize.VisualizeUtils; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Toolkit; import java.util.HashMap; import java.util.Properties; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultEditorKit; import javax.swing.text.DefaultStyledDocument; import javax.swing.text.Element; import javax.swing.text.MutableAttributeSet; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.TabSet; import javax.swing.text.TabStop; /** * Highlights syntax in a DefaultStyledDocument. Allows any number of keywords * to be formatted in any number of user-defined styles. * * @author camickr (primary author; java sun forums user) * @author David Underhill * @author FracPete (fracpete at waikato dot ac dot nz) - use of a properties file to setup syntax highlighting instead of hard-coded */ public class SyntaxDocument extends DefaultStyledDocument { /** for serialization. */ protected static final long serialVersionUID = -3642426465631271381L; /** the maximum number of tabs. */ public static final int MAX_TABS = 35; /** the font family. */ public static final String DEFAULT_FONT_FAMILY = "monospaced"; /** the font size. */ public static final int DEFAULT_FONT_SIZE = 12; /** the attribute set for normal code. */ public static final SimpleAttributeSet DEFAULT_NORMAL; /** the attribute set for comments. */ public static final SimpleAttributeSet DEFAULT_COMMENT; /** the attribute set for strings. */ public static final SimpleAttributeSet DEFAULT_STRING; /** the attribute set for keywords. */ public static final SimpleAttributeSet DEFAULT_KEYWORD; static { DEFAULT_NORMAL = new SimpleAttributeSet(); StyleConstants.setForeground(DEFAULT_NORMAL, Color.BLACK); StyleConstants.setFontFamily(DEFAULT_NORMAL, DEFAULT_FONT_FAMILY); StyleConstants.setFontSize(DEFAULT_NORMAL, DEFAULT_FONT_SIZE); DEFAULT_COMMENT = new SimpleAttributeSet(); StyleConstants.setForeground(DEFAULT_COMMENT, Color.GRAY); StyleConstants.setFontFamily(DEFAULT_COMMENT, DEFAULT_FONT_FAMILY); StyleConstants.setFontSize(DEFAULT_COMMENT, DEFAULT_FONT_SIZE); DEFAULT_STRING = new SimpleAttributeSet(); StyleConstants.setForeground(DEFAULT_STRING, Color.RED); StyleConstants.setFontFamily(DEFAULT_STRING, DEFAULT_FONT_FAMILY); StyleConstants.setFontSize(DEFAULT_STRING, DEFAULT_FONT_SIZE); // default style for new keyword types DEFAULT_KEYWORD = new SimpleAttributeSet(); StyleConstants.setForeground(DEFAULT_KEYWORD, Color.BLUE); StyleConstants.setBold(DEFAULT_KEYWORD, false); StyleConstants.setFontFamily(DEFAULT_KEYWORD, DEFAULT_FONT_FAMILY); StyleConstants.setFontSize(DEFAULT_KEYWORD, DEFAULT_FONT_SIZE); } /** * The attribute type. */ public enum ATTR_TYPE { /** normal string. */ Normal, /** a comment. */ Comment, /** a quoted string. */ Quote; } /** the document. */ protected DefaultStyledDocument m_Self; /** the root element. */ protected Element m_RootElement; /** whether we're currently in a multi-line comment. */ protected boolean m_InsideMultiLineComment; /** the keywords. */ protected HashMap m_Keywords; /** the delimiters. */ protected String m_Delimiters; /** the quote delimiter. */ protected String m_QuoteDelimiters; /** the quote escape. */ protected String m_QuoteEscape; /** the multi-line comment start. */ protected String m_MultiLineCommentStart; /** the multi-line comment end. */ protected String m_MultiLineCommentEnd; /** the single-line comment start. */ protected String m_SingleLineCommentStart; /** the start of a block. */ protected String m_BlockStart; /** the end of a block. */ protected String m_BlockEnd; /** the font size. */ protected int m_FontSize; /** the font name. */ protected String m_FontName; /** the background color. */ protected Color m_BackgroundColor; /** the number of spaces used for indentation. */ protected String m_Indentation; /** whether to add matching brackets. */ protected boolean m_AddMatchingEndBlocks; /** whether to use blanks instead of tabs. */ protected boolean m_UseBlanks; /** whether multi-line comments are enabled. */ protected boolean m_MultiLineComment; /** whether keywords are case-sensitive. */ protected boolean m_CaseSensitive; /** * Initializes the document. * * @param props the properties to obtain the setup from */ public SyntaxDocument(Properties props) { m_Self = this; m_RootElement = m_Self.getDefaultRootElement(); m_Keywords = new HashMap(); m_FontSize = DEFAULT_FONT_SIZE; m_FontName = DEFAULT_FONT_FAMILY; putProperty(DefaultEditorKit.EndOfLineStringProperty, "\n"); setup(props); } /** * Sets up the document according to the properties. * * @param props the properties to use */ protected void setup(Properties props) { setDelimiters(props.getProperty("Delimiters", ";:{}()[]+-/%<=>!&|^~*")); setQuoteDelimiters(props.getProperty("QuoteDelimiters", "\"\'")); setQuoteEscape(props.getProperty("QuoteEscape", "\\")); setSingleLineCommentStart(props.getProperty("SingleLineCommentStart", "//")); setMultiLineComment(props.getProperty("MultiLineComment", "false").equals("true")); setMultiLineCommentStart(props.getProperty("MultiLineCommentStart", "/*")); setMultiLineCommentEnd(props.getProperty("MultiLineCommentEnd", "*/")); setBlockStart(props.getProperty("BlockStart", "{")); setBlockEnd(props.getProperty("BlockEnd", "}")); setAddMatchingEndBlocks(props.getProperty("AddMatchingBlockEnd", "false").equals("true")); setUseBlanks(props.getProperty("UseBlanks", "false").equals("true")); setCaseSensitive(props.getProperty("CaseSensitive", "true").equals("true")); addKeywords(props.getProperty("Keywords", "").trim().replaceAll(" ", "").split(","), DEFAULT_KEYWORD); setTabs(Integer.parseInt(props.getProperty("Tabs", "2"))); setAttributeColor(DEFAULT_NORMAL, VisualizeUtils.processColour(props.getProperty("ForegroundColor", "black"), Color.BLACK)); setAttributeColor(DEFAULT_COMMENT, VisualizeUtils.processColour(props.getProperty("CommentColor", "gray"), Color.GRAY)); setAttributeColor(DEFAULT_STRING, VisualizeUtils.processColour(props.getProperty("StringColor", "red"), Color.RED)); setAttributeColor(DEFAULT_KEYWORD, VisualizeUtils.processColour(props.getProperty("KeywordColor", "blue"), Color.BLUE)); setBackgroundColor(VisualizeUtils.processColour(props.getProperty("BackgroundColor", "white"), Color.WHITE)); setFontName(props.getProperty("FontName", "monospaced")); setFontSize(Integer.parseInt(props.getProperty("FontSize", "12"))); setIndentationSize(Integer.parseInt(props.getProperty("Indentation", "2"))); } /** * Sets the font of the specified attribute. * * @param attr * the attribute to apply this font to (normal, comment, string) * @param style * font style (Font.BOLD, Font.ITALIC, Font.PLAIN) */ public void setAttributeFont(ATTR_TYPE attr, int style) { Font f = new Font(m_FontName, style, m_FontSize); if (attr == ATTR_TYPE.Comment) setAttributeFont(DEFAULT_COMMENT, f); else if (attr == ATTR_TYPE.Quote) setAttributeFont(DEFAULT_STRING, f); else setAttributeFont(DEFAULT_NORMAL, f); } /** * Sets the font of the specified attribute. * * @param attr * attribute to apply this font to * @param f * the font to use */ public static void setAttributeFont(MutableAttributeSet attr, Font f) { StyleConstants.setBold(attr, f.isBold()); StyleConstants.setItalic(attr, f.isItalic()); StyleConstants.setFontFamily(attr, f.getFamily()); StyleConstants.setFontSize(attr, f.getSize()); } /** * Sets the foreground (font) color of the specified attribute. * * @param attr * the attribute to apply this font to (normal, comment, string) * @param c * the color to use */ public void setAttributeColor(ATTR_TYPE attr, Color c) { if (attr == ATTR_TYPE.Comment) setAttributeColor(DEFAULT_COMMENT, c); else if (attr == ATTR_TYPE.Quote) setAttributeColor(DEFAULT_STRING, c); else setAttributeColor(DEFAULT_NORMAL, c); } /** * Sets the foreground (font) color of the specified attribute. * * @param attr * attribute to apply this color to * @param c * the color to use */ public static void setAttributeColor(MutableAttributeSet attr, Color c) { StyleConstants.setForeground(attr, c); } /** * Associates the keywords with a particular formatting style. * * @param keywords * the tokens or words to format * @param attr * how to format the keywords */ public void addKeywords(String[] keywords, MutableAttributeSet attr) { int i; for (i = 0; i < keywords.length; i++) addKeyword(keywords[i], attr); } /** * Associates a keyword with a particular formatting style. * * @param keyword * the token or word to format * @param attr * how to format keyword */ public void addKeyword(String keyword, MutableAttributeSet attr) { if (m_CaseSensitive) m_Keywords.put(keyword, attr); else m_Keywords.put(keyword.toLowerCase(), attr); } /** * Gets the formatting for a keyword. * * @param keyword * the token or word to stop formatting * * @return how keyword is formatted, or null if no formatting is applied to it */ public MutableAttributeSet getKeywordFormatting(String keyword) { if (m_CaseSensitive) return m_Keywords.get(keyword); else return m_Keywords.get(keyword.toLowerCase()); } /** * Removes an association between a keyword with a particular formatting style. * * @param keyword * the token or word to stop formatting */ public void removeKeyword(String keyword) { if (m_CaseSensitive) m_Keywords.remove(keyword); else m_Keywords.remove(keyword.toLowerCase()); } /** * sets the number of characters per tab. * * @param charactersPerTab * the characters per tab */ public void setTabs(int charactersPerTab) { Font f = new Font(m_FontName, Font.PLAIN, m_FontSize); FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(f); int charWidth = fm.charWidth('w'); int tabWidth = charWidth * charactersPerTab; TabStop[] tabs = new TabStop[MAX_TABS]; for (int j = 0; j < tabs.length; j++) tabs[j] = new TabStop((j+1) * tabWidth); TabSet tabSet = new TabSet(tabs); SimpleAttributeSet attributes = new SimpleAttributeSet(); StyleConstants.setTabSet(attributes, tabSet); int length = getLength(); setParagraphAttributes(0, length, attributes, false); } /** * Override to apply syntax highlighting after the document has been updated. * * @param offset * the offset * @param str * the string to insert * @param a * the attribute set, can be null * @throws BadLocationException * if offset is invalid */ public void insertString(int offset, String str, AttributeSet a) throws BadLocationException { if (m_AddMatchingEndBlocks && (m_BlockStart.length() > 0) && str.equals(m_BlockStart)) str = addMatchingBlockEnd(offset); else if (m_UseBlanks && str.equals("\t")) str = m_Indentation; super.insertString(offset, str, a); processChangedLines(offset, str.length()); } /** * Applies syntax highlighting after the document has been updated. * * @param offset * the offset of the deletion * @param length * the length of the deletion * @throws BadLocationException * if offsets are invalid */ public void remove(int offset, int length) throws BadLocationException { super.remove(offset, length); processChangedLines(offset, 0); } /** * Determine how many lines have been changed, then apply highlighting to each * line. * * @param offset * the offset of the changed lines * @param length * the length of the change * @throws BadLocationException * if offset is invalid */ public void processChangedLines(int offset, int length) throws BadLocationException { String content = m_Self.getText(0, m_Self.getLength()); // The lines affected by the latest document update int startLine = m_RootElement.getElementIndex(offset); int endLine = m_RootElement.getElementIndex(offset + length); // Make sure all comment lines prior to the start line are commented // and determine if the start line is still in a multi line comment if (getMultiLineComment()) setInsideMultiLineComment(commentLinesBefore(content, startLine)); // Do the actual highlighting for (int i = startLine; i <= endLine; i++) { applyHighlighting(content, i); } // Resolve highlighting to the next end multi line delimiter if (isMultiLineComment()) commentLinesAfter(content, endLine); else highlightLinesAfter(content, endLine); } /** * Highlight lines when a multi line comment is still 'open' (ie. matching end * delimiter has not yet been encountered). * * @param content * the content to check * @param line * the line number * @return * true if there are comment lines before */ protected boolean commentLinesBefore(String content, int line) { int offset = m_RootElement.getElement(line).getStartOffset(); // Start of comment not found, nothing to do int startDelimiter = -1; if (getMultiLineComment()) startDelimiter = lastIndexOf(content, getMultiLineCommentStart(), offset - 2); if (startDelimiter < 0) return false; // Matching start/end of comment found, nothing to do int endDelimiter = indexOf(content, getMultiLineCommentEnd(), startDelimiter); if (endDelimiter < offset & endDelimiter != -1) return false; // End of comment not found, highlight the lines m_Self.setCharacterAttributes(startDelimiter, offset - startDelimiter + 1, DEFAULT_COMMENT, false); return true; } /** * Highlight comment lines to matching end delimiter. * * @param content * the content to parse * @param line * the line number */ protected void commentLinesAfter(String content, int line) { int offset = m_RootElement.getElement(line).getEndOffset(); // End of comment not found, nothing to do int endDelimiter = -1; if (getMultiLineComment()) endDelimiter = indexOf(content, getMultiLineCommentEnd(), offset); if (endDelimiter < 0) return; // Matching start/end of comment found, comment the lines int startDelimiter = lastIndexOf(content, getMultiLineCommentStart(), endDelimiter); if (startDelimiter < 0 || startDelimiter <= offset) { m_Self.setCharacterAttributes(offset, endDelimiter - offset + 1, DEFAULT_COMMENT, false); } } /** * Highlight lines to start or end delimiter. * * @param content * the content to parse * @param line * the line number * @throws BadLocationException * if offsets are wrong */ protected void highlightLinesAfter(String content, int line) throws BadLocationException { int offset = m_RootElement.getElement(line).getEndOffset(); // Start/End delimiter not found, nothing to do int startDelimiter = -1; int endDelimiter = -1; if (getMultiLineComment()) { startDelimiter = indexOf(content, getMultiLineCommentStart(), offset); endDelimiter = indexOf(content, getMultiLineCommentEnd(), offset); } if (startDelimiter < 0) startDelimiter = content.length(); if (endDelimiter < 0) endDelimiter = content.length(); int delimiter = Math.min(startDelimiter, endDelimiter); if (delimiter < offset) return; // Start/End delimiter found, reapply highlighting int endLine = m_RootElement.getElementIndex(delimiter); for (int i = line + 1; i < endLine; i++) { Element branch = m_RootElement.getElement(i); Element leaf = m_Self.getCharacterElement(branch.getStartOffset()); AttributeSet as = leaf.getAttributes(); if (as.isEqual(DEFAULT_COMMENT)) applyHighlighting(content, i); } } /** * Parse the line to determine the appropriate highlighting. * * @param content * the content to parse * @param line * the line number * @throws BadLocationException * if offsets are invalid */ protected void applyHighlighting(String content, int line) throws BadLocationException { int startOffset = m_RootElement.getElement(line).getStartOffset(); int endOffset = m_RootElement.getElement(line).getEndOffset() - 1; int lineLength = endOffset - startOffset; int contentLength = content.length(); if (endOffset >= contentLength) endOffset = contentLength - 1; // check for multi line comments // (always set the comment attribute for the entire line) if (getMultiLineComment()) { if (endingMultiLineComment(content, startOffset, endOffset) || isMultiLineComment() || startingMultiLineComment(content, startOffset, endOffset)) { m_Self.setCharacterAttributes(startOffset, endOffset - startOffset + 1, DEFAULT_COMMENT, false); return; } } // set normal attributes for the line m_Self.setCharacterAttributes(startOffset, lineLength, DEFAULT_NORMAL, true); // check for single line comment int index = content.indexOf(getSingleLineCommentStart(), startOffset); if ((index > -1) && (index < endOffset)) { m_Self.setCharacterAttributes(index, endOffset - index + 1, DEFAULT_COMMENT, false); endOffset = index - 1; } // check for tokens checkForTokens(content, startOffset, endOffset); } /** * Does this line contain the start of a multi-line comment. * * @param content * the content to search * @param startOffset * the start of the search * @param endOffset * the end of the search * @return * true if it contains the start delimiter * @throws BadLocationException * if offsets are invalid */ protected boolean startingMultiLineComment(String content, int startOffset, int endOffset) throws BadLocationException { if (!getMultiLineComment()) return false; int index = indexOf(content, getMultiLineCommentStart(), startOffset); if ((index < 0) || (index > endOffset)) return false; else { setInsideMultiLineComment(true); return true; } } /** * Does this line contain the end delimiter of a multi-line comment. * * @param content * the content to search * @param startOffset * the start of the search * @param endOffset * the end of the search * @return * true if the line contains the end delimiter * @throws BadLocationException * if offsets are invalid */ protected boolean endingMultiLineComment(String content, int startOffset, int endOffset) throws BadLocationException { if (!getMultiLineComment()) return false; int index = indexOf(content, getMultiLineCommentEnd(), startOffset); if ((index < 0) || (index > endOffset)) return false; else { setInsideMultiLineComment(false); return true; } } /** * We have found a start delimiter and are still searching for the end * delimiter. * * @return * true if currently within a multi-line comment */ protected boolean isMultiLineComment() { return m_InsideMultiLineComment; } /** * Sets whether we're currently within a multi-line comment or not. * * @param value * true if currently within a multi-line comment */ protected void setInsideMultiLineComment(boolean value) { m_InsideMultiLineComment = value; } /** * Parse the line for tokens to highlight. * * @param content * the content to parse * @param startOffset * the start position * @param endOffset * the end position */ protected void checkForTokens(String content, int startOffset, int endOffset) { while (startOffset <= endOffset) { // skip the delimiters to find the start of a new token while (isDelimiter(content.substring(startOffset, startOffset + 1))) { if (startOffset < endOffset) startOffset++; else return; } // Extract and process the entire token if (isQuoteDelimiter(content.substring(startOffset, startOffset + 1))) startOffset = getQuoteToken(content, startOffset, endOffset); else startOffset = getOtherToken(content, startOffset, endOffset); } } /** * Searches for a quote token. * * @param content * the content to search * @param startOffset * the start of the search * @param endOffset * the end of the search * @return * the new position */ protected int getQuoteToken(String content, int startOffset, int endOffset) { String quoteDelimiter = content.substring(startOffset, startOffset + 1); String escapeString = escapeQuote(quoteDelimiter); int index; int endOfQuote = startOffset; // skip over the escape quotes in this quote index = content.indexOf(escapeString, endOfQuote + 1); while ((index > -1) && (index < endOffset)) { endOfQuote = index + 1; index = content.indexOf(escapeString, endOfQuote); } // now find the matching delimiter index = content.indexOf(quoteDelimiter, endOfQuote + 1); if ((index < 0) || (index > endOffset)) endOfQuote = endOffset; else endOfQuote = index; m_Self.setCharacterAttributes(startOffset, endOfQuote - startOffset + 1, DEFAULT_STRING, false); return endOfQuote + 1; } /** * Searches for a keyword token. * * @param content * the content to search in * @param startOffset * the position to start the search fromm * @param endOffset * the position to end the search * @return * the new position */ protected int getOtherToken(String content, int startOffset, int endOffset) { int endOfToken = startOffset + 1; while (endOfToken <= endOffset) { if (isDelimiter(content.substring(endOfToken, endOfToken + 1))) break; endOfToken++; } String token = content.substring(startOffset, endOfToken); // see if this token has a highlighting format associated with it MutableAttributeSet attr = getKeywordFormatting(token); if (attr != null) m_Self.setCharacterAttributes(startOffset, endOfToken - startOffset, attr, false); return endOfToken + 1; } /** * Assume the needle will the found at the start/end of the line. * * @param content * the content to search * @param needle * the string to look for * @param offset * the offset to start at * @return * the index */ protected int indexOf(String content, String needle, int offset) { int index; while ((index = content.indexOf(needle, offset)) != -1) { String text = getLine(content, index).trim(); if (text.startsWith(needle) || text.endsWith(needle)) break; else offset = index + 1; } return index; } /** * Assume the needle will the found at the start/end of the line. * * @param content * the content search * @param needle * what to look for * @param offset * the offset to start * @return * the index */ protected int lastIndexOf(String content, String needle, int offset) { int index; while ((index = content.lastIndexOf(needle, offset)) != -1) { String text = getLine(content, index).trim(); if (text.startsWith(needle) || text.endsWith(needle)) break; else offset = index - 1; } return index; } /** * Returns the line. * * @param content * the content * @param offset * the offset to start at * @return * the line */ protected String getLine(String content, int offset) { int line = m_RootElement.getElementIndex(offset); Element lineElement = m_RootElement.getElement(line); int start = lineElement.getStartOffset(); int end = lineElement.getEndOffset(); return content.substring(start, end - 1); } /** * Checks whether the character is a delimiter. * * @param character * the character to check * @return * true if a delimiter */ public boolean isDelimiter(String character) { return Character.isWhitespace(character.charAt(0)) || (m_Delimiters.indexOf(character.charAt(0)) > -1); } /** * Checks whether the character is quote delimiter. * * @param character * the character to check * @return * true if a quote delimiter */ public boolean isQuoteDelimiter(String character) { return (m_QuoteDelimiters.indexOf(character.charAt(0)) > -1); } /** * Escapes the quote delimiter. * * @param quoteDelimiter * the string to escape * @return * the escaped string */ public String escapeQuote(String quoteDelimiter) { return m_QuoteEscape + quoteDelimiter; } /** * Adds the matching block end. * * @param offset * the offset * @return * the string after adding the matching block end * @throws BadLocationException * if the offset is invalid */ protected String addMatchingBlockEnd(int offset) throws BadLocationException { StringBuffer result; StringBuffer whiteSpace = new StringBuffer(); int line = m_RootElement.getElementIndex(offset); int i = m_RootElement.getElement(line).getStartOffset(); while (true) { String temp = m_Self.getText(i, 1); if (temp.equals(" ") || temp.equals("\t")) { whiteSpace.append(temp); i++; } else { break; } } // assemble string result = new StringBuffer(); result.append(m_BlockStart); result.append("\n"); result.append(whiteSpace.toString()); if (m_UseBlanks) result.append(m_Indentation); else result.append("\t"); result.append("\n"); result.append(whiteSpace.toString()); result.append(m_BlockEnd); return result.toString(); } /** * gets the current font size. * * @return * the font size */ public int getFontSize() { return m_FontSize; } /** * sets the current font size (affects all built-in styles). * * @param fontSize * the size */ public void setFontSize(int fontSize) { m_FontSize = fontSize; StyleConstants.setFontSize(DEFAULT_NORMAL, fontSize); StyleConstants.setFontSize(DEFAULT_STRING, fontSize); StyleConstants.setFontSize(DEFAULT_COMMENT, fontSize); } /** * gets the current font family. * * @return * the font name */ public String getFontName() { return m_FontName; } /** * sets the current font family (affects all built-in styles). * * @param fontName * the font name */ public void setFontName(String fontName) { m_FontName = fontName; StyleConstants.setFontFamily(DEFAULT_NORMAL, fontName); StyleConstants.setFontFamily(DEFAULT_STRING, fontName); StyleConstants.setFontFamily(DEFAULT_COMMENT, fontName); } /** * Sets the number of blanks to use for indentation. * * @param value * the number of blanks */ public void setIndentationSize(int value) { int i; m_Indentation = ""; for (i = 0; i < value; i++) m_Indentation += " "; } /** * Returns the number of blanks used for indentation. * * @return * the number of blanks */ public int getIndentationSize() { return m_Indentation.length(); } /** * Sets the delimiter characters to use. * * @param value * the characters */ public void setDelimiters(String value) { m_Delimiters = value; } /** * Returns the delimiter characters to use. * * @return * the characters */ public String getDelimiters() { return m_Delimiters; } /** * Sets the quote delimiter characters to use. * * @param value * the characters */ public void setQuoteDelimiters(String value) { m_QuoteDelimiters = value; } /** * Returns the quote delimiter characters to use. * * @return * the characters */ public String getQuoteDelimiters() { return m_QuoteDelimiters; } /** * Sets the character to use for escaping a quote character. * * @param value * the character */ public void setQuoteEscape(String value) { m_QuoteEscape = value; } /** * Returns the character for escaping a quote delimiter. * * @return * the character */ public String getQuoteEscape() { return m_QuoteEscape; } /** * Sets the string that is the start of a single-line comment. * * @param value * the string */ public void setSingleLineCommentStart(String value) { m_SingleLineCommentStart = value; } /** * Retrusn the single line comment start string. * * @return * the start string */ public String getSingleLineCommentStart() { return m_SingleLineCommentStart; } /** * Sets the string that is the start of a multi-line comment. * * @param value * the string */ public void setMultiLineCommentStart(String value) { m_MultiLineCommentStart = value; } /** * Returns the string that is the start of a multi-line comment. * * @return * the string */ public String getMultiLineCommentStart() { return m_MultiLineCommentStart; } /** * Sets the string that is the end of a multi-line comment. * * @param value the string */ public void setMultiLineCommentEnd(String value) { m_MultiLineCommentEnd = value; } /** * Returns the end of a multi-line comment. * * @return * the end string */ public String getMultiLineCommentEnd() { return m_MultiLineCommentEnd; } /** * Sets the string that is the start of a block. * * @param value * the string */ public void setBlockStart(String value) { m_BlockStart = value; } /** * Returns the start of a block. * * @return * the end string */ public String getBlockStart() { return m_BlockStart; } /** * Sets the string that is the end of a block. * * @param value * the string */ public void setBlockEnd(String value) { m_BlockEnd = value; } /** * Returns the end of a block. * * @return * the end string */ public String getBlockEnd() { return m_BlockEnd; } /** * Sets whether matching block ends are inserted or not. * * @param value * if true then matching block ends are inserted */ public void setAddMatchingEndBlocks(boolean value) { m_AddMatchingEndBlocks = value; } /** * Returns whether matching block ends are inserted or not. * * @return * true if matching block ends are inserted */ public boolean getAddMatchingEndBlocks() { return m_AddMatchingEndBlocks; } /** * Sets whether to use blanks instead of tabs. * * @param value * if true then blanks are used instead of tabs */ public void setUseBlanks(boolean value) { m_UseBlanks = value; } /** * Returns whether blanks are used instead of tabs. * * @return * true if blanks are used instead of tabs */ public boolean getUseBlanks() { return m_UseBlanks; } /** * Sets the background color. * * @param value * the background color */ public void setBackgroundColor(Color value) { m_BackgroundColor = value; } /** * Returns the background color. * * @return * the background color */ public Color getBackgroundColor() { return m_BackgroundColor; } /** * Sets whether to enable multi-line comments. * * @param value * if true then multi-line comments are enabled */ public void setMultiLineComment(boolean value) { m_MultiLineComment = value; } /** * Returns whether multi-line comments are enabled. * * @return * true if multi-line comments are enabled */ public boolean getMultiLineComment() { return m_MultiLineComment; } /** * Sets whether the keywords are case-sensitive or not. * * @param value * if true then keywords are treated case-sensitive */ public void setCaseSensitive(boolean value) { m_CaseSensitive = value; } /** * Returns whether blanks are used instead of tabs. * * @return * true if keywords are case-sensitive */ public boolean getCaseSensitive() { return m_CaseSensitive; } }