/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.examples.javaviewer;


import org.eclipse.swt.*;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import java.util.*;
import java.io.*;

class JavaLineStyler implements LineStyleListener {
	JavaScanner scanner = new JavaScanner();
	int[] tokenColors;
	Color[] colors;
	Vector blockComments = new Vector();

	public static final int EOF= -1;
	public static final int EOL= 10;

	public static final int WORD=		0;
	public static final int WHITE=		1;
	public static final int KEY=			2;
	public static final int COMMENT=		3;	
	public static final int STRING=		5;
	public static final int OTHER=		6;
	public static final int NUMBER=		7;

	public static final int MAXIMUM_TOKEN= 8;

public JavaLineStyler() {
	initializeColors();
	scanner = new JavaScanner();
}

Color getColor(int type) {
	if (type < 0 || type >= tokenColors.length) {
		return null;
	}
	return colors[tokenColors[type]];
}

boolean inBlockComment(int start, int end) {
	for (int i=0; i<blockComments.size(); i++) {
		int[] offsets = (int[])blockComments.elementAt(i);
		// start of comment in the line
		if ((offsets[0] >= start) && (offsets[0] <= end)) return true;
		// end of comment in the line
		if ((offsets[1] >= start) && (offsets[1] <= end)) return true;
		if ((offsets[0] <= start) && (offsets[1] >= end)) return true;
	}
	return false;
}

void initializeColors() {
	Display display = Display.getDefault();
	colors= new Color[] {
		new Color(display, new RGB(0, 0, 0)),		// black
		new Color(display, new RGB(255, 0, 0)),	// red
		new Color(display, new RGB(0, 255, 0)),	// green
		new Color(display, new RGB(0,   0, 255))	// blue
	};
	tokenColors= new int[MAXIMUM_TOKEN];
	tokenColors[WORD]=		0;
	tokenColors[WHITE]=		0;
	tokenColors[KEY]=		3; 
	tokenColors[COMMENT]=	1; 
	tokenColors[STRING]= 	2; 
	tokenColors[OTHER]=		0;
	tokenColors[NUMBER]=	0;
}

void disposeColors() {
	for (int i=0;i<colors.length;i++) {
		colors[i].dispose();
	}
}

/**
 * Event.detail			line start offset (input)	
 * Event.text 			line text (input)
 * LineStyleEvent.styles 	Enumeration of StyleRanges, need to be in order. (output)
 * LineStyleEvent.background 	line background color (output)
 */
public void lineGetStyle(LineStyleEvent event) {
	Vector styles = new Vector();
	int token;
	StyleRange lastStyle;
	// If the line is part of a block comment, create one style for the entire line.
	if (inBlockComment(event.lineOffset, event.lineOffset + event.lineText.length())) {
		styles.addElement(new StyleRange(event.lineOffset, event.lineText.length(), getColor(COMMENT), null));
		event.styles = new StyleRange[styles.size()];
		styles.copyInto(event.styles);
		return;
	}
	Color defaultFgColor = ((Control)event.widget).getForeground();
	scanner.setRange(event.lineText);
	token = scanner.nextToken();
	while (token != EOF) {
		if (token == OTHER) {
			// do nothing for non-colored tokens
		} else if (token != WHITE) {
			Color color = getColor(token);
			// Only create a style if the token color is different than the 
			// widget's default foreground color and the token's style is not 
			// bold.  Keywords are bolded.
			if ((!color.equals(defaultFgColor)) || (token == KEY)) {
				StyleRange style = new StyleRange(scanner.getStartOffset() + event.lineOffset, scanner.getLength(), color, null);
				if (token == KEY) {
					style.fontStyle = SWT.BOLD;
				}
				if (styles.isEmpty()) {
					styles.addElement(style);
				} else {
					// Merge similar styles.  Doing so will improve performance.
					lastStyle = (StyleRange)styles.lastElement();
					if (lastStyle.similarTo(style) && (lastStyle.start + lastStyle.length == style.start)) {
						lastStyle.length += style.length;
					} else {
						styles.addElement(style); 
					}
				} 
			} 
		} else if ((!styles.isEmpty()) && ((lastStyle=(StyleRange)styles.lastElement()).fontStyle == SWT.BOLD)) {
			int start = scanner.getStartOffset() + event.lineOffset;
			lastStyle = (StyleRange)styles.lastElement();
			// A font style of SWT.BOLD implies that the last style
			// represents a java keyword.
			if (lastStyle.start + lastStyle.length == start) {
				// Have the white space take on the style before it to 
				// minimize the number of style ranges created and the
				// number of font style changes during rendering.
				lastStyle.length += scanner.getLength();
			}
		} 
		token= scanner.nextToken();
	}
	event.styles = new StyleRange[styles.size()];
	styles.copyInto(event.styles);
}
public void parseBlockComments(String text) {
	blockComments = new Vector();
	StringReader buffer = new StringReader(text);
	int ch;
	boolean blkComment = false;
	int cnt = 0;
	int[] offsets = new int[2];
	boolean done = false;
	
	try {
	while (!done) {
		switch (ch = buffer.read()) {
			case -1 : {
				if (blkComment) {
					offsets[1] = cnt;
					blockComments.addElement(offsets);
				}
				done = true;
				break;
			}
			case '/' : {
				ch = buffer.read();
				if ((ch == '*') && (!blkComment)) {
					offsets = new int[2];
					offsets[0] = cnt;
					blkComment = true;
					cnt++;	
				} else {
					cnt++;
				}						
				cnt++;
				break;
			}
			case '*' : {
				if (blkComment) {
					ch = buffer.read();
					cnt++;
					if (ch == '/') {
						blkComment = false;	
						offsets[1] = cnt;
						blockComments.addElement(offsets);
					}
				}
				cnt++;	
				break;
			}
			default : {
				cnt++;				
				break;
			}
		}
	}		
	} catch(IOException e) {
		// ignore errors
	}
}

/**
 * A simple fuzzy scanner for Java
 */
public class JavaScanner {

