/*
* @(#)GTKParser.java 1.88 04/08/10
*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.sun.java.swing.plaf.gtk;
import java.util.*;
import java.io.*;
import java.awt.*;
import java.util.regex.PatternSyntaxException;
import javax.swing.plaf.ColorUIResource;
import java.security.AccessController;
import sun.security.action.GetPropertyAction;
import javax.swing.plaf.synth.SynthConstants;
/**
* @author Shannon Hickey
* @version 1.88 08/10/04
*/
class GTKParser {
private ArrayList freeScanners = new ArrayList();
private HashMap namedStyles = new HashMap();
private ArrayList assignments = new ArrayList();
private HashMap settings = new HashMap();
private File[] pixmapPaths = null;
private ArrayList dirStack = new ArrayList();
private HashMap engineParsers = new HashMap();
// Register parsers here for now. Later we can add methods to register
// new parser classes.
{
engineParsers.put("pixmap", "com.sun.java.swing.plaf.gtk.PixmapEngineParser");
engineParsers.put("bluecurve", "com.sun.java.swing.plaf.gtk.BluecurveEngineParser");
engineParsers.put("wonderland", "com.sun.java.swing.plaf.gtk.BluecurveEngineParser");
engineParsers.put("blueprint", "com.sun.java.swing.plaf.gtk.BlueprintEngineParser");
}
private GTKScanner scanner;
private final String CWD = (String)AccessController.doPrivileged(
new GetPropertyAction("user.dir"));
static class Symbol {
public String name;
public int val;
public Symbol(String name, int val) {
this.name = name;
this.val = val;
}
}
private static final Symbol SYMBOL_INVALID = new Symbol("invalid", GTKScanner.TOKEN_LAST);
private static final Symbol SYMBOL_INCLUDE = new Symbol("include", SYMBOL_INVALID.val + 1);
private static final Symbol SYMBOL_NORMAL = new Symbol("NORMAL", SYMBOL_INCLUDE.val + 1);
private static final Symbol SYMBOL_ACTIVE = new Symbol("ACTIVE", SYMBOL_NORMAL.val + 1);
private static final Symbol SYMBOL_PRELIGHT = new Symbol("PRELIGHT", SYMBOL_ACTIVE.val + 1);
private static final Symbol SYMBOL_SELECTED = new Symbol("SELECTED", SYMBOL_PRELIGHT.val + 1);
private static final Symbol SYMBOL_INSENSITIVE = new Symbol("INSENSITIVE", SYMBOL_SELECTED.val + 1);
private static final Symbol SYMBOL_FG = new Symbol("fg", SYMBOL_INSENSITIVE.val + 1);
private static final Symbol SYMBOL_BG = new Symbol("bg", SYMBOL_FG.val + 1);
private static final Symbol SYMBOL_TEXT = new Symbol("text", SYMBOL_BG.val + 1);
private static final Symbol SYMBOL_BASE = new Symbol("base", SYMBOL_TEXT.val + 1);
private static final Symbol SYMBOL_XTHICKNESS = new Symbol("xthickness", SYMBOL_BASE.val + 1);
private static final Symbol SYMBOL_YTHICKNESS = new Symbol("ythickness", SYMBOL_XTHICKNESS.val + 1);
private static final Symbol SYMBOL_FONT = new Symbol("font", SYMBOL_YTHICKNESS.val + 1);
private static final Symbol SYMBOL_FONTSET = new Symbol("fontset", SYMBOL_FONT.val + 1);
private static final Symbol SYMBOL_FONT_NAME = new Symbol("font_name", SYMBOL_FONTSET.val + 1);
private static final Symbol SYMBOL_BG_PIXMAP = new Symbol("bg_pixmap", SYMBOL_FONT_NAME.val + 1);
private static final Symbol SYMBOL_PIXMAP_PATH = new Symbol("pixmap_path", SYMBOL_BG_PIXMAP.val + 1);
private static final Symbol SYMBOL_STYLE = new Symbol("style", SYMBOL_PIXMAP_PATH.val + 1);
private static final Symbol SYMBOL_BINDING = new Symbol("binding", SYMBOL_STYLE.val + 1);
private static final Symbol SYMBOL_BIND = new Symbol("bind", SYMBOL_BINDING.val + 1);
private static final Symbol SYMBOL_WIDGET = new Symbol("widget", SYMBOL_BIND.val + 1);
private static final Symbol SYMBOL_WIDGET_CLASS = new Symbol("widget_class", SYMBOL_WIDGET.val + 1);
private static final Symbol SYMBOL_CLASS = new Symbol("class", SYMBOL_WIDGET_CLASS.val + 1);
private static final Symbol SYMBOL_LOWEST = new Symbol("lowest", SYMBOL_CLASS.val + 1);
private static final Symbol SYMBOL_GTK = new Symbol("gtk", SYMBOL_LOWEST.val + 1);
private static final Symbol SYMBOL_APPLICATION = new Symbol("application", SYMBOL_GTK.val + 1);
private static final Symbol SYMBOL_THEME = new Symbol("theme", SYMBOL_APPLICATION.val + 1);
private static final Symbol SYMBOL_RC = new Symbol("rc", SYMBOL_THEME.val + 1);
private static final Symbol SYMBOL_HIGHEST = new Symbol("highest", SYMBOL_RC.val + 1);
private static final Symbol SYMBOL_ENGINE = new Symbol("engine", SYMBOL_HIGHEST.val + 1);
private static final Symbol SYMBOL_MODULE_PATH = new Symbol("module_path", SYMBOL_ENGINE.val + 1);
private static final Symbol SYMBOL_IM_MODULE_PATH = new Symbol("im_module_path", SYMBOL_MODULE_PATH.val + 1);
private static final Symbol SYMBOL_IM_MODULE_FILE = new Symbol("im_module_file", SYMBOL_IM_MODULE_PATH.val + 1);
private static final Symbol SYMBOL_STOCK = new Symbol("stock", SYMBOL_IM_MODULE_FILE.val + 1);
private static final Symbol SYMBOL_LTR = new Symbol("LTR", SYMBOL_STOCK.val + 1);
private static final Symbol SYMBOL_RTL = new Symbol("RTL", SYMBOL_LTR.val + 1);
private static final Symbol SYMBOL_LAST = new Symbol("last", SYMBOL_RTL.val + 1);
private static final Symbol[] symbols = {
SYMBOL_INCLUDE, SYMBOL_NORMAL, SYMBOL_ACTIVE, SYMBOL_PRELIGHT,
SYMBOL_SELECTED, SYMBOL_INSENSITIVE, SYMBOL_FG, SYMBOL_BG,
SYMBOL_TEXT, SYMBOL_BASE, SYMBOL_XTHICKNESS, SYMBOL_YTHICKNESS,
SYMBOL_FONT, SYMBOL_FONTSET, SYMBOL_FONT_NAME, SYMBOL_BG_PIXMAP,
SYMBOL_PIXMAP_PATH, SYMBOL_STYLE, SYMBOL_BINDING, SYMBOL_BIND,
SYMBOL_WIDGET, SYMBOL_WIDGET_CLASS, SYMBOL_CLASS, SYMBOL_LOWEST,
SYMBOL_GTK, SYMBOL_APPLICATION, SYMBOL_THEME, SYMBOL_RC,
SYMBOL_HIGHEST, SYMBOL_ENGINE, SYMBOL_MODULE_PATH,
SYMBOL_IM_MODULE_FILE, SYMBOL_STOCK, SYMBOL_LTR, SYMBOL_RTL
};
private static class StyleInfo {
String name;
static final int NUM_STATES = 5;
static final int NORMAL = 0;
static final int PRELIGHT = 1;
static final int ACTIVE = 2;
static final int INSENSITIVE = 3;
static final int SELECTED = 4;
Color[] fg = new Color[NUM_STATES];
Color[] bg = new Color[NUM_STATES];
Color[] text = new Color[NUM_STATES];
Color[] base = new Color[NUM_STATES];
String[] bgPixmapName = new String[NUM_STATES];
Font font = null;
int xThickness = GTKStyle.UNDEFINED_THICKNESS;
int yThickness = GTKStyle.UNDEFINED_THICKNESS;
// An array of HashMaps. The first HashMap is for stock
// icons defined in this style. The other elements are
// those inherited from parent.
ArrayList stocks = null;
CircularIdentityList props = null;
EngineInfo engineInfo = null;
private GTKStyle cachedStyle = null;
private static GTKStyle EMPTY_STYLE = new GTKStyle();
StyleInfo(String name) {
this.name = name;
}
private void initStocksIfNecessary() {
if (stocks == null) {
stocks = new ArrayList();
// for stock icons defined in this style
stocks.add(new HashMap());
}
}
void addStockItem(String id, GTKStyle.GTKIconSource[] sources) {
initStocksIfNecessary();
GTKStyle.GTKStockIconInfo iconInfo = new GTKStyle.GTKStockIconInfo(id, sources);
HashMap map = (HashMap)stocks.get(0);
map.put(id, iconInfo);
}
void addProperty(String klass, String prop, Object value) {
if (props == null) {
props = new CircularIdentityList();
}
CircularIdentityList subList = (CircularIdentityList)props.get(klass);
if (subList == null) {
subList = new CircularIdentityList();
props.set(klass, subList);
}
subList.set(prop, value);
}
void copyDataFrom(StyleInfo other) {
for (int i = 0; i < NUM_STATES; i++) {
fg[i] = other.fg[i];
bg[i] = other.bg[i];
text[i] = other.text[i];
base[i] = other.base[i];
bgPixmapName[i] = other.bgPixmapName[i];
}
xThickness = other.xThickness;
yThickness = other.yThickness;
font = other.font;
if (other.stocks != null) {
initStocksIfNecessary();
stocks.addAll(other.stocks);
}
if (props == null) {
props = GTKStyle.cloneClassSpecificValues(other.props);
} else {
GTKStyle.addClassSpecificValues(other.props, props);
}
}
GTKStyle toGTKStyle() {
if (cachedStyle != null) {
return cachedStyle;
}
ArrayList stateInfos = new ArrayList();
for (int i = 0; i < NUM_STATES; i++) {
Color[] colors = null;
if (fg[i] != null
|| bg[i] != null
|| text[i] != null
|| base[i] != null) {
colors = new Color[GTKColorType.MAX_COUNT];
colors[GTKColorType.FOREGROUND.getID()] = fg[i];
colors[GTKColorType.BACKGROUND.getID()] = bg[i];
colors[GTKColorType.TEXT_FOREGROUND.getID()] = text[i];
colors[GTKColorType.TEXT_BACKGROUND.getID()] = base[i];
}
if (colors != null || bgPixmapName[i] != null) {
GTKStyle.GTKStateInfo stateInfo =
new GTKStyle.GTKStateInfo(toSynthState(i),
null, colors, bgPixmapName[i]);
stateInfos.add(stateInfo);
}
}
GTKStyle.GTKStateInfo[] infoArray = null;
if (stateInfos.size() != 0) {
infoArray = new GTKStyle.GTKStateInfo[stateInfos.size()];
infoArray = (GTKStyle.GTKStateInfo[])stateInfos.toArray(infoArray);
}
GTKStyle.GTKStockIconInfo[] stockArray = stocksToArray();
// if this style has engine information, delegate the creation
if (engineInfo != null) {
cachedStyle = engineInfo.constructGTKStyle(infoArray,
props,
font,
xThickness,
yThickness,
stockArray);
// otherwise, create a regular GTKStyle
} else if (infoArray != null
|| stockArray != null
|| props != null
|| font != null
|| xThickness != GTKStyle.UNDEFINED_THICKNESS
|| yThickness != GTKStyle.UNDEFINED_THICKNESS) {
cachedStyle = new GTKStyle(infoArray,
props,
font,
xThickness,
yThickness,
stockArray);
} else {
cachedStyle = EMPTY_STYLE;
}
return cachedStyle;
}
private GTKStyle.GTKStockIconInfo[] stocksToArray() {
if (stocks == null) {
return null;
}
ArrayList tmpList = new ArrayList();
HashMap[] maps = new HashMap[stocks.size()];
maps = (HashMap[])stocks.toArray(maps);
for (int i = 0; i < maps.length; i++) {
tmpList.addAll(maps[i].values());
}
GTKStyle.GTKStockIconInfo[] retVal = new GTKStyle.GTKStockIconInfo[tmpList.size()];
retVal = (GTKStyle.GTKStockIconInfo[])tmpList.toArray(retVal);
return retVal;
}
private static int toSynthState(int ourState) {
switch(ourState) {
case NORMAL: return SynthConstants.ENABLED;
case PRELIGHT: return SynthConstants.MOUSE_OVER;
case ACTIVE: return SynthConstants.PRESSED;
case INSENSITIVE: return SynthConstants.DISABLED;
case SELECTED: return SynthConstants.SELECTED;
}
// should not happen
return SynthConstants.ENABLED;
}
}
static abstract class EngineInfo {
private String engineName;
abstract GTKStyle constructGTKStyle(GTKStyle.GTKStateInfo[] infoArray,
CircularIdentityList props,
Font font,
int xThickness,
int yThickness,
GTKStyle.GTKStockIconInfo[] stockArray);
}
private static class Assignment {
int type;
String pattern;
StyleInfo info;
Assignment(int type, String pattern, StyleInfo info) {
this.type = type;
this.pattern = pattern;
this.info = info;
}
public String toString() {
String sVal = "";
switch(type) {
case GTKStyleFactory.WIDGET: sVal = "widget, "; break;
case GTKStyleFactory.WIDGET_CLASS: sVal = "widget_class, "; break;
case GTKStyleFactory.CLASS: sVal = "class, "; break;
}
sVal += pattern + ", ";
sVal += info.name;
return sVal;
}
}
private static Symbol getSymbol(int symbol) {
if (symbol > SYMBOL_INVALID.val && symbol < SYMBOL_LAST.val) {
for (int i = 0; i < symbols.length; i++) {
if (symbols[i].val == symbol) {
return symbols[i];
}
}
}
return null;
}
public GTKParser() {
freeScanners.add(createScanner());
}
public void parseString(String str) throws IOException {
StringReader reader = new StringReader(str);
parseReader(reader, "-");
}
public void parseFile(File file, String name) throws IOException {
if (!file.canRead() || !file.isFile()) {
return;
}
File parent = file.getParentFile();
if (parent == null) {
parent = new File(CWD);
}
dirStack.add(parent);
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
parseReader(reader, name);
} finally {
dirStack.remove(dirStack.size() - 1);
}
// PENDING(shannonh) - This is where we should look up and parse
// the locale-specific version of the file.
}
private void parseReader(Reader reader, String name) throws IOException {
int len = freeScanners.size();
if (len == 0) {
scanner = createScanner();
} else {
scanner = (GTKScanner)freeScanners.remove(len - 1);
}
scanner.scanReader(reader, name);
try {
parseCurrent();
} finally {
scanner.clearScanner();
freeScanners.add(scanner);
}
}
private static GTKScanner createScanner() {
GTKScanner scanner = new GTKScanner();
// configure scanner for GTK rc files
scanner.caseSensitive = true;
scanner.scanBinary = true;
scanner.scanHexDollar = true;
scanner.symbol2Token = true;
for (int i = 0; i < symbols.length; i++) {
scanner.addSymbol(symbols[i].name, symbols[i].val);
}
return scanner;
}
public void loadStylesInto(GTKStyleFactory factory) {
Assignment[] assigns = new Assignment[assignments.size()];
assigns = (Assignment[])assignments.toArray(assigns);
for (int i = 0; i < assigns.length; i++) {
Assignment assign = assigns[i];
GTKStyle style = assign.info.toGTKStyle();
if (style != StyleInfo.EMPTY_STYLE) {
try {
factory.addStyle(style, assign.pattern, assign.type);
} catch (PatternSyntaxException pse) {
// should not happen
}
}
}
}
public HashMap getGTKSettings() {
return settings;
}
public void clearParser() {
namedStyles.clear();
settings.clear();
assignments.clear();
dirStack.clear();
pixmapPaths = null;
}
//------------------------- Parsing Methods ------------------------------//
private void parseCurrent() throws IOException {
while (true) {
if (scanner.peekNextToken() == GTKScanner.TOKEN_EOF) {
break;
}
int expected = parseStatement();
if (expected != GTKScanner.TOKEN_NONE) {
String symbolName = null;
String msg = null;
if (scanner.currScope == 0) {
Symbol lookup;
lookup = getSymbol(expected);
if (lookup != null) {
msg = "e.g. `" + lookup.name + "'";
}
lookup = getSymbol(scanner.currToken);
if (lookup != null) {
symbolName = lookup.name;
}
}
scanner.unexpectedToken(expected, symbolName, msg, true);
break;
}
}
}
private int parseStatement() throws IOException {
int token;
token = scanner.peekNextToken();
if (token == SYMBOL_INCLUDE.val) {
return parseInclude();
} else if (token == SYMBOL_STYLE.val) {
return parseStyle();
} else if (token == SYMBOL_BINDING.val) {
return parseBinding();
} else if (token == SYMBOL_PIXMAP_PATH.val) {
return parsePixmapPath();
} else if (token == SYMBOL_WIDGET.val
|| token == SYMBOL_WIDGET_CLASS.val
|| token == SYMBOL_CLASS.val) {
return parseAssignment(token);
} else if (token == SYMBOL_MODULE_PATH.val) {
return parseModulePath();
} else if (token == SYMBOL_IM_MODULE_FILE.val) {
return parseIMModuleFile();
} else if (token == GTKScanner.TOKEN_IDENTIFIER) {
return parseIdentifier();
}
scanner.getToken();
return SYMBOL_STYLE.val;
}
private int parseInclude() throws IOException {
int token;
token = scanner.getToken();
if (token != SYMBOL_INCLUDE.val) {
return SYMBOL_INCLUDE.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
File parseFile = null;
String name = scanner.currValue.stringVal;
File file = new File(name);
if (file.isAbsolute()) {
parseFile = file;
} else {
File[] dirs = new File[dirStack.size()];
dirs = (File[])dirStack.toArray(dirs);
for (int i = dirs.length - 1; i >= 0; i--) {
file = new File(dirs[i], name);
if (file.exists()) {
parseFile = file;
break;
}
}
}
if (parseFile == null) {
scanner.printMessage("Unable to find include file: \"" + name + "\"", false);
} else {
// save the current scanner and recurse
GTKScanner savedScanner = scanner;
try {
parseFile(file, name);
} catch (IOException ioe) {
savedScanner.printMessage("(" + ioe.toString()
+ ") while parsing include file: \""
+ name
+ "\"", false);
}
// restore the scanner
scanner = savedScanner;
}
return GTKScanner.TOKEN_NONE;
}
private int parseStyle() throws IOException {
int token;
token = scanner.getToken();
if (token != SYMBOL_STYLE.val) {
return SYMBOL_STYLE.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
StyleInfo info = (StyleInfo)namedStyles.get(scanner.currValue.stringVal);
if (info == null) {
info = new StyleInfo(scanner.currValue.stringVal);
}
token = scanner.peekNextToken();
if (token == GTKScanner.TOKEN_EQUAL_SIGN) {
token = scanner.getToken();
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
StyleInfo parent = (StyleInfo)namedStyles.get(scanner.currValue.stringVal);
if (parent != null) {
info.copyDataFrom(parent);
}
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_LEFT_CURLY) {
return GTKScanner.TOKEN_LEFT_CURLY;
}
token = scanner.peekNextToken();
while (token != GTKScanner.TOKEN_RIGHT_CURLY) {
if (token == SYMBOL_FG.val
|| token == SYMBOL_BG.val
|| token == SYMBOL_TEXT.val
|| token == SYMBOL_BASE.val) {
token = parseColorSetting(token, info);
} else if (token == SYMBOL_XTHICKNESS.val
|| token == SYMBOL_YTHICKNESS.val) {
token = parseThickness(token, info);
} else if (token == SYMBOL_BG_PIXMAP.val) {
token = parseBGPixmap(info);
} else if (token == SYMBOL_FONT.val
|| token == SYMBOL_FONTSET.val
|| token == SYMBOL_FONT_NAME.val) {
token = parseFont(token, info);
} else if (token == SYMBOL_ENGINE.val) {
token = parseEngine(info);
} else if (token == SYMBOL_STOCK.val) {
token = parseStock(info);
} else if (token == GTKScanner.TOKEN_IDENTIFIER) {
token = parseIdentifierInStyle(info);
} else {
scanner.getToken();
token = GTKScanner.TOKEN_RIGHT_CURLY;
}
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
token = scanner.peekNextToken();
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_RIGHT_CURLY) {
return GTKScanner.TOKEN_RIGHT_CURLY;
}
namedStyles.put(info.name, info);
return GTKScanner.TOKEN_NONE;
}
private int parseBinding() throws IOException {
int token;
token = scanner.getToken();
if (token != SYMBOL_BINDING.val) {
return SYMBOL_BINDING.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
token = ignoreBlock();
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
scanner.printMessage("Binding specification is unsupported, ignoring", false);
return GTKScanner.TOKEN_NONE;
}
private int parsePixmapPath() throws IOException {
int token;
token = scanner.getToken();
if (token != SYMBOL_PIXMAP_PATH.val) {
return SYMBOL_PIXMAP_PATH.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
pixmapPaths = null;
ArrayList tempPaths = new ArrayList();
StringTokenizer tok = new StringTokenizer(scanner.currValue.stringVal, File.pathSeparator);
while (tok.hasMoreTokens()) {
String path = tok.nextToken();
File file = new File(path);
if (file.isAbsolute()) {
tempPaths.add(file);
} else {
scanner.printMessage("Pixmap path element: \"" + path + "\" must be absolute", false);
}
}
if (tempPaths.size() > 0) {
pixmapPaths = new File[tempPaths.size()];
pixmapPaths = (File[])tempPaths.toArray(pixmapPaths);
}
return GTKScanner.TOKEN_NONE;
}
private int parseAssignment(int expVal) throws IOException {
int token;
token = scanner.getToken();
if (token != expVal) {
return expVal;
}
int type;
String pattern;
StyleInfo info;
boolean isBinding;
if (token == SYMBOL_WIDGET.val) {
type = GTKStyleFactory.WIDGET;
} else if (token == SYMBOL_WIDGET_CLASS.val) {
type = GTKStyleFactory.WIDGET_CLASS;
} else if (token == SYMBOL_CLASS.val) {
type = GTKStyleFactory.CLASS;
} else {
return SYMBOL_WIDGET_CLASS.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
pattern = scanner.currValue.stringVal;
token = scanner.getToken();
if (token == SYMBOL_STYLE.val) {
isBinding = false;
} else if (token == SYMBOL_BINDING.val) {
isBinding = true;
} else {
return SYMBOL_STYLE.val;
}
token = scanner.peekNextToken();
if (token == ':') {
token = scanner.getToken();
token = scanner.getToken();
if (token != SYMBOL_LOWEST.val
&& token != SYMBOL_GTK.val
&& token != SYMBOL_APPLICATION.val
&& token != SYMBOL_THEME.val
&& token != SYMBOL_RC.val
&& token != SYMBOL_HIGHEST.val) {
return SYMBOL_APPLICATION.val;
}
scanner.printMessage("Priority specification is unsupported, ignoring", false);
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
// PENDING(shannonh) - When we start handling priority, the information will
// probably be stored as part of an Assignment here
if (isBinding) {
// PENDING(shannonh) - Key binding support
scanner.printMessage("Binding assignment is unsupported, ignoring", false);
} else {
info = (StyleInfo)namedStyles.get(scanner.currValue.stringVal);
if (info == null) {
return GTKScanner.TOKEN_STRING;
}
Assignment assignment = new Assignment(type, pattern, info);
assignments.add(assignment);
}
return GTKScanner.TOKEN_NONE;
}
private int parseModulePath() throws IOException {
int token;
token = scanner.getToken();
if (token != SYMBOL_MODULE_PATH.val) {
return SYMBOL_MODULE_PATH.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
scanner.printMessage("module_path directive is now ignored", false);
return GTKScanner.TOKEN_NONE;
}
private int parseIMModuleFile() throws IOException {
int token;
token = scanner.getToken();
if (token != SYMBOL_IM_MODULE_FILE.val) {
return SYMBOL_IM_MODULE_FILE.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
scanner.printMessage("im_module_file directive is unsupported, ignoring", false);
return GTKScanner.TOKEN_NONE;
}
private int parseIdentifier() throws IOException {
int token;
token = scanner.getToken();
if (token != GTKScanner.TOKEN_IDENTIFIER) {
return GTKScanner.TOKEN_IDENTIFIER;
}
String prop;
Object[] value = new Object[1];
StringBuffer buf = new StringBuffer(scanner.currValue.stringVal);
String validChars = GTKScanner.CHARS_A_2_Z
+ GTKScanner.CHARS_a_2_z
+ GTKScanner.CHARS_DIGITS
+ "-";
// some weird logic that GTK does
int len = buf.length();
for (int i = 0; i < len; i++) {
if (validChars.indexOf(buf.charAt(i)) == -1) {
buf.setCharAt(i, '-');
}
}
prop = buf.toString().intern();
token = parsePropertyAssignment(value);
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
settings.put(prop, value[0]);
return GTKScanner.TOKEN_NONE;
}
private int parseColorSetting(int expVal, StyleInfo info) throws IOException {
int token;
token = scanner.getToken();
if (token != expVal) {
return expVal;
}
Color[] cols = null;
if (token == SYMBOL_FG.val) {
cols = info.fg;
} else if (token == SYMBOL_BG.val) {
cols = info.bg;
} else if (token == SYMBOL_TEXT.val) {
cols = info.text;
} else if (token == SYMBOL_BASE.val) {
cols = info.base;
} else {
return SYMBOL_FG.val;
}
int[] state = new int[1];
token = parseState(state);
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_EQUAL_SIGN) {
return GTKScanner.TOKEN_EQUAL_SIGN;
}
return parseColor(scanner, cols, state[0]);
}
private int parseState(int[] retVal) throws IOException {
int token;
token = scanner.getToken();
if (token != GTKScanner.TOKEN_LEFT_BRACE) {
return GTKScanner.TOKEN_LEFT_BRACE;
}
token = scanner.getToken();
if (token == SYMBOL_NORMAL.val) {
retVal[0] = StyleInfo.NORMAL;
} else if (token == SYMBOL_ACTIVE.val) {
retVal[0] = StyleInfo.ACTIVE;
} else if (token == SYMBOL_PRELIGHT.val) {
retVal[0] = StyleInfo.PRELIGHT;
} else if (token == SYMBOL_SELECTED.val) {
retVal[0] = StyleInfo.SELECTED;
} else if (token == SYMBOL_INSENSITIVE.val) {
retVal[0] = StyleInfo.INSENSITIVE;
} else {
return SYMBOL_NORMAL.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_RIGHT_BRACE) {
return GTKScanner.TOKEN_RIGHT_BRACE;
}
return GTKScanner.TOKEN_NONE;
}
// this is static, and takes a scanner as a parameter, so that it can
// be used in other places that need to parse colors
static int parseColor(GTKScanner scanner, Color[] colors, int index)
throws IOException {
int token;
long lVal;
double dVal;
float red;
float green;
float blue;
token = scanner.getToken();
switch(token) {
case GTKScanner.TOKEN_LEFT_CURLY:
token = scanner.getToken();
if (token == GTKScanner.TOKEN_INT) {
red = javaColorVal(scanner.currValue.longVal);
} else if (token == GTKScanner.TOKEN_FLOAT) {
red = javaColorVal(scanner.currValue.doubleVal);
} else {
return GTKScanner.TOKEN_FLOAT;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_COMMA) {
return GTKScanner.TOKEN_COMMA;
}
token = scanner.getToken();
if (token == GTKScanner.TOKEN_INT) {
green = javaColorVal(scanner.currValue.longVal);
} else if (token == GTKScanner.TOKEN_FLOAT) {
green = javaColorVal(scanner.currValue.doubleVal);
} else {
return GTKScanner.TOKEN_FLOAT;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_COMMA) {
return GTKScanner.TOKEN_COMMA;
}
token = scanner.getToken();
if (token == GTKScanner.TOKEN_INT) {
blue = javaColorVal(scanner.currValue.longVal);
} else if (token == GTKScanner.TOKEN_FLOAT) {
blue = javaColorVal(scanner.currValue.doubleVal);
} else {
return GTKScanner.TOKEN_FLOAT;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_RIGHT_CURLY) {
return GTKScanner.TOKEN_RIGHT_CURLY;
}
colors[index] = new ColorUIResource(red, green, blue);
break;
case GTKScanner.TOKEN_STRING:
Color color = parseColorString(scanner.currValue.stringVal);
if (color == null) {
scanner.printMessage("Invalid color constant '" +
scanner.currValue.stringVal
+ "'", false);
return GTKScanner.TOKEN_STRING;
}
colors[index] = color;
break;
default:
return GTKScanner.TOKEN_STRING;
}
return GTKScanner.TOKEN_NONE;
}
static Color parseColorString(String str) {
if (str.charAt(0) == '#') {
str = str.substring(1);
int i = str.length();
if (i < 3 || i > 12 || (i % 3) != 0) {
return null;
}
i /= 3;
int r;
int g;
int b;
try {
r = Integer.parseInt(str.substring(0, i), 16);
g = Integer.parseInt(str.substring(i, i * 2), 16);
b = Integer.parseInt(str.substring(i * 2, i * 3), 16);
} catch (NumberFormatException nfe) {
return null;
}
if (i == 4) {
return new ColorUIResource(r / 65535.0f, g / 65535.0f, b / 65535.0f);
} else if (i == 1) {
return new ColorUIResource(r / 15.0f, g / 15.0f, b / 15.0f);
} else if (i == 2) {
return new ColorUIResource(r, g, b);
} else {
return new ColorUIResource(r / 4095.0f, g / 4095.0f, b / 4095.0f);
}
} else {
return XColors.lookupColor(str);
}
}
private static float javaColorVal(long col) {
int color = (int)Math.max(Math.min(col, 65535), 0);
return color / 65535.0f;
}
private static float javaColorVal(double col) {
float color = (float)Math.max(Math.min(col, 1.0f), 0.0f);
return color;
}
private int parseThickness(int expVal, StyleInfo info) throws IOException {
int token;
boolean isXThickness;
token = scanner.getToken();
if (token != expVal) {
return expVal;
}
if (token == SYMBOL_XTHICKNESS.val) {
isXThickness = true;
} else if (token == SYMBOL_YTHICKNESS.val) {
isXThickness = false;
} else {
return SYMBOL_XTHICKNESS.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_EQUAL_SIGN) {
return GTKScanner.TOKEN_EQUAL_SIGN;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_INT) {
return GTKScanner.TOKEN_INT;
}
int thickness = (int)scanner.currValue.longVal;
if (isXThickness) {
info.xThickness = thickness;
} else {
info.yThickness = thickness;
}
return GTKScanner.TOKEN_NONE;
}
private int parseBGPixmap(StyleInfo info) throws IOException {
int token;
token = scanner.getToken();
if (token != SYMBOL_BG_PIXMAP.val) {
return SYMBOL_BG_PIXMAP.val;
}
int[] state = new int[1];
token = parseState(state);
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_EQUAL_SIGN) {
return GTKScanner.TOKEN_EQUAL_SIGN;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
String pixmapStr = null;
String str = scanner.currValue.stringVal;
if (str.equals("<none>") || str.equals("<parent>")) {
pixmapStr = str.intern();
} else {
pixmapStr = resolvePixmapPath(str);
}
if (pixmapStr == null) {
scanner.printMessage("Unable to locate image file in pixmap_path: \"" + str + "\"", false);
} else {
info.bgPixmapName[state[0]] = pixmapStr;
}
return GTKScanner.TOKEN_NONE;
}
String resolvePixmapPath(String str) {
// search in pixmap path
if (pixmapPaths != null) {
for (int i = 0; i < pixmapPaths.length; i++) {
File file = new File(pixmapPaths[i], str);
if (file.canRead()) {
return file.getAbsolutePath();
}
}
}
// search in rc directory stack
File[] dirs = new File[dirStack.size()];
dirs = (File[])dirStack.toArray(dirs);
for (int i = dirs.length - 1; i >= 0; i--) {
File file = new File(dirs[i], str);
if (file.canRead()) {
return file.getAbsolutePath();
}
}
return null;
}
private int parseFont(int expVal, StyleInfo info) throws IOException {
int token;
boolean isPango;
token = scanner.getToken();
if (token != expVal) {
return expVal;
}
if (token == SYMBOL_FONT_NAME.val) {
isPango = true;
} else if (token == SYMBOL_FONT.val
|| token == SYMBOL_FONTSET.val) {
isPango = false;
} else {
return SYMBOL_FONT_NAME.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_EQUAL_SIGN) {
return GTKScanner.TOKEN_EQUAL_SIGN;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
// only need to parse pango font names
if (isPango) {
String pangoName = scanner.currValue.stringVal;
info.font = PangoFonts.lookupFont(pangoName);
}
return GTKScanner.TOKEN_NONE;
}
private GTKEngineParser getParser(String engineName) {
Object o = engineParsers.get(engineName);
if (o == null) {
return null;
}
if (o instanceof GTKEngineParser) {
return (GTKEngineParser)o;
}
GTKEngineParser parser = null;
try {
parser = (GTKEngineParser)Class.forName((String)o).newInstance();
} catch (ClassNotFoundException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
}
if (parser == null) {
// no need to keep trying to load it every time
engineParsers.remove(engineName);
} else {
// replace the name with an instance of a parser
engineParsers.put(engineName, parser);
}
return parser;
}
private int parseEngine(StyleInfo info) throws IOException {
int token;
token = scanner.getToken();
if (token != SYMBOL_ENGINE.val) {
return SYMBOL_ENGINE.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
String engineName = scanner.currValue.stringVal;
// engine "" {} means to use the default engine
if (engineName.length() == 0) {
token = scanner.getToken();
if (token != GTKScanner.TOKEN_LEFT_CURLY) {
return GTKScanner.TOKEN_LEFT_CURLY;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_RIGHT_CURLY) {
return GTKScanner.TOKEN_RIGHT_CURLY;
}
info.engineInfo = null;
return GTKScanner.TOKEN_NONE;
}
GTKEngineParser parser = getParser(engineName);
if (parser == null) {
token = ignoreBlock();
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
scanner.printMessage("Engine \"" + engineName + "\" is unsupported, ignoring", false);
} else {
token = scanner.getToken();
if (token != GTKScanner.TOKEN_LEFT_CURLY) {
return GTKScanner.TOKEN_LEFT_CURLY;
}
EngineInfo[] engineInfo = new EngineInfo[1];
// only pass in the existing engine info if it came from this parser
if (info.engineInfo != null && engineName.equals(info.engineInfo.engineName)) {
engineInfo[0] = info.engineInfo;
}
token = parser.parse(scanner, this, engineInfo);
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
// tag the returned engine info with the engine name
if (engineInfo[0] != null) {
engineInfo[0].engineName = engineName;
}
info.engineInfo = engineInfo[0];
}
return GTKScanner.TOKEN_NONE;
}
private int parseStock(StyleInfo info) throws IOException {
String id;
int token;
token = scanner.getToken();
if (token != SYMBOL_STOCK.val) {
return SYMBOL_STOCK.val;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_LEFT_BRACE) {
return GTKScanner.TOKEN_LEFT_BRACE;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
id = scanner.currValue.stringVal;
token = scanner.getToken();
if (token != GTKScanner.TOKEN_RIGHT_BRACE) {
return GTKScanner.TOKEN_RIGHT_BRACE;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_EQUAL_SIGN) {
return GTKScanner.TOKEN_EQUAL_SIGN;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_LEFT_CURLY) {
return GTKScanner.TOKEN_LEFT_CURLY;
}
ArrayList iconSources = new ArrayList();
// This array will be used first to hold the return value from
// parseIconSource and then the variable will be used in
// converting iconSources to an array.
GTKStyle.GTKIconSource[] sources = new GTKStyle.GTKIconSource[1];
token = scanner.peekNextToken();
while (token != GTKScanner.TOKEN_RIGHT_CURLY) {
token = parseIconSource(sources);
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_COMMA
&& token != GTKScanner.TOKEN_RIGHT_CURLY) {
return GTKScanner.TOKEN_RIGHT_CURLY;
}
if (sources[0] != null) {
iconSources.add(sources[0]);
}
}
if (iconSources.size() != 0) {
sources = new GTKStyle.GTKIconSource[iconSources.size()];
sources = (GTKStyle.GTKIconSource[])iconSources.toArray(sources);
info.addStockItem(id, sources);
}
return GTKScanner.TOKEN_NONE;
}
private GTKStyle.GTKIconSource createIconSource(String path,
int direction,
int state,
String size) {
String resolvedPath = resolvePixmapPath(path);
if (resolvedPath != null) {
return new GTKStyle.GTKIconSource(resolvedPath, direction, state, size);
}
return null;
}
private int parseIconSource(GTKStyle.GTKIconSource[] retVal) throws IOException {
int token;
String pixmapStr = null;
int direction = GTKConstants.UNDEFINED;
int state = GTKConstants.UNDEFINED;
String size = null;
token = scanner.getToken();
if (token != GTKScanner.TOKEN_LEFT_CURLY) {
return GTKScanner.TOKEN_LEFT_CURLY;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
pixmapStr = scanner.currValue.stringVal;
token = scanner.getToken();
if (token == GTKScanner.TOKEN_RIGHT_CURLY) {
retVal[0] = createIconSource(pixmapStr, direction, state, size);
return GTKScanner.TOKEN_NONE;
} else if (token != GTKScanner.TOKEN_COMMA) {
return GTKScanner.TOKEN_COMMA;
}
token = scanner.getToken();
if (token == SYMBOL_RTL.val) {
direction = GTKConstants.RTL;
} else if (token == SYMBOL_LTR.val) {
direction = GTKConstants.LTR;
} else if (token == '*') {
// nothing
} else {
return SYMBOL_RTL.val;
}
token = scanner.getToken();
if (token == GTKScanner.TOKEN_RIGHT_CURLY) {
retVal[0] = createIconSource(pixmapStr, direction, state, size);
return GTKScanner.TOKEN_NONE;
} else if (token != GTKScanner.TOKEN_COMMA) {
return GTKScanner.TOKEN_COMMA;
}
token = scanner.getToken();
if (token == SYMBOL_NORMAL.val) {
state = SynthConstants.ENABLED;
} else if (token == SYMBOL_ACTIVE.val) {
state = SynthConstants.PRESSED;
} else if (token == SYMBOL_PRELIGHT.val) {
state = SynthConstants.MOUSE_OVER;
} else if (token == SYMBOL_SELECTED.val) {
state = SynthConstants.SELECTED;
} else if (token == SYMBOL_INSENSITIVE.val) {
state = SynthConstants.DISABLED;
} else if (token == '*') {
// nothing
} else {
return SYMBOL_PRELIGHT.val;
}
token = scanner.getToken();
if (token == GTKScanner.TOKEN_RIGHT_CURLY) {
retVal[0] = createIconSource(pixmapStr, direction, state, size);
return GTKScanner.TOKEN_NONE;
} else if (token != GTKScanner.TOKEN_COMMA) {
return GTKScanner.TOKEN_COMMA;
}
token = scanner.getToken();
if (token != '*') {
if (token != GTKScanner.TOKEN_STRING) {
return GTKScanner.TOKEN_STRING;
}
size = scanner.currValue.stringVal;
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_RIGHT_CURLY) {
return GTKScanner.TOKEN_RIGHT_CURLY;
}
retVal[0] = createIconSource(pixmapStr, direction, state, size);
return GTKScanner.TOKEN_NONE;
}
private int parseIdentifierInStyle(StyleInfo info) throws IOException {
int token;
token = scanner.getToken();
if (token != GTKScanner.TOKEN_IDENTIFIER
|| scanner.currValue.stringVal.charAt(0) < 'A'
|| scanner.currValue.stringVal.charAt(0) > 'Z') {
return GTKScanner.TOKEN_IDENTIFIER;
}
String klass;
String prop;
Object[] value = new Object[1];
klass = scanner.currValue.stringVal.intern();
// check the next two tokens to make sure they're both ':'
if (scanner.getToken() != ':' || scanner.getToken() != ':') {
return ':';
}
token = scanner.getToken();
if (token != GTKScanner.TOKEN_IDENTIFIER) {
return GTKScanner.TOKEN_IDENTIFIER;
}
StringBuffer buf = new StringBuffer(scanner.currValue.stringVal);
String validChars = GTKScanner.CHARS_A_2_Z
+ GTKScanner.CHARS_a_2_z
+ GTKScanner.CHARS_DIGITS
+ "-";
// some weird logic that GTK does
int len = buf.length();
for (int i = 0; i < len; i++) {
if (validChars.indexOf(buf.charAt(i)) == -1) {
buf.setCharAt(i, '-');
}
}
prop = buf.toString().intern();
token = parsePropertyAssignment(value);
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
// for Strings or StringBuffers (representing complex values) we check
// for a parser that might want to parse the value
if (value[0] instanceof String || value[0] instanceof StringBuffer) {
Object val = value[0];
PropertyParser pp = PropertyParser.getParserFor(prop);
if (pp == null) {
// just add the property (but convert to String first if StringBuffer)
info.addProperty(klass, prop,
val instanceof String ? val : val.toString());
} else {
String toParse;
if (val instanceof String) {
if (pp.needSimpleStringsEscaped()) {
toParse = '"' + escapeString((String) val) + '"';
} else {
toParse = (String)val;
}
} else {
toParse = val.toString();
}
Object parsedVal = pp.parse(toParse);
if (parsedVal == null) {
scanner.printMessage("Failed to parse property value \"" + toParse + "\" for `"
+ klass + "::" + prop + "'", false);
} else {
info.addProperty(klass, prop, parsedVal);
}
}
} else {
info.addProperty(klass, prop, value[0]);
}
return GTKScanner.TOKEN_NONE;
}
private int parsePropertyAssignment(Object[] retVal) throws IOException {
int token;
token = scanner.getToken();
if (token != '=') {
return '=';
}
// save the scanner mode
boolean scanIdentifier = scanner.scanIdentifier;
boolean scanSymbols = scanner.scanSymbols;
boolean identifier2String = scanner.identifier2String;
boolean char2Token = scanner.char2Token;
boolean scanIdentifierNULL = scanner.scanIdentifierNULL;
boolean numbers2Int = scanner.numbers2Int;
// modify the scanner mode for our purposes
scanner.scanIdentifier = true;
scanner.scanSymbols = false;
scanner.identifier2String = false;
scanner.char2Token = true;
scanner.scanIdentifierNULL = false;
scanner.numbers2Int = true;
boolean negate = false;
if (scanner.peekNextToken() == '-') {
scanner.getToken();
negate = true;
}
token = scanner.peekNextToken();
switch(token) {
case GTKScanner.TOKEN_INT:
scanner.getToken();
retVal[0] = new Long(negate ? -scanner.currValue.longVal : scanner.currValue.longVal);
token = GTKScanner.TOKEN_NONE;
break;
case GTKScanner.TOKEN_FLOAT:
scanner.getToken();
retVal[0] = new Double(negate ? -scanner.currValue.doubleVal : scanner.currValue.doubleVal);
token = GTKScanner.TOKEN_NONE;
break;
case GTKScanner.TOKEN_STRING:
scanner.getToken();
if (negate) {
token = GTKScanner.TOKEN_INT;
} else {
retVal[0] = scanner.currValue.stringVal;
token = GTKScanner.TOKEN_NONE;
}
break;
case GTKScanner.TOKEN_IDENTIFIER:
case GTKScanner.TOKEN_LEFT_PAREN:
case GTKScanner.TOKEN_LEFT_CURLY:
case GTKScanner.TOKEN_LEFT_BRACE:
if (negate) {
token = GTKScanner.TOKEN_INT;
} else {
StringBuffer result = new StringBuffer();
token = parseComplexPropVal(result, GTKScanner.TOKEN_EOF);
if (token == GTKScanner.TOKEN_NONE) {
result.append(' ');
// return the StringBuffer directly to indicate a complex value
retVal[0] = result;
}
}
break;
default:
scanner.getToken();
token = GTKScanner.TOKEN_INT;
break;
}
// restore the scanner mode
scanner.scanIdentifier = scanIdentifier;
scanner.scanSymbols = scanSymbols;
scanner.identifier2String = identifier2String;
scanner.char2Token = char2Token;
scanner.scanIdentifierNULL = scanIdentifierNULL;
scanner.numbers2Int = numbers2Int;
return token;
}
private int parseComplexPropVal(StringBuffer into, int delim) throws IOException {
int token;
token = scanner.getToken();
switch(token) {
case GTKScanner.TOKEN_INT:
into.append(" 0x");
into.append(Long.toHexString(scanner.currValue.longVal));
break;
case GTKScanner.TOKEN_FLOAT:
into.append(' ');
into.append(scanner.currValue.doubleVal);
break;
case GTKScanner.TOKEN_STRING:
into.append(" \"");
into.append(escapeString(scanner.currValue.stringVal));
into.append('"');
break;
case GTKScanner.TOKEN_IDENTIFIER:
into.append(' ');
into.append(scanner.currValue.stringVal);
break;
case GTKScanner.TOKEN_LEFT_PAREN:
into.append(' ');
into.append((char)token);
token = parseComplexPropVal(into, GTKScanner.TOKEN_RIGHT_PAREN);
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
break;
case GTKScanner.TOKEN_LEFT_CURLY:
into.append(' ');
into.append((char)token);
token = parseComplexPropVal(into, GTKScanner.TOKEN_RIGHT_CURLY);
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
break;
case GTKScanner.TOKEN_LEFT_BRACE:
into.append(' ');
into.append((char)token);
token = parseComplexPropVal(into, GTKScanner.TOKEN_RIGHT_BRACE);
if (token != GTKScanner.TOKEN_NONE) {
return token;
}
break;
default:
if (token >= GTKScanner.TOKEN_NONE || token <= GTKScanner.TOKEN_EOF) {
return delim != GTKScanner.TOKEN_EOF ? delim : GTKScanner.TOKEN_STRING;
}
into.append(' ');
into.append((char)token);
if (token == delim) {
return GTKScanner.TOKEN_NONE;
}
}
if (delim == GTKScanner.TOKEN_EOF) {
return GTKScanner.TOKEN_NONE;
} else {
return parseComplexPropVal(into, delim);
}
}
private String escapeString(String source) {
int len = source.length();
StringBuffer result = new StringBuffer(len * 4);
for (int i = 0; i < len; i++) {
char ch = source.charAt(i);
switch(ch) {
case '\b':
result.append("\\b");
break;
case '\f':
result.append("\\f");
break;
case '\n':
result.append("\\n");
break;
case '\r':
result.append("\\r");
break;
case '\t':
result.append("\\t");
break;
case '\\':
result.append("\\\\");
break;
case '"':
result.append("\\\"");
break;
default:
if (ch < ' ' || ch > '~') {
result.append('\\');
result.append(Integer.toOctalString(ch));
} else {
result.append((char)ch);
}
break;
}
}
return result.toString();
}
private int ignoreBlock() throws IOException {
int token;
token = scanner.getToken();
if (token != GTKScanner.TOKEN_LEFT_CURLY) {
return GTKScanner.TOKEN_LEFT_CURLY;
}
int curlys = 1;
while (curlys > 0) {
token = scanner.getToken();
switch(token) {
case GTKScanner.TOKEN_EOF:
return GTKScanner.TOKEN_RIGHT_CURLY;
case GTKScanner.TOKEN_LEFT_CURLY:
curlys++;
break;
case GTKScanner.TOKEN_RIGHT_CURLY:
curlys--;
break;
default:
// ignore
}
}
return GTKScanner.TOKEN_NONE;
}
// for testing
public static void main(String[] args) {
if (args.length == 0) {
System.err.println("Usage: java GTKParser <gtkrc file> <gtkrc file>....");
System.exit(1);
}
GTKParser parser = new GTKParser();
try {
for (int i = 0; i < args.length; i++) {
parser.parseFile(new File(args[i]), args[i]);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
parser.printNamedStyles();
System.out.println();
parser.printSettings();
System.out.println();
parser.printAssignments();
}
// for testing
private void printNamedStyles() {
System.out.println("===== Named Styles =====");
StyleInfo[] infos = new StyleInfo[namedStyles.size()];
infos = (StyleInfo[])namedStyles.values().toArray(infos);
for (int i = 0; i < infos.length; i++) {
StyleInfo info = infos[i];
System.out.println("NAME: " + info.name);
GTKStyle style = info.toGTKStyle();
System.out.println(style == StyleInfo.EMPTY_STYLE ? "EMPTY_STYLE" : style.toString());
System.out.println("---------------------------");
}
}
// for testing
private void printSettings() {
System.out.println("===== GTK Settings =====");
Iterator iter = settings.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}
// for testing
private void printAssignments() {
System.out.println("===== Assignments =====");
Assignment[] assigns = new Assignment[assignments.size()];
assigns = (Assignment[])assignments.toArray(assigns);
for (int i = 0; i < assigns.length; i++) {
System.out.println(assigns[i]);
}
}
}
|