FileDocCategorySizeDatePackage
GTKParser.javaAPI DocJava SE 5 API63477Fri Aug 26 14:54:46 BST 2005com.sun.java.swing.plaf.gtk

GTKParser

public class GTKParser extends Object
author
Shannon Hickey
version
1.88 08/10/04

Fields Summary
private ArrayList
freeScanners
private HashMap
namedStyles
private ArrayList
assignments
private HashMap
settings
private File[]
pixmapPaths
private ArrayList
dirStack
private HashMap
engineParsers
private GTKScanner
scanner
private final String
CWD
private static final Symbol
SYMBOL_INVALID
private static final Symbol
SYMBOL_INCLUDE
private static final Symbol
SYMBOL_NORMAL
private static final Symbol
SYMBOL_ACTIVE
private static final Symbol
SYMBOL_PRELIGHT
private static final Symbol
SYMBOL_SELECTED
private static final Symbol
SYMBOL_INSENSITIVE
private static final Symbol
SYMBOL_FG
private static final Symbol
SYMBOL_BG
private static final Symbol
SYMBOL_TEXT
private static final Symbol
SYMBOL_BASE
private static final Symbol
SYMBOL_XTHICKNESS
private static final Symbol
SYMBOL_YTHICKNESS
private static final Symbol
SYMBOL_FONT
private static final Symbol
SYMBOL_FONTSET
private static final Symbol
SYMBOL_FONT_NAME
private static final Symbol
SYMBOL_BG_PIXMAP
private static final Symbol
SYMBOL_PIXMAP_PATH
private static final Symbol
SYMBOL_STYLE
private static final Symbol
SYMBOL_BINDING
private static final Symbol
SYMBOL_BIND
private static final Symbol
SYMBOL_WIDGET
private static final Symbol
SYMBOL_WIDGET_CLASS
private static final Symbol
SYMBOL_CLASS
private static final Symbol
SYMBOL_LOWEST
private static final Symbol
SYMBOL_GTK
private static final Symbol
SYMBOL_APPLICATION
private static final Symbol
SYMBOL_THEME
private static final Symbol
SYMBOL_RC
private static final Symbol
SYMBOL_HIGHEST
private static final Symbol
SYMBOL_ENGINE
private static final Symbol
SYMBOL_MODULE_PATH
private static final Symbol
SYMBOL_IM_MODULE_PATH
private static final Symbol
SYMBOL_IM_MODULE_FILE
private static final Symbol
SYMBOL_STOCK
private static final Symbol
SYMBOL_LTR
private static final Symbol
SYMBOL_RTL
private static final Symbol
SYMBOL_LAST
private static final Symbol[]
symbols
Constructors Summary
public GTKParser()

        freeScanners.add(createScanner());
    
Methods Summary
public voidclearParser()

        namedStyles.clear();
        settings.clear();
        assignments.clear();
        dirStack.clear();
        pixmapPaths = null;
    
private GTKStyle.GTKIconSourcecreateIconSource(java.lang.String path, int direction, int state, java.lang.String size)

        String resolvedPath = resolvePixmapPath(path);

        if (resolvedPath != null) {
            return new GTKStyle.GTKIconSource(resolvedPath, direction, state, size);
        }
        
        return null;
    
private static GTKScannercreateScanner()

        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;
    
private java.lang.StringescapeString(java.lang.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();
    
public java.util.HashMapgetGTKSettings()

        return settings;
    
private GTKEngineParsergetParser(java.lang.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 static com.sun.java.swing.plaf.gtk.GTKParser$SymbolgetSymbol(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;
    
private intignoreBlock()

        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;
    
private static floatjavaColorVal(long col)

        int color = (int)Math.max(Math.min(col, 65535), 0);
        return color / 65535.0f;
    
private static floatjavaColorVal(double col)

        float color = (float)Math.max(Math.min(col, 1.0f), 0.0f);
        return color;
    
public voidloadStylesInto(com.sun.java.swing.plaf.gtk.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 static voidmain(java.lang.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();
    
private intparseAssignment(int expVal)

        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 intparseBGPixmap(com.sun.java.swing.plaf.gtk.GTKParser$StyleInfo info)

        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;
    
private intparseBinding()

        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;
    
static intparseColor(GTKScanner scanner, java.awt.Color[] colors, int index)

        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;
    
private intparseColorSetting(int expVal, com.sun.java.swing.plaf.gtk.GTKParser$StyleInfo info)

        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]);
    
static java.awt.ColorparseColorString(java.lang.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 intparseComplexPropVal(java.lang.StringBuffer into, int delim)

        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 voidparseCurrent()

        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 intparseEngine(com.sun.java.swing.plaf.gtk.GTKParser$StyleInfo info)

        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;
    
public voidparseFile(java.io.File file, java.lang.String name)

        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 intparseFont(int expVal, com.sun.java.swing.plaf.gtk.GTKParser$StyleInfo info)

        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 intparseIMModuleFile()

        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 intparseIconSource(GTKStyle.GTKIconSource[] retVal)

        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 intparseIdentifier()

        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 intparseIdentifierInStyle(com.sun.java.swing.plaf.gtk.GTKParser$StyleInfo info)

        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 intparseInclude()

        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 intparseModulePath()

        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 intparsePixmapPath()

        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 intparsePropertyAssignment(java.lang.Object[] retVal)

        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 voidparseReader(java.io.Reader reader, java.lang.String name)

        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 intparseState(int[] retVal)

        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;
    
private intparseStatement()

        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 intparseStock(com.sun.java.swing.plaf.gtk.GTKParser$StyleInfo info)

        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;
    
public voidparseString(java.lang.String str)

        StringReader reader = new StringReader(str);
        parseReader(reader, "-");
    
private intparseStyle()

        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 intparseThickness(int expVal, com.sun.java.swing.plaf.gtk.GTKParser$StyleInfo info)

        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 voidprintAssignments()

        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]);
        }
    
private voidprintNamedStyles()

        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("---------------------------");
        }
    
private voidprintSettings()

        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());
        }
    
java.lang.StringresolvePixmapPath(java.lang.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;