package Editor.GUI.CodeDocument; import Editor.GUI.Dialogo.Message; import Portugol.Language.Calcular.CalculusElement; import Portugol.Language.Analisador.Keyword; import java.awt.Color; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.Element; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; public class AlgoCodeStyle extends AlgoSyntaxHighlight { public static String VERSION = "Versão:2.0 \t(c)Augusto Bilabila e David Silva Barrera"; public final static int STRING_MODE = 10; public final static int TEXT_MODE = 11; public final static int NUMBER_MODE = 12; public final static int BLOCK_COMMENT_MODE = 13; public final static int SINGLE_COMMENT_MODE = 14; public final static int FUNCTION_MODE = 15; public final static int KEYWORD_MODE = 16; public final static int STATEMENT_MODE = 17; public final static int OPERATOR_MODE = 18; public final static int ATTRIB_MODE = 19; public final static int NEWDATATYPE_MODE = 20;//registos e classes são novos tipos de dados private int mode = TEXT_MODE; private int currentPos = 0; private Color backGround = defaultBackGround; private SimpleAttributeSet comments; //comentarios private SimpleAttributeSet normal; // normal private SimpleAttributeSet string; // strings private SimpleAttributeSet number; // numeros private SimpleAttributeSet function; // funcoes private SimpleAttributeSet keyword; // palavras reservadas private SimpleAttributeSet operator; // operadores private SimpleAttributeSet attrib; // sinal de atribuicao private SimpleAttributeSet newdatatype; // registos e classes public AlgoCodeStyle() { //set the attributes for string string = new SimpleAttributeSet(); StyleConstants.setForeground(string, new Color(255, 69, 0)); StyleConstants.setFontFamily(string, "Courier"); //set the attributes for number number = new SimpleAttributeSet(); StyleConstants.setForeground(number, Color.red); StyleConstants.setFontFamily(number, "Courier"); //set the attributes for comments comments = new SimpleAttributeSet(); StyleConstants.setForeground(comments, new Color(150, 150, 150));//cinza StyleConstants.setItalic(comments, true); StyleConstants.setFontFamily(comments, "Courier"); //set the attributes for normal normal = new SimpleAttributeSet(); StyleConstants.setBold(normal, false); StyleConstants.setForeground(normal, Color.black); StyleConstants.setFontFamily(normal, "Courier"); //set the attributes for Functions function = new SimpleAttributeSet(); StyleConstants.setBold(function, true); StyleConstants.setForeground(function, Color.RED); StyleConstants.setFontFamily(function, "Courier"); //set the attributes for KeyWords keyword = new SimpleAttributeSet(); StyleConstants.setBold(keyword, true); StyleConstants.setForeground(keyword, Color.BLUE); StyleConstants.setFontFamily(keyword, "Courier"); //set the attributes for operators operator = new SimpleAttributeSet(); StyleConstants.setBold(operator, true); StyleConstants.setForeground(operator, new Color(30, 180, 30)); //green StyleConstants.setFontFamily(operator, "Courier"); //set the attributes for operators attrib = new SimpleAttributeSet(); StyleConstants.setBold(attrib, true); StyleConstants.setForeground(attrib, new Color(139, 71, 38)); //castanho meio claro StyleConstants.setFontFamily(attrib, "Courier"); //set the attributes for operators newdatatype = new SimpleAttributeSet(); StyleConstants.setBold(newdatatype, true); StyleConstants.setForeground(newdatatype, Color.magenta); //David: Classe côr StyleConstants.setFontFamily(newdatatype, "Courier"); } //------------------------------------------------------------------------- //------------------------------------------------------------------------- // verifica se e atribuicao //------------------------------------------------------------------------- //---------------------------------------------------------------------------- private boolean checkForAttrib(int offs, String elementText) { if ((mode == this.BLOCK_COMMENT_MODE) || (mode == this.SINGLE_COMMENT_MODE)) { return false; } int strLen = elementText.length(); int i = 0; if ((offs >= 1) && (offs <= strLen - 1)) { i = offs; char commentStartChar1 = elementText.charAt(i - 1); char commentStartChar2 = elementText.charAt(i); if (commentStartChar1 == '<' && commentStartChar2 == '-') { mode = this.ATTRIB_MODE; insertHighlight("<-", currentPos - 1); return true; } } return false; } //------------------------------------------------------------------------- //------------------------------------------------------------------------- // verifica se e um comentario //------------------------------------------------------------------------- //---------------------------------------------------------------------------- private boolean checkForComment(int offs, String elementText) { int strLen = elementText.length(); int i = 0; if ((offs >= 1) && (offs <= strLen - 1)) { i = offs; char commentStartChar1 = elementText.charAt(i - 1); char commentStartChar2 = elementText.charAt(i); if (commentStartChar1 == '/' && commentStartChar2 == '*') { mode = this.BLOCK_COMMENT_MODE; insertHighlight("/*", currentPos - 1); return true; } else if (commentStartChar1 == '*' && commentStartChar2 == '/') { insertHighlight("*/", currentPos - 1); mode = this.TEXT_MODE; return true; } else if (commentStartChar1 == '/' && commentStartChar2 == '/') { this.mode = this.SINGLE_COMMENT_MODE; insertHighlight("//", currentPos - 1); return true; } } return false; } //------------------------------------------------------------------------- //------------------------------------------------------------------------- // verifica se é uma string //------------------------------------------------------------------------- private boolean checkForString(int offs, String elementText) { if ((mode == this.BLOCK_COMMENT_MODE) || (mode == this.SINGLE_COMMENT_MODE)) { return false; } int i = 0; int quoteCount = 0; int strLen = elementText.length(); if ((offs >= 0) && (offs <= strLen - 1)) { i = offs; while (i > 0) { //contar os "" if (elementText.charAt(i) == '"') { // se estiver precedido de \ nao conta if (i == 0 || (i > 0 && elementText.charAt(i - 1) != '\\')) { quoteCount++; } } i--; } // insere O " em STRING_MODE mode = this.STRING_MODE; insertHighlight("\"", currentPos); // se o numero for impar is string int rem = quoteCount % 2; mode = (rem == 0) ? this.TEXT_MODE : this.STRING_MODE; return true; } return false; } //------------------------------------------------------------------------- //------------------------------------------------------------------------- //verifica se is numero //------------------------------------------------------------------------- //------------------------------------------------------------------------- private void checkForNumber(int offs, String elementText) { //se for comentario ou if ((mode == this.BLOCK_COMMENT_MODE) || (mode == this.SINGLE_COMMENT_MODE) || (mode == this.STRING_MODE)) { return; } int i = 0; mode = this.TEXT_MODE; int strLen = elementText.length(); if ((offs >= 0) && (offs <= strLen - 1)) { i = offs; while (i > 0) { //the while loop walks back until we hit a delimiter char charAt = elementText.charAt(i); if ((charAt == ' ') | (i == 0) | (charAt == '(') | (charAt == ')') | (charAt == '{') | (charAt == '}') /*|*/) { //if i == 0 then we're at the begininng if (i != 0) { i++; } mode = this.NUMBER_MODE; break; } else if (!(charAt >= '0' & charAt <= '9' | charAt == '.' | charAt == '+' | charAt == '-' | charAt == '/' | charAt == '*' | charAt == '%' | charAt == '=')) { mode = this.TEXT_MODE; break; } i--; } } } private boolean checkForKeyword(int offs, String elementText) { if ((mode == this.BLOCK_COMMENT_MODE) || (mode == this.SINGLE_COMMENT_MODE) || (mode == this.STRING_MODE)) { return false; } int i; int strLen = elementText.length(); if ((offs >= 0) && (offs <= strLen - 1)) { i = offs; while (i > 0) { //the while loop walks back until we hit a delimiter i--; char charAt = elementText.charAt(i); if ((charAt == ' ') | (i == 0) | (charAt == '(') | (charAt == ')') | (charAt == '{') | (charAt == '}')) { //if i == 0 then we're at the begininng if (i != 0) { i++; } return ClassifyWord(elementText.substring(i, offs)); //skip the period } } } return false; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- private boolean ClassifyWord(String word) { if ((mode == this.BLOCK_COMMENT_MODE) || (mode == this.SINGLE_COMMENT_MODE) || (mode == this.STRING_MODE)) { return false; } if (CalculusElement.IsFunction(word)) { mode = this.FUNCTION_MODE; insertHighlight(word, currentPos - word.length()); return true; } if (Keyword.IsKeyword(word)) { mode = this.KEYWORD_MODE; insertHighlight(word, currentPos - word.length()); return true; //operadores aritmeticos relacionais e logicos } else if (Keyword.DefineClasse(word) || Keyword.DefineRegisto(word)) { mode = this.NEWDATATYPE_MODE; insertHighlight(word, currentPos - word.length()); return true; //operadores aritmeticos relacionais e logicos } else if (CalculusElement.IsElemCalculus(word)) { mode = this.OPERATOR_MODE; insertHighlight(word, currentPos - word.length()); return true; } return false; } //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { super.insertString(offs, str, normal); int strLen = str.length(); int endpos = offs + strLen; int strpos; for (int i = offs; i < endpos; i++) { currentPos = i; strpos = i - offs; processChar(str.charAt(strpos)); } currentPos = offs; } //------------------------------------------------------------------------- private void processChar(char strChar) { //------------------------------- extrair o elemento --------------- int offs = this.currentPos; Element element = this.getParagraphElement(offs); String elementText = ""; try { //this gets our chuck of current text for the element we're on elementText = this.getText(element.getStartOffset(), element.getEndOffset() - element.getStartOffset()); } catch (Exception ex) { //whoops! Message.Error("PORTUGOLCODESTYLE.checkForString\n" + ex.getMessage()); } if (elementText.length() == 0) { return; } if (element.getStartOffset() > 0) { //translates backward if neccessary offs = offs - element.getStartOffset(); } //------------------------------- processar o caracter --------------- //por defeito � modo normal, excepto se . . . if (this.mode != this.BLOCK_COMMENT_MODE && this.mode != this.SINGLE_COMMENT_MODE && this.mode != this.STRING_MODE) { this.mode = TEXT_MODE; } switch (strChar) { case ('\n'): if (checkForKeyword(offs, elementText)) { insertHighlight(strChar + "", this.currentPos); } if (this.mode != this.BLOCK_COMMENT_MODE) { this.mode = this.TEXT_MODE; } return; case (' '): case ('('): case (')'): if (checkForKeyword(offs, elementText)) { //imprimir este caracter insertHighlight(strChar + "", this.currentPos); return; } break; case ('*'): case ('/'): if (checkForComment(offs, elementText)) { return; } break; case ('"'): if (checkForString(offs, elementText)) { return; } break; case ('-'): if (checkForAttrib(offs, elementText)) { return; } break; case ('0'): case ('1'): case ('2'): case ('3'): case ('4'): case ('5'): case ('6'): case ('7'): case ('8'): case ('9'): case ('.'): checkForNumber(offs, elementText); break; } insertHighlight(strChar + "", this.currentPos); } //---------------------------------------------------------------------------- private void insertHighlight(String str, int pos) { try { SimpleAttributeSet attr; //remove the old word and formatting this.remove(pos, str.length()); switch (this.mode) { case STRING_MODE: attr = string; break; case NUMBER_MODE: attr = number; break; case FUNCTION_MODE: attr = function; break; case KEYWORD_MODE: attr = keyword; break; case OPERATOR_MODE: attr = operator; break; case ATTRIB_MODE: attr = attrib; break; case NEWDATATYPE_MODE: attr = newdatatype; break; case BLOCK_COMMENT_MODE: case SINGLE_COMMENT_MODE: attr = comments; break; default: attr = normal; } StyleConstants.setBackground(attr, backGround); super.insertString(pos, str, attr); } catch (Exception ex) { Message.Error("PORTUGOLCODESTYLE.insertCommentString\n" + ex.getMessage()); } } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// private void printSelectLine(int numChar) { if (numChar < 0) { return; } try { Element element = this.getParagraphElement(numChar); int start = element.getStartOffset(); int end = element.getEndOffset(); String old = this.getText(start, end - start); currentPos = numChar; for (int i = start; i < end; i++) { currentPos = i; this.processChar(old.charAt(i - start)); } } catch (Exception ex) { Message.Error("PRINT SELECT LINE \n" + ex.getMessage()); } } public void selectErrorLine(int numChar) { if (esDebug) { this.backGround = new Color(155, 230, 230); } else { this.backGround = new Color(255, 230, 230); } printSelectLine(numChar); this.backGround = defaultBackGround; } public void selectCodeLine(int numChar) { this.backGround = new Color(255, 255, 120); printSelectLine(numChar); this.backGround = defaultBackGround; } public void deSelectCodeLine(int numChar) { this.backGround = defaultBackGround; printSelectLine(numChar); } public void clearTextBackground() { this.mode = this.TEXT_MODE; try { int index = 0; while (index < this.getLength()) { Element element = this.getParagraphElement(index); String old = this.getText(element.getStartOffset(), element.getEndOffset() - element.getStartOffset()); printSelectLine(index); //fazer o skip dos \n if (old.length() < 2) { index += 2; } else { index += old.length(); } } } catch (Exception ex) { Message.Error("CLEAR TEXT BACKGROUND \n" + ex.getMessage()); } } }