	protected Hashtable fgKeys= null;
	protected StringBuffer fBuffer= new StringBuffer();
	protected String fDoc;
	protected int fPos;
	protected int fEnd;
	protected int fStartToken;
	protected boolean fEofSeen= false;

	private String[] fgKeywords= { 
		"abstract",
		"boolean", "break", "byte",
		"case", "catch", "char", "class", "continue",
		"default", "do", "double",
		"else", "extends",
		"false", "final", "finally", "float", "for",
		"if", "implements", "import", "instanceof", "int", "interface",
		"long",
		"native", "new", "null",
		"package", "private", "protected", "public",
		"return",
		"short", "static", "super", "switch", "synchronized",
		"this", "throw", "throws", "transient", "true", "try",
		"void", "volatile",
		"while"
	};

	public JavaScanner() {
		initialize();
	}

	/**
	 * Returns the ending location of the current token in the document.
	 */
	public final int getLength() {
		return fPos - fStartToken;
	}

	/**
	 * Initialize the lookup table.
	 */
	void initialize() {
		fgKeys= new Hashtable();
		Integer k= new Integer(KEY);
		for (int i= 0; i < fgKeywords.length; i++)
			fgKeys.put(fgKeywords[i], k);
	}

	/**
	 * Returns the starting location of the current token in the document.
	 */
	public final int getStartOffset() {
		return fStartToken;
	}

	/**
	 * Returns the next lexical token in the document.
	 */
	public int nextToken() {
		int c;
		fStartToken= fPos;
		while (true) {
			switch (c= read()) {			
			case EOF:
				return EOF;				
			case '/':	// comment
				c= read();
				if (c == '/') {
					while (true) {
						c= read();
						if ((c == EOF) || (c == EOL)) {
							unread(c);
							return COMMENT;
						}
					}
				} else {
					unread(c);
				}
				return OTHER;
			case '\'':	// char const
				character: for(;;) {
					c= read();
					switch (c) {
						case '\'':
							return STRING;
						case EOF:
							unread(c);
							return STRING;
						case '\\':
							c= read();
							break;
						}
				}

			case '"':	// string
				string: for (;;) {
					c= read();
					switch (c) {
						case '"':
							return STRING;
						case EOF:
							unread(c);
							return STRING;
						case '\\':
							c= read();
							break;
						}
				}

			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
				do {
					c= read();
				} while(Character.isDigit((char)c));
				unread(c);
				return NUMBER;
			default:
				if (Character.isWhitespace((char)c)) {
					do {
						c= read();
					} while(Character.isWhitespace((char)c));
					unread(c);
					return WHITE;
				}
				if (Character.isJavaIdentifierStart((char)c)) {
					fBuffer.setLength(0);
					do {
						fBuffer.append((char)c);
						c= read();
					} while(Character.isJavaIdentifierPart((char)c));
					unread(c);
					Integer i= (Integer) fgKeys.get(fBuffer.toString());
					if (i != null)
						return i.intValue();
						return WORD;
				}
				return OTHER;
			}
		}
	}

	/**
	 * Returns next character.
	 */
	protected int read() {
		if (fPos <= fEnd) {
			return fDoc.charAt(fPos++);
		}
		return EOF;
	}

	public void setRange(String text) {
		fDoc= text;
		fPos= 0;
		fEnd= fDoc.length() -1;
	}

	protected void unread(int c) {
		if (c != EOF)
	    	fPos--;
	}
}





}
