package org.eclipse.dltk.console.ui; import java.util.StringTokenizer; import org.eclipse.jface.text.BadLocationException; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Display; /** * @author ssanders */ public class AnsiColorHelper { public static interface IAnsiColorHandler { public void handleText(int start, String content, boolean isInput, boolean isError) throws BadLocationException; public void processingComplete(int start, int length); } public static final Color COLOR_BLACK = new Color(Display.getCurrent(), 0, 0, 0); public static final Color COLOR_BLUE = new Color(Display.getCurrent(), 0, 0, 255); public static final Color COLOR_CYAN = new Color(Display.getCurrent(), 0, 255, 255); public static final Color COLOR_GREEN = new Color(Display.getCurrent(), 0, 255, 0); public static final Color COLOR_MAGENTA = new Color(Display.getCurrent(), 255, 0, 255); public static final Color COLOR_RED = new Color(Display.getCurrent(), 255, 0, 0); public static final Color COLOR_WHITE = new Color(Display.getCurrent(), 255, 255, 255); public static final Color COLOR_YELLOW = new Color(Display.getCurrent(), 255, 255, 0); private static final StyleRange DEFAULT_ERROR = new StyleRange(-1, -1, COLOR_RED, null, SWT.BOLD); private static final StyleRange DEFAULT_OUTPUT = new StyleRange(-1, -1, COLOR_BLUE, null); private StyleRange defaultOutput; private StyleRange defaultError; private boolean enabled = true; private boolean bright; private boolean dim; private boolean underscore; private boolean blink; private boolean reverse; private boolean hidden; private Color foreground; private Color background; public AnsiColorHelper(StyleRange defaultOutput, StyleRange defaultError) { this.defaultOutput = ((defaultOutput != null) ? defaultOutput : DEFAULT_OUTPUT); this.defaultError = ((defaultError != null) ? defaultError : DEFAULT_ERROR); } public AnsiColorHelper() { this(DEFAULT_OUTPUT, DEFAULT_ERROR); } public void reset() { bright = false; dim = false; underscore = false; blink = false; reverse = false; hidden = false; foreground = null; background = null; } public StyleRange resolveStyleRange(int start, int length, boolean isError) { StyleRange styleRange; Color curForeground = foreground; Color curBackground = background; int curFontStyle = 0; if (bright == true) { curFontStyle = (curFontStyle | SWT.BOLD); } if (dim == true) { curFontStyle = (curFontStyle | SWT.ITALIC); } if (curForeground == null) { StyleRange curDefault = ((isError == true) ? defaultError : defaultOutput); curForeground = curDefault.foreground; curBackground = curDefault.background; if (curFontStyle == 0) { curFontStyle = curDefault.fontStyle; } } if (hidden == true) { curForeground = curBackground; } else if (reverse == true) { Color oldForeground = curForeground; curForeground = curBackground; curBackground = oldForeground; } styleRange = new StyleRange(start, length, curForeground, curBackground, curFontStyle); styleRange.underline = underscore; styleRange.strikeout = blink; return styleRange; } private void decodeAnsi(String ansiCode) { StringTokenizer tokenizer = new StringTokenizer(ansiCode, ";"); //$NON-NLS-1$ String token; while (tokenizer.hasMoreTokens() == true) { token = tokenizer.nextToken(); if ("0".equals(token) == true) { //$NON-NLS-1$ reset(); } else if ("1".equals(token) == true) { //$NON-NLS-1$ bright = true; } else if ("2".equals(token) == true) { //$NON-NLS-1$ dim = true; } else if ("4".equals(token) == true) { //$NON-NLS-1$ underscore = true; } else if ("5".equals(token) == true) { //$NON-NLS-1$ blink = true; } else if ("7".equals(token) == true) { //$NON-NLS-1$ reverse = true; } else if ("8".equals(token) == true) { //$NON-NLS-1$ hidden = true; } else if ("30".equals(token) == true) { //$NON-NLS-1$ foreground = COLOR_BLACK; } else if ("31".equals(token) == true) { //$NON-NLS-1$ foreground = COLOR_RED; } else if ("32".equals(token) == true) { //$NON-NLS-1$ foreground = COLOR_GREEN; } else if ("33".equals(token) == true) { //$NON-NLS-1$ foreground = COLOR_YELLOW; } else if ("34".equals(token) == true) { //$NON-NLS-1$ foreground = COLOR_BLUE; } else if ("35".equals(token) == true) { //$NON-NLS-1$ foreground = COLOR_MAGENTA; } else if ("36".equals(token) == true) { //$NON-NLS-1$ foreground = COLOR_CYAN; } else if ("37".equals(token) == true) { //$NON-NLS-1$ foreground = COLOR_WHITE; } else if ("40".equals(token) == true) { //$NON-NLS-1$ background = COLOR_BLACK; } else if ("41".equals(token) == true) { //$NON-NLS-1$ background = COLOR_RED; } else if ("42".equals(token) == true) { //$NON-NLS-1$ background = COLOR_GREEN; } else if ("43".equals(token) == true) { //$NON-NLS-1$ background = COLOR_YELLOW; } else if ("44".equals(token) == true) { //$NON-NLS-1$ background = COLOR_BLUE; } else if ("45".equals(token) == true) { //$NON-NLS-1$ background = COLOR_MAGENTA; } else if ("46".equals(token) == true) { //$NON-NLS-1$ background = COLOR_CYAN; } else if ("47".equals(token) == true) { //$NON-NLS-1$ background = COLOR_WHITE; } } } public void processText(int originalOffset, String content, boolean isInput, boolean isError, IAnsiColorHandler handler) throws BadLocationException { int start = 0; int adjust = 0; if (enabled == true) { int ansiCnt; boolean isAnsi; char curChar; String ansiCode; String curContent; for (int cnt = 0, max = content.length(); cnt < max; cnt++) { if (content.charAt(cnt) == '[') { ansiCnt = (cnt + 1); isAnsi = false; while (ansiCnt < max) { curChar = content.charAt(ansiCnt); if ((curChar == ';') || ((curChar >= '0') && (curChar <= '9'))) { ansiCnt++; } else if (curChar == 'm') { isAnsi = true; break; } else { isAnsi = false; break; } } if (isAnsi == true) { curContent = content.substring(start, cnt); handler.handleText((originalOffset + start - adjust), curContent, isInput, isError); ansiCode = content.substring((cnt + 1), ansiCnt); decodeAnsi(ansiCode); adjust += ((ansiCnt - cnt) + 1); cnt = ansiCnt; start = (ansiCnt + 1); } } } } if (start < content.length()) { String overflowContent = ((start == 0) ? content : content .substring(start)); handler.handleText((originalOffset + start - adjust), overflowContent, isInput, isError); } handler.processingComplete(originalOffset, (content.length() - adjust)); } public void disableWhile(Runnable runnable) { boolean oldEnabled = enabled; enabled = false; try { runnable.run(); } finally { enabled = oldEnabled; } } }