Math2mat

/home/ythoma/docs/math2mat/svn/wp1/framework/m2mGUI/src/m2m/frontend/MatlabLineStyler.java

Go to the documentation of this file.
00001 
00020 package m2m.frontend;
00021 
00022 import java.util.Hashtable;
00023 import java.util.Vector;
00024 
00025 import org.eclipse.swt.SWT;
00026 import org.eclipse.swt.custom.LineStyleEvent;
00027 import org.eclipse.swt.custom.LineStyleListener;
00028 import org.eclipse.swt.custom.StyleRange;
00029 import org.eclipse.swt.graphics.Color;
00030 import org.eclipse.swt.graphics.RGB;
00031 import org.eclipse.swt.widgets.Control;
00032 import org.eclipse.swt.widgets.Display;
00033 
00034 public class MatlabLineStyler implements LineStyleListener {
00035           JavaScanner scanner = new JavaScanner();
00036 
00037           int[] tokenColors;
00038 
00039           Color[] colors;
00040 
00041           Vector<int[]> blockComments = new Vector<int[]>();
00042 
00043           public static final int EOF = -1;
00044 
00045           public static final int EOL = 10;
00046 
00047           public static final int WORD = 0;
00048 
00049           public static final int WHITE = 1;
00050 
00051           public static final int KEY = 2;
00052 
00053           public static final int COMMENT = 3;
00054 
00055           public static final int STRING = 5;
00056 
00057           public static final int OTHER = 6;
00058 
00059           public static final int NUMBER = 7;
00060 
00061           public static final int MAXIMUM_TOKEN = 8;
00062 
00063           public MatlabLineStyler() {
00064             initializeColors();
00065             scanner = new JavaScanner();
00066           }
00067 
00068           Color getColor(int type) {
00069             if (type < 0 || type >= tokenColors.length) {
00070               return null;
00071             }
00072             return colors[tokenColors[type]];
00073           }
00074 
00075           boolean inBlockComment(int start, int end) {
00076             for (int i = 0; i < blockComments.size(); i++) {
00077               int[] offsets = (int[]) blockComments.elementAt(i);
00078               // start of comment in the line
00079               if ((offsets[0] >= start) && (offsets[0] <= end))
00080                 return true;
00081               // end of comment in the line
00082               if ((offsets[1] >= start) && (offsets[1] <= end))
00083                 return true;
00084               if ((offsets[0] <= start) && (offsets[1] >= end))
00085                 return true;
00086             }
00087             return false;
00088           }
00089 
00090           void initializeColors() {
00091             Display display = Display.getDefault();
00092             colors = new Color[] { new Color(display, new RGB(0, 0, 0)), // black
00093                 new Color(display, new RGB(255, 0, 0)), // red
00094                 new Color(display, new RGB(0, 255, 0)), // green
00095                 new Color(display, new RGB(0, 0, 255)) // blue
00096             };
00097             tokenColors = new int[MAXIMUM_TOKEN];
00098             tokenColors[WORD] = 0;
00099             tokenColors[WHITE] = 0;
00100             tokenColors[KEY] = 3;
00101             tokenColors[COMMENT] = 1;
00102             tokenColors[STRING] = 2;
00103             tokenColors[OTHER] = 0;
00104             tokenColors[NUMBER] = 0;
00105           }
00106 
00107           void disposeColors() {
00108             for (int i = 0; i < colors.length; i++) {
00109               colors[i].dispose();
00110             }
00111           }
00112 
00118           public void lineGetStyle(LineStyleEvent event) {
00119             Vector<StyleRange> styles = new Vector<StyleRange>();
00120             int token;
00121             StyleRange lastStyle;
00122             // If the line is part of a block comment, create one style for the
00123             // entire line.
00124             if (inBlockComment(event.lineOffset, event.lineOffset
00125                 + event.lineText.length())) {
00126               styles.addElement(new StyleRange(event.lineOffset, event.lineText.length(), getColor(COMMENT), null));
00127               event.styles = new StyleRange[styles.size()];
00128               styles.copyInto(event.styles);
00129               return;
00130             }
00131             Color defaultFgColor = ((Control) event.widget).getForeground();
00132             scanner.setRange(event.lineText);
00133             token = scanner.nextToken();
00134             while (token != EOF) {
00135               if (token == OTHER) {
00136                 // do nothing for non-colored tokens
00137               } else if (token != WHITE) {
00138                 Color color = getColor(token);
00139                 // Only create a style if the token color is different than the
00140                 // widget's default foreground color and the token's style is
00141                 // not
00142                 // bold. Keywords are bolded.
00143                 if ((!color.equals(defaultFgColor)) || (token == KEY)) {
00144                   StyleRange style = new StyleRange(scanner.getStartOffset()
00145                       + event.lineOffset, scanner.getLength(), color,
00146                       null);
00147                   if (token == KEY) {
00148                     style.fontStyle = SWT.BOLD;
00149                   }
00150                   if (styles.isEmpty()) {
00151                     styles.addElement(style);
00152                   } else {
00153                     // Merge similar styles. Doing so will improve
00154                     // performance.
00155                     lastStyle = (StyleRange) styles.lastElement();
00156                     if (lastStyle.similarTo(style)
00157                         && (lastStyle.start + lastStyle.length == style.start)) {
00158                       lastStyle.length += style.length;
00159                     } else {
00160                       styles.addElement(style);
00161                     }
00162                   }
00163                 }
00164               } else if ((!styles.isEmpty())
00165                   && ((lastStyle = (StyleRange) styles.lastElement()).fontStyle == SWT.BOLD)) {
00166                 int start = scanner.getStartOffset() + event.lineOffset;
00167                 lastStyle = (StyleRange) styles.lastElement();
00168                 // A font style of SWT.BOLD implies that the last style
00169                 // represents a java keyword.
00170                 if (lastStyle.start + lastStyle.length == start) {
00171                   // Have the white space take on the style before it to
00172                   // minimize the number of style ranges created and the
00173                   // number of font style changes during rendering.
00174                   lastStyle.length += scanner.getLength();
00175                 }
00176               }
00177               token = scanner.nextToken();
00178             }
00179             event.styles = new StyleRange[styles.size()];
00180             styles.copyInto(event.styles);
00181           }
00182 
00183 
00187           public class JavaScanner {
00188 
00189             protected Hashtable<String,Integer> fgKeys = null;
00190 
00191             protected StringBuffer fBuffer = new StringBuffer();
00192 
00193             protected String fDoc;
00194 
00195             protected int fPos;
00196 
00197             protected int fEnd;
00198 
00199             protected int fStartToken;
00200 
00201             protected boolean fEofSeen = false;
00202 
00203             private String[] fgKeywords = { "int", "short", "double", "rand", "break", "case", "catch",
00204                                                         "classdef", "continue", "else", "elseif", "end", "for", "function",
00205                                                         "if", "global", "otherwise", "return", "switch", "try", "while",
00206                                                         "endfunction", "endif", "endfor", "endwhile" };
00207 
00208             public JavaScanner() {
00209               initialize();
00210             }
00211 
00215             public final int getLength() {
00216               return fPos - fStartToken;
00217             }
00218 
00222             void initialize() {
00223               fgKeys = new Hashtable<String,Integer>();
00224               Integer k = new Integer(KEY);
00225               for (int i = 0; i < fgKeywords.length; i++)
00226                 fgKeys.put(fgKeywords[i], k);
00227             }
00228 
00232             public final int getStartOffset() {
00233               return fStartToken;
00234             }
00235 
00239             public int nextToken() {
00240               int c;
00241               fStartToken = fPos;
00242               while (true) {
00243                 switch (c = read()) {
00244                 case EOF:
00245                   return EOF;
00246                 case '%': // comment
00247                 case '#':
00248                     while (true) {
00249                       c = read();
00250                       if ((c == EOF) || (c == EOL)) {
00251                         unread(c);
00252                         return COMMENT;
00253                       }
00254                     }
00255                 case '\'': // char const
00256                   for (;;) {
00257                     c = read();
00258                     switch (c) {
00259                     case '\'':
00260                       return STRING;
00261                     case EOF:
00262                       unread(c);
00263                       return STRING;
00264                     case '\\':
00265                       c = read();
00266                       break;
00267                     }
00268                   }
00269 
00270                 case '"': // string
00271                   for (;;) {
00272                     c = read();
00273                     switch (c) {
00274                     case '"':
00275                       return STRING;
00276                     case EOF:
00277                       unread(c);
00278                       return STRING;
00279                     case '\\':
00280                       c = read();
00281                       break;
00282                     }
00283                   }
00284 
00285                 case '0':
00286                 case '1':
00287                 case '2':
00288                 case '3':
00289                 case '4':
00290                 case '5':
00291                 case '6':
00292                 case '7':
00293                 case '8':
00294                 case '9':
00295                   do {
00296                     c = read();
00297                   } while (Character.isDigit((char) c));
00298                   unread(c);
00299                   return NUMBER;
00300                 default:
00301                   if (Character.isWhitespace((char) c)) {
00302                     do {
00303                       c = read();
00304                     } while (Character.isWhitespace((char) c));
00305                     unread(c);
00306                     return WHITE;
00307                   }
00308                   if (Character.isJavaIdentifierStart((char) c)) {
00309                     fBuffer.setLength(0);
00310                     do {
00311                       fBuffer.append((char) c);
00312                       c = read();
00313                     } while (Character.isJavaIdentifierPart((char) c));
00314                     unread(c);
00315                     Integer i = (Integer) fgKeys.get(fBuffer.toString());
00316                     if (i != null)
00317                       return i.intValue();
00318                     return WORD;
00319                   }
00320                   return OTHER;
00321                 }
00322               }
00323             }
00324 
00328             protected int read() {
00329               if (fPos <= fEnd) {
00330                 return fDoc.charAt(fPos++);
00331               }
00332               return EOF;
00333             }
00334 
00335             public void setRange(String text) {
00336               fDoc = text;
00337               fPos = 0;
00338               fEnd = fDoc.length() - 1;
00339             }
00340 
00341             protected void unread(int c) {
00342               if (c != EOF)
00343                 fPos--;
00344             }
00345           }
00346 }
 All Classes Namespaces Files Functions Variables Enumerations