[autocomplete] 06/143: Added support for "markup tags", to be used in languages such as HTML, JSP and XML. Cleaned up code somewhat.

Benjamin Mesing ben at alioth.debian.org
Sat Oct 19 12:53:07 UTC 2013


This is an automated email from the git hooks/post-receive script.

ben pushed a commit to branch master
in repository autocomplete.

commit 9eb21291a56299f8f2219b56d2bee357ac553cfc
Author: bobbylight <robert at fifesoft.com>
Date:   Wed Jan 7 05:20:36 2009 +0000

    Added support for "markup tags", to be used in languages such as HTML, JSP and XML.  Cleaned up code somewhat.
---
 .../autocomplete/AbstractCompletionProvider.java   |   36 +-
 .../ui/autocomplete/AutoCompleteDescWindow.java    |   37 +-
 .../ui/autocomplete/AutoCompletePopupWindow.java   |   32 +-
 src/org/fife/ui/autocomplete/AutoCompletion.java   |   38 ++
 src/org/fife/ui/autocomplete/BasicCompletion.java  |   35 +-
 ...etionProvider.java => CCompletionProvider.java} |  150 ++++++--
 src/org/fife/ui/autocomplete/Completion.java       |    2 +-
 .../ui/autocomplete/CompletionCellRenderer.java    |  289 ++++++++++++++
 .../fife/ui/autocomplete/CompletionXMLParser.java  |  234 +++++++++++
 .../ui/autocomplete/DefaultCompletionProvider.java |  216 +++++++++++
 .../ui/autocomplete/DelegatingCellRenderer.java    |   40 +-
 .../fife/ui/autocomplete/FunctionCompletion.java   |   10 +-
 ...bleCompletion.java => MarkupTagCompletion.java} |  149 ++++---
 .../ProceduralLanguageCellRenderer.java            |  191 ---------
 .../ProceduralLanguageCompletionProvider.java      |  405 --------------------
 .../fife/ui/autocomplete/ShorthandCompletion.java  |   52 ++-
 .../fife/ui/autocomplete/VariableCompletion.java   |   13 +-
 src/org/fife/ui/autocomplete/WordCompletion.java   |   73 ----
 .../ui/autocomplete/WordCompletionProvider.java    |  130 -------
 19 files changed, 1176 insertions(+), 956 deletions(-)

diff --git a/src/org/fife/ui/autocomplete/AbstractCompletionProvider.java b/src/org/fife/ui/autocomplete/AbstractCompletionProvider.java
index e6bf206..3d9f5fe 100644
--- a/src/org/fife/ui/autocomplete/AbstractCompletionProvider.java
+++ b/src/org/fife/ui/autocomplete/AbstractCompletionProvider.java
@@ -27,7 +27,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
-
 import javax.swing.ListCellRenderer;
 import javax.swing.text.JTextComponent;
 
@@ -89,7 +88,7 @@ public abstract class AbstractCompletionProvider implements CompletionProvider {
 	 * @see #clear()
 	 */
 	public void addCompletion(Completion c) {
-		completions.add(c);
+		checkProviderAndAdd(c);
 		Collections.sort(completions);
 	}
 
@@ -99,19 +98,46 @@ public abstract class AbstractCompletionProvider implements CompletionProvider {
 	 *
 	 * @param completions The completions to add.  This cannot be
 	 *        <code>null</code>.
-	 * @throws IllegalArgumentException If the completion's provider isn't
+	 * @throws IllegalArgumentException If a completion's provider isn't
 	 *         this <tt>CompletionProvider</tt>.
 	 * @see #addCompletion(Completion)
 	 * @see #removeCompletion(Completion)
 	 * @see #clear()
 	 */
 	public void addCompletions(List completions) {
-		this.completions.addAll(completions);
+		//this.completions.addAll(completions);
+		for (int i=0; i<completions.size(); i++) {
+			Completion c = (Completion)completions.get(i);
+			checkProviderAndAdd(c);
+		}
 		Collections.sort(this.completions);
 	}
 
 
 	/**
+	 * Adds simple completions for a list of words.
+	 *
+	 * @param words The words.
+	 * @see BasicCompletion
+	 */
+	protected void addWordCompletions(String[] words) {
+		int count = words==null ? 0 : words.length;
+		for (int i=0; i<count; i++) {
+			completions.add(new BasicCompletion(this, words[i]));
+		}
+		Collections.sort(completions);
+	}
+
+
+	protected void checkProviderAndAdd(Completion c) {
+		if (c.getProvider()!=this) {
+			throw new IllegalArgumentException("Invalid CompletionProvider");
+		}
+		completions.add(c);
+	}
+
+
+	/**
 	 * Removes all completions from this provider.  This does not affect
 	 * the parent <tt>CompletionProvider</tt>, if there is one.
 	 *
@@ -170,7 +196,7 @@ public abstract class AbstractCompletionProvider implements CompletionProvider {
 		String text = getAlreadyEnteredText(comp);
 
 		int index = Collections.binarySearch(completions, text, comparator);
-		System.out.println(index + "(" + completions.size() + ")");
+		//System.out.println(index + "(" + completions.size() + ")");
 		if (index<0) {
 			index = -index - 1;
 		}
diff --git a/src/org/fife/ui/autocomplete/AutoCompleteDescWindow.java b/src/org/fife/ui/autocomplete/AutoCompleteDescWindow.java
index 60a63a5..17bd894 100644
--- a/src/org/fife/ui/autocomplete/AutoCompleteDescWindow.java
+++ b/src/org/fife/ui/autocomplete/AutoCompleteDescWindow.java
@@ -25,7 +25,6 @@ package org.fife.ui.autocomplete;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
-import java.awt.Cursor;
 import java.awt.Font;
 import java.awt.SystemColor;
 import java.awt.Window;
@@ -100,12 +99,6 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener {
 	private int historyPos;
 
 	/**
-	 * Used on OS X, where non-editable JEditorPanes don't have their cursors
-	 * made into hand cursors on hyperlink mouseover.
-	 */
-	private Cursor prevCursor;
-
-	/**
 	 * The resource bundle for this window.
 	 */
 	private ResourceBundle bundle;
@@ -116,8 +109,8 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener {
 	private static final String MSG =
 					"org.fife.ui.autocomplete.AutoCompleteDescWindow";
 
-	private static final boolean IS_OS_X = System.getProperty("os.name").
-													indexOf("OS X")>-1;
+//	private static final boolean IS_OS_X = System.getProperty("os.name").
+//													indexOf("OS X")>-1;
 
 
 	/**
@@ -243,7 +236,6 @@ class AutoCompleteDescWindow extends JWindow implements HyperlinkListener {
 	 * @return The default background color.
 	 */
 	protected Color getDefaultBackground() {
-		System.out.println(UIManager.getColor("info"));
 		Color c = UIManager.getColor("ToolTip.background");
 		if (c==null) { // Some LookAndFeels like Nimbus
 			c = UIManager.getColor("info"); // Used by Nimbus (and others)
@@ -289,20 +281,9 @@ System.out.println(descArea.isEnabled() + ", " + e);
 				// No handler - try loading in external browser (Java 6+ only).
 				try {
 					Util.browse(new URI(url.toString()));
-					//descArea.setText(null);
-					//descArea.read(url.openStream(), descArea.getDocument());
-					////descArea.setPage(url);
-					////descArea.setCaretPosition(0); // In case we scrolled
-					////addToHistory(descArea.getText());
 				} catch (/*IO*/URISyntaxException ioe) {
 					UIManager.getLookAndFeel().provideErrorFeedback(descArea);
 					ioe.printStackTrace();
-//					try {
-//						descArea.read(url.openStream(), null);
-//					} catch (IOException ioe2) {
-//						ioe2.printStackTrace();
-//						UIManager.getLookAndFeel().provideErrorFeedback(descArea);
-//					}
 				}
 			}
 			else { // Simple function name text, like in c.xml
@@ -320,20 +301,6 @@ System.out.println(descArea.isEnabled() + ", " + e);
 			}
 		}
 
-		// OS X needs a little push to use the hand cursor for links in a
-		// non-editable JEditorPane
-		else if (IS_OS_X) {
-			boolean entered = HyperlinkEvent.EventType.ENTERED.equals(type);
-			if (entered) {
-				prevCursor = descArea.getCursor();
-				descArea.setCursor(Cursor.getPredefinedCursor(
-											Cursor.HAND_CURSOR));
-			}
-			else {
-				descArea.setCursor(prevCursor);
-			}
-		}
-
 	}
 
 
diff --git a/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java b/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java
index 0dafc7e..c232153 100644
--- a/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java
+++ b/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java
@@ -39,6 +39,7 @@ import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.JWindow;
 import javax.swing.KeyStroke;
+import javax.swing.ListCellRenderer;
 import javax.swing.SwingUtilities;
 import javax.swing.event.CaretEvent;
 import javax.swing.event.CaretListener;
@@ -85,8 +86,6 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener,
 		this.ac = ac;
 		model = new CompletionListModel();//DefaultListModel();
 		list = new JList(model);
-//list.setFixedCellWidth(300);
-//list.setFixedCellHeight(29);
 		list.setCellRenderer(new DelegatingCellRenderer());
 		list.addListSelectionListener(this);
 		list.addMouseListener(this);
@@ -166,6 +165,20 @@ lastLine = -1;
 
 
 	/**
+	 * Returns the default list cell renderer used when a completion provider
+	 * does not supply its own.
+	 *
+	 * @return The default list cell renderer.
+	 * @see #setListCellRenderer(ListCellRenderer)
+	 */
+	public ListCellRenderer getListCellRenderer() {
+		DelegatingCellRenderer dcr = (DelegatingCellRenderer)list.
+															getCellRenderer();
+		return dcr.getFallbackCellRenderer();
+	}
+
+
+	/**
 	 * Returns the selected value, or <code>null</code> if nothing is selected.
 	 *
 	 * @return The selected value.
@@ -368,6 +381,21 @@ lastLine = -1;
 	}
 
 
+	/**
+	 * Sets the default list cell renderer to use when a completion provider
+	 * does not supply its own.
+	 *
+	 * @param renderer The renderer to use.  If this is <code>null</code>,
+	 *        a default renderer is used.
+	 * @see #getListCellRenderer()
+	 */
+	public void setListCellRenderer(ListCellRenderer renderer) {
+		DelegatingCellRenderer dcr = (DelegatingCellRenderer)list.
+													getCellRenderer();
+		dcr.setFallbackCellRenderer(renderer);
+	}
+
+
 	public void setLocationRelativeTo(Rectangle r) {
 
 		boolean showDescWindow = descWindow!=null && ac.getShowDescWindow();
diff --git a/src/org/fife/ui/autocomplete/AutoCompletion.java b/src/org/fife/ui/autocomplete/AutoCompletion.java
index a1eae7d..ffa6d37 100644
--- a/src/org/fife/ui/autocomplete/AutoCompletion.java
+++ b/src/org/fife/ui/autocomplete/AutoCompletion.java
@@ -65,6 +65,12 @@ public class AutoCompletion implements HierarchyListener {
 	private CompletionProvider provider;
 
 	/**
+	 * The renderer to use for the completion choices.  If this is
+	 * <code>null</code>, then a default renderer is used.
+	 */
+	private ListCellRenderer renderer;
+
+	/**
 	 * The handler to use when an external URL is clicked in the help
 	 * documentation.
 	 */
@@ -187,6 +193,18 @@ public class AutoCompletion implements HierarchyListener {
 
 
 	/**
+	 * Returns the default list cell renderer used when a completion provider
+	 * does not supply its own.
+	 *
+	 * @return The default list cell renderer.
+	 * @see #setListCellRenderer(ListCellRenderer)
+	 */
+	public ListCellRenderer getListCellRenderer() {
+		return renderer;
+	}
+
+
+	/**
 	 * Returns the text to replace with in the document.  This is a
 	 * "last-chance" hook for subclasses to make special modifications to the
 	 * completion text inserted.  The default implementation simply returns
@@ -394,6 +412,9 @@ try {
 
 			if (popupWindow==null) {
 				popupWindow = new AutoCompletePopupWindow(parentWindow, this);
+				if (renderer!=null) {
+					popupWindow.setListCellRenderer(renderer);
+				}
 			}
 
 			popupWindow.setCompletions(completions);
@@ -495,6 +516,23 @@ try {
 
 
 	/**
+	 * Sets the default list cell renderer to use when a completion provider
+	 * does not supply its own.
+	 *
+	 * @param renderer The renderer to use.  If this is <code>null</code>,
+	 *        a default renderer is used.
+	 * @see #getListCellRenderer()
+	 */
+	public void setListCellRenderer(ListCellRenderer renderer) {
+		this.renderer = renderer;
+		if (popupWindow!=null) {
+			popupWindow.setListCellRenderer(renderer);
+			hidePopupWindow();
+		}
+	}
+
+
+	/**
 	 * Sets whether the "description window" should be shown beside the
 	 * completion window.
 	 *
diff --git a/src/org/fife/ui/autocomplete/BasicCompletion.java b/src/org/fife/ui/autocomplete/BasicCompletion.java
index a2034fd..d2894b1 100644
--- a/src/org/fife/ui/autocomplete/BasicCompletion.java
+++ b/src/org/fife/ui/autocomplete/BasicCompletion.java
@@ -45,7 +45,21 @@ public class BasicCompletion extends AbstractCompletion {
 	 * @param replacementText The text to replace.
 	 */
 	public BasicCompletion(CompletionProvider provider, String replacementText){
-		this(provider, replacementText, null, null);
+		this(provider, replacementText, null);
+	}
+
+
+	/**
+	 * Constructor.
+	 *
+	 * @param provider The parent completion provider.
+	 * @param replacementText The text to replace.
+	 * @param shortDesc A short description of the completion.  This will be
+	 *        displayed in the completion list.  This may be <code>null</code>.
+	 */
+	public BasicCompletion(CompletionProvider provider, String replacementText,
+							String shortDesc) {
+		this(provider, replacementText, shortDesc, null);
 	}
 
 
@@ -88,20 +102,31 @@ public class BasicCompletion extends AbstractCompletion {
 	 * Returns a string representation of this completion.  If the short
 	 * description is not <code>null</code>, this method will return:
 	 * 
-	 * <code>getReplacementText() + " - " + shortDesc</code>
+	 * <code>getInputText() + " - " + shortDesc</code>
 	 * 
-	 * otherwise, it will return <tt>getReplacementText()</tt>.
+	 * otherwise, it will return <tt>getInputText()</tt>.
 	 *
 	 * @return A string representation of this completion.
 	 */
 	public String toString() {
 		if (shortDesc==null) {
-			return getReplacementText();
+			return getInputText();
 		}
 		else {
-			return getReplacementText() + " - " + shortDesc;
+			return getInputText() + " - " + shortDesc;
 		}
 	}
 
 
+	/**
+	 * Sets the summary for this completion.
+	 *
+	 * @param summary The summary for this completion.
+	 * @see #getSummary()
+	 */
+	public void setSummary(String summary) {
+		this.summary = summary;
+	}
+
+
 }
\ No newline at end of file
diff --git a/src/org/fife/ui/autocomplete/LanguageAwareCompletionProvider.java b/src/org/fife/ui/autocomplete/CCompletionProvider.java
similarity index 50%
rename from src/org/fife/ui/autocomplete/LanguageAwareCompletionProvider.java
rename to src/org/fife/ui/autocomplete/CCompletionProvider.java
index f1ec8ba..4fcea1a 100644
--- a/src/org/fife/ui/autocomplete/LanguageAwareCompletionProvider.java
+++ b/src/org/fife/ui/autocomplete/CCompletionProvider.java
@@ -25,7 +25,6 @@ package org.fife.ui.autocomplete;
 
 import java.util.ArrayList;
 import java.util.List;
-
 import javax.swing.text.JTextComponent;
 
 import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
@@ -35,13 +34,24 @@ import org.fife.ui.rsyntaxtextarea.Token;
 
 
 /**
- * A completion provider that is aware of the programming language it is
- * providing auto-completion for.
+ * A completion provider for the C programming language (and other languages
+ * with similar syntax).  This provider simply delegates to another provider,
+ * depending on whether the caret is in:
+ * 
+ * <ul>
+ *    <li>A string</li>
+ *    <li>A comment</li>
+ *    <li>A documentation comment</li>
+ *    <li>Plain text</li>
+ * </ul>
+ *
+ * This allows for different completion choices in comments than  in code,
+ * for example.
  *
  * @author Robert Futrell
  * @version 1.0
  */
-public class LanguageAwareCompletionProvider extends AbstractCompletionProvider{
+public class CCompletionProvider extends AbstractCompletionProvider{
 
 	/**
 	 * The provider to use when no provider is assigned to a particular token
@@ -50,10 +60,20 @@ public class LanguageAwareCompletionProvider extends AbstractCompletionProvider{
 	private CompletionProvider defaultProvider;
 
 	/**
-	 * The provider to use when completing a string.
+	 * The provider to use when completing in a string.
 	 */
 	private CompletionProvider stringCompletionProvider;
 
+	/**
+	 * The provider to use when completing in a comment.
+	 */
+	private CompletionProvider commentCompletionProvider;
+
+	/**
+	 * The provider to use while in documentation comments.
+	 */
+	private CompletionProvider docCommentCompletionProvider;
+
 
 	/**
 	 * Constructor.
@@ -61,9 +81,9 @@ public class LanguageAwareCompletionProvider extends AbstractCompletionProvider{
 	 * @param defaultProvider The provider to use when no provider is assigned
 	 *        to a particular token type.  This cannot be <code>null</code>.
 	 */
-	public LanguageAwareCompletionProvider(CompletionProvider defaultProvider) {
+	public CCompletionProvider(CompletionProvider defaultProvider) {
 		setDefaultCompletionProvider(defaultProvider);
-		completions = new java.util.ArrayList(0); // TODO: Remove me.
+		completions = new ArrayList(0); // TODO: Remove me.
 	}
 
 
@@ -77,6 +97,17 @@ public class LanguageAwareCompletionProvider extends AbstractCompletionProvider{
 
 
 	/**
+	 * Returns the completion provider to use for comments.
+	 *
+	 * @return The completion provider to use.
+	 * @see #setCommentCompletionProvider(CompletionProvider)
+	 */
+	public CompletionProvider getCommentCompletionProvider() {
+		return commentCompletionProvider;
+	}
+
+
+	/**
 	 * Does the dirty work of creating a list of completions.
 	 *
 	 * @param comp The text component to look in.
@@ -88,7 +119,8 @@ public class LanguageAwareCompletionProvider extends AbstractCompletionProvider{
 			return new ArrayList(0);
 		}
 		CompletionProvider provider = getProviderFor(comp);
-		return provider.getCompletions(comp);
+		return provider!=null ? provider.getCompletions(comp) :
+					new ArrayList(0);
 	}
 
 
@@ -104,50 +136,107 @@ public class LanguageAwareCompletionProvider extends AbstractCompletionProvider{
 	}
 
 
+	/**
+	 * Returns the completion provider to use for documentation comments.
+	 *
+	 * @return The completion provider to use.
+	 * @see #setDocCommentCompletionProvider(CompletionProvider)
+	 */
+	public CompletionProvider getDocCommentCompletionProvider() {
+		return docCommentCompletionProvider;
+	}
+
+
 	private CompletionProvider getProviderFor(JTextComponent comp) {
 
 		RSyntaxTextArea rsta = (RSyntaxTextArea)comp;
 		RSyntaxDocument doc = (RSyntaxDocument)rsta.getDocument();
-		Token t = doc.getTokenListForLine(rsta.getCaretLineNumber());
+		int line = rsta.getCaretLineNumber();
+		Token t = doc.getTokenListForLine(line);
 		if (t==null) {
 			return getDefaultCompletionProvider();
 		}
 
 		int dot = rsta.getCaretPosition();
 		Token curToken = RSyntaxUtilities.getTokenAtOffset(t, dot);
-		int type = 0;
+
 		if (curToken==null) { // At end of the line
-			Token temp = t.getLastPaintableToken();
-			if (temp==null) {
-				return getDefaultCompletionProvider();
+
+			int type = doc.getLastTokenTypeOnLine(line);
+			if (type==Token.NULL) {
+				Token temp = t.getLastPaintableToken();
+				if (temp==null) {
+					return getDefaultCompletionProvider();
+				}
+				type = temp.type;
 			}
-			type = temp.type;
+
+			switch (type) {
+				case Token.ERROR_STRING_DOUBLE:
+					return getStringCompletionProvider();
+				case Token.COMMENT_EOL:
+				case Token.COMMENT_MULTILINE:
+					return getCommentCompletionProvider();
+				case Token.COMMENT_DOCUMENTATION:
+					return getDocCommentCompletionProvider();
+				default:
+					return getDefaultCompletionProvider();
+			}
+
 		}
-		else {
-			type = curToken.type;
+
+		// FIXME: This isn't always a safe assumption.
+		if (dot==curToken.offset) { // At the very beginning of a new token
+			// Need to check previous token for its type before deciding.
+			// Previous token may also be on previous line!
+			return getDefaultCompletionProvider();
 		}
 
-		switch (type) {
+		switch (curToken.type) {
 			case Token.LITERAL_STRING_DOUBLE_QUOTE:
 			case Token.ERROR_STRING_DOUBLE:
 				return getStringCompletionProvider();
-			default:
+			case Token.COMMENT_EOL:
+			case Token.COMMENT_MULTILINE:
+				return getCommentCompletionProvider();
+			case Token.COMMENT_DOCUMENTATION:
+				return getDocCommentCompletionProvider();
+			case Token.WHITESPACE:
+			case Token.IDENTIFIER:
+			case Token.VARIABLE:
+			case Token.PREPROCESSOR:
+			case Token.DATA_TYPE:
+			case Token.FUNCTION:
 				return getDefaultCompletionProvider();
 		}
 
+		return null; // In a token type we can't auto-complete from.
+
 	}
 
 
 	/**
-	 * Returns the completion provider to use for strings.  This may be the
-	 * default provider if one isn't explicitly set for strings.
+	 * Returns the completion provider to use for strings.
 	 *
 	 * @return The completion provider to use.
 	 * @see #setStringCompletionProvider(CompletionProvider)
 	 */
 	public CompletionProvider getStringCompletionProvider() {
-		return stringCompletionProvider==null ? defaultProvider :
-									stringCompletionProvider;
+		return stringCompletionProvider;
+	}
+
+
+	/**
+	 * Sets the comment completion provider.
+	 *
+	 * @param provider The provider to use in comments.
+	 * @see #getCommentCompletionProvider()
+	 */
+	public void setCommentCompletionProvider(CompletionProvider provider) {
+		if (provider==null) {
+			throw new IllegalArgumentException("provider cannot be null");
+		}
+		this.commentCompletionProvider = provider;
 	}
 
 
@@ -167,10 +256,23 @@ public class LanguageAwareCompletionProvider extends AbstractCompletionProvider{
 
 
 	/**
+	 * Sets the documentation comment completion provider.
+	 *
+	 * @param provider The provider to use in comments.
+	 * @see #getDocCommentCompletionProvider()
+	 */
+	public void setDocCommentCompletionProvider(CompletionProvider provider) {
+		if (provider==null) {
+			throw new IllegalArgumentException("provider cannot be null");
+		}
+		this.docCommentCompletionProvider = provider;
+	}
+
+
+	/**
 	 * Sets the completion provider to use while in a string.
 	 *
-	 * @param provider The provider to use.  If this is <code>null</code>, the
-	 *        default completion provider will be used.
+	 * @param provider The provider to use.
 	 * @see #getStringCompletionProvider()
 	 */
 	public void setStringCompletionProvider(CompletionProvider provider) {
diff --git a/src/org/fife/ui/autocomplete/Completion.java b/src/org/fife/ui/autocomplete/Completion.java
index 2afebbe..080e450 100644
--- a/src/org/fife/ui/autocomplete/Completion.java
+++ b/src/org/fife/ui/autocomplete/Completion.java
@@ -40,7 +40,7 @@ public interface Completion {
 	 * into the text component.  The match is case-insensitive.<p>
 	 *
 	 * This is a convenience method for:
-	 * <code>getProvider().getAlreadyEntered(comp)</code>.
+	 * <code>getProvider().getAlreadyEnteredText(comp)</code>.
 	 *
 	 * @param comp The text component.
 	 * @return The already-entered portion of this completion.
diff --git a/src/org/fife/ui/autocomplete/CompletionCellRenderer.java b/src/org/fife/ui/autocomplete/CompletionCellRenderer.java
new file mode 100644
index 0000000..527f546
--- /dev/null
+++ b/src/org/fife/ui/autocomplete/CompletionCellRenderer.java
@@ -0,0 +1,289 @@
+/*
+ * 12/23/2008
+ *
+ * CompletionCellRenderer.java - Cell renderer that can render the standard
+ * completion types like Eclipse or NetBeans does.
+ * Copyright (C) 2008 Robert Futrell
+ * robert_futrell at users.sourceforge.net
+ * http://fifesoft.com/rsyntaxtextarea
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
+ */
+package org.fife.ui.autocomplete;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JList;
+
+
+/**
+ * A cell renderer that adds some pizazz when rendering the standard
+ * {@link Completion} types, like Eclipse and NetBeans do.  Specifically,
+ * this renderer handles:  
+ * 
+ * <ul>
+ *    <li>{@link FunctionCompletion}s</li>
+ *    <li>{@link VariableCompletion}s</li>
+ *    <li>{@link MarkupTagCompletion}s</li>
+ *    <li>{@link ShorthandCompletion}s</li>
+ * </ul>
+ *
+ * @author Robert Futrell
+ * @version 1.0
+ */
+public class CompletionCellRenderer extends DefaultListCellRenderer {
+
+	/**
+	 * The alternating background color.
+	 */
+	private Color altBG;
+
+	/**
+	 * The font to use when rendering items.
+	 */
+	private Font font;
+
+
+	/**
+	 * Constructor.
+	 */
+	public CompletionCellRenderer() {
+		setDisplayFont(new Font("Monospaced", Font.PLAIN, 12));
+		setAlternateBackground(new Color(240,240,240));
+	}
+
+
+	/**
+	 * Returns the background color to use on alternating lines.
+	 *
+	 * @return The altnernate background color.  If this is <code>null</code>,
+	 *         alternating colors are not used.
+	 * @see #setAlternateBackground(Color)
+	 */
+	public Color getAlternateBackground() {
+		return altBG;
+	}
+
+
+	/**
+	 * Returns the font used when rendering completions.
+	 *
+	 * @return The font.  If this is <code>null</code>, then the default list
+	 *         font is used.
+	 * @see #setDisplayFont(Font)
+	 */
+	public Font getDisplayFont() {
+		return font;
+	}
+
+
+	/**
+	 * Returns the renderer.
+	 *
+	 * @param list The list of choices being rendered.
+	 * @param value The {@link Completion} being rendered.
+	 * @param index The index into <code>list</code> being rendered.
+	 * @param selected Whether the item is selected.
+	 * @param hasFocus Whether the item has focus.
+	 */
+	public Component getListCellRendererComponent(JList list, Object value,
+						int index, boolean selected, boolean hasFocus) {
+
+		super.getListCellRendererComponent(list,value,index,selected,hasFocus);
+		setFont(font); // Overrides super's setFont(list.getFont()).
+
+		if (value instanceof FunctionCompletion) {
+			FunctionCompletion fc = (FunctionCompletion)value;
+			prepareForFunctionCompletion(list, fc, index, selected, hasFocus);
+		}
+		else if (value instanceof VariableCompletion) {
+			VariableCompletion vc = (VariableCompletion)value;
+			prepareForVariableCompletion(list, vc, index, selected, hasFocus);
+		}
+		else if (value instanceof MarkupTagCompletion) {
+			MarkupTagCompletion mtc = (MarkupTagCompletion)value;
+			prepareForMarkupTagCompletion(list, mtc, index, selected, hasFocus);
+		}
+		else {
+			Completion c = (Completion)value;
+			prepareForCompletion(list, c, index, selected, hasFocus);
+		}
+
+		if (!selected && (index&1)==0 && altBG!=null) {
+			setBackground(altBG);
+		}
+
+		return this;
+
+	}
+
+
+	/**
+	 * Prepares this renderer to display a shorthand completion.
+	 *
+	 * @param list The list of choices being rendered.
+	 * @param c The completion to render.
+	 * @param index The index into <code>list</code> being rendered.
+	 * @param selected Whether the item is selected.
+	 * @param hasFocus Whether the item has focus.
+	 */
+	protected void prepareForCompletion(JList list,
+		Completion c, int index, boolean selected, boolean hasFocus) {
+
+		StringBuffer sb = new StringBuffer("<html><b><em>");
+		sb.append(c.getInputText());
+		sb.append("</em></b>");
+
+		setText(sb.toString());
+
+	}
+
+
+	/**
+	 * Prepares this renderer to display a function completion. 
+	 *
+	 * @param list The list of choices being rendered.
+	 * @param fc The completion to render.
+	 * @param index The index into <code>list</code> being rendered.
+	 * @param selected Whether the item is selected.
+	 * @param hasFocus Whether the item has focus.
+	 */
+	protected void prepareForFunctionCompletion(JList list,
+		FunctionCompletion fc, int index, boolean selected, boolean hasFocus) {
+
+		StringBuffer sb = new StringBuffer("<html><b><em>");
+		sb.append(fc.getName());
+		sb.append("</em></b>");
+
+		sb.append('(');
+		int paramCount = fc.getParamCount();
+		for (int i=0; i<paramCount; i++) {
+			FunctionCompletion.Parameter param = fc.getParam(i);
+			String type = param.getType();
+			String name = param.getName();
+			if (type!=null) {
+				if (!selected) {
+					sb.append("<font color='#aa0077'>");
+				}
+				sb.append(type);
+				if (!selected) {
+					sb.append("</font>");
+				}
+				if (name!=null) {
+					sb.append(' ');
+				}
+			}
+			if (name!=null) {
+				sb.append(name);
+			}
+			if (i<paramCount-1) {
+				sb.append(", ");
+			}
+		}
+		sb.append(") : ");
+		if (!selected) {
+			sb.append("<font color='#a0a0ff'>");
+		}
+		sb.append(fc.getType());
+		if (!selected) {
+			sb.append("</font>");
+		}
+
+		setText(sb.toString());
+
+	}
+
+
+	/**
+	 * Prepares this renderer to display a markup tag completion.
+	 *
+	 * @param list The list of choices being rendered.
+	 * @param mc The completion to render.
+	 * @param index The index into <code>list</code> being rendered.
+	 * @param selected Whether the item is selected.
+	 * @param hasFocus Whether the item has focus.
+	 */
+	protected void prepareForMarkupTagCompletion(JList list,
+		MarkupTagCompletion mc, int index, boolean selected, boolean hasFocus) {
+
+		StringBuffer sb = new StringBuffer("<html><b><em>");
+		sb.append(mc.getName());
+		sb.append("</em></b>");
+
+		setText(sb.toString());
+
+	}
+
+
+	/**
+	 * Prepares this renderer to display a variable completion.
+	 *
+	 * @param list The list of choices being rendered.
+	 * @param vc The completion to render.
+	 * @param index The index into <code>list</code> being rendered.
+	 * @param selected Whether the item is selected.
+	 * @param hasFocus Whether the item has focus.
+	 */
+	protected void prepareForVariableCompletion(JList list,
+		VariableCompletion vc, int index, boolean selected, boolean hasFocus) {
+
+		StringBuffer sb = new StringBuffer("<html><b><em>");
+		sb.append(vc.getName());
+		sb.append("</em></b>");
+
+		if (vc.getType()!=null) {
+			sb.append(" : ");
+			if (!selected) {
+				sb.append("<font color='#a0a0ff'>");
+			}
+			sb.append(vc.getType());
+			if (!selected) {
+				sb.append("</font>");
+			}
+		}
+
+		setText(sb.toString());
+
+	}
+
+
+	/**
+	 * Sets the background color to use on alternating lines.
+	 *
+	 * @param altBG The new alternate background color.  If this is
+	 *        <code>null</code>, alternating lines will not use different
+	 *        background colors.
+	 * @see #getAlternateBackground()
+	 */
+	public void setAlternateBackground(Color altBG) {
+		this.altBG = altBG;
+	}
+
+
+	/**
+	 * Sets the font to use when rendering completion items.
+	 *
+	 * @param font The font to use.  If this is <code>null</code>, then
+	 *        the default list font is used.
+	 * @see #getDisplayFont()
+	 */
+	public void setDisplayFont(Font font) {
+		this.font = font;
+	}
+
+
+}
\ No newline at end of file
diff --git a/src/org/fife/ui/autocomplete/CompletionXMLParser.java b/src/org/fife/ui/autocomplete/CompletionXMLParser.java
new file mode 100644
index 0000000..5102774
--- /dev/null
+++ b/src/org/fife/ui/autocomplete/CompletionXMLParser.java
@@ -0,0 +1,234 @@
+package org.fife.ui.autocomplete;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.DefaultHandler;
+
+
+/**
+ * Parser for an XML file describing a procedural language such as C.
+ *
+ * @author Robert Futrell
+ * @version 1.0
+ */
+class CompletionXMLParser extends DefaultHandler {
+
+	/**
+	 * The completions found after parsing the XML.
+	 */
+	private List completions;
+
+	/**
+	 * The provider we're getting completions for.
+	 */
+	private CompletionProvider provider;
+
+	private String name;
+	private String type;
+	private String returnType;
+	private StringBuffer desc;
+	private String paramName;
+	private String paramType;
+	private StringBuffer paramDesc;
+	private List params;
+	private String definedIn;
+	private boolean doingKeywords;
+	private boolean inKeyword;
+	private boolean gettingDesc;
+	private boolean gettingParams;
+	private boolean inParam;
+	private boolean gettingParamDesc;
+
+
+	/**
+	 * Constructor.
+	 *
+	 * @param provider The provider to get completions for.
+	 * @see #reset(CompletionProvider)
+	 */
+	public CompletionXMLParser(CompletionProvider provider) {
+		this.provider = provider;
+		completions = new ArrayList();
+		params = new ArrayList(1);
+		desc = new StringBuffer();
+		paramDesc = new StringBuffer();
+	}
+
+
+	/**
+	 * Called when character data inside an element is found.
+	 */
+	public void characters(char[] ch, int start, int length) {
+		if (gettingDesc) {
+			desc.append(ch, start, length);
+		}
+		else if (gettingParamDesc) {
+			paramDesc.append(ch, start, length);
+		}
+	}
+
+
+	private FunctionCompletion createFunctionCompletion() {
+		FunctionCompletion fc = new FunctionCompletion(provider,
+				name, returnType);
+		if (desc.length()>0) {
+			fc.setDescription(desc.toString());
+			desc.setLength(0);
+		}
+		fc.setParams(params);
+		fc.setDefinedIn(definedIn);
+		return fc;
+	}
+
+
+	private MarkupTagCompletion createMarkupTagCompletion() {
+		MarkupTagCompletion mc = new MarkupTagCompletion(provider,
+				name);
+		if (desc.length()>0) {
+			mc.setDescription(desc.toString());
+			desc.setLength(0);
+		}
+		mc.setAttributes(params);
+		mc.setDefinedIn(definedIn);
+		return mc;
+	}
+
+
+	private VariableCompletion createVariableCompletion() {
+		VariableCompletion vc = new VariableCompletion(provider,
+				name, returnType);
+		if (desc.length()>0) {
+			vc.setDescription(desc.toString());
+			desc.setLength(0);
+		}
+		vc.setDefinedIn(definedIn);
+		return vc;
+	}
+
+
+	/**
+	 * Called when an element is closed.
+	 */
+	public void endElement(String uri, String localName, String qName) {
+
+		if ("keywords".equals(qName)) {
+			doingKeywords = false;
+		}
+
+		else if (doingKeywords) {
+
+			if ("keyword".equals(qName)) {
+				Completion c = null;
+				if ("function".equals(type)) {
+					c = createFunctionCompletion();
+				}
+				else if ("constant".equals(type)) {
+					c = createVariableCompletion();
+				}
+				else if ("tag".equals(type)) { // Markup tag, such as HTML
+					c = createMarkupTagCompletion();
+				}
+				else {
+					throw new InternalError("Unexpected type: " + type);
+				}
+				completions.add(c);
+				inKeyword = false;
+			}
+			else if (inKeyword) {
+				if ("desc".equals(qName)) {
+					gettingDesc = false;
+				}
+				else if (gettingParams) {
+					if ("params".equals(qName)) {
+						gettingParams = false;
+					}
+					else if ("param".equals(qName)) {
+						FunctionCompletion.Parameter param =
+							new FunctionCompletion.Parameter(paramType,
+														paramName);
+						if (paramDesc.length()>0) {
+							param.setDescription(paramDesc.toString());
+							paramDesc.setLength(0);
+						}
+						params.add(param);
+						inParam = false;
+					}
+					else if (inParam) {
+						if ("desc".equals(qName)) {
+							gettingParamDesc = false;
+						}
+					}
+				}
+			}
+
+		}
+
+	}
+
+
+	/**
+	 * Returns the completions found after parsing the XML.
+	 *
+	 * @return The completions.
+	 */
+	public List getCompletions() {
+		return completions;
+	}
+
+
+	/**
+	 * Resets this parser to grab more completions.
+	 *
+	 * @param provider The new provider to get completions for.
+	 */
+	public void reset(CompletionProvider provider) {
+		this.provider = provider;
+		completions.clear();
+		doingKeywords = inKeyword = gettingDesc = gettingParams =  inParam = 
+				gettingParamDesc = false;
+	}
+
+
+	/**
+	 * Called when an element starts.
+	 */
+	public void startElement(String uri, String localName, String qName,
+							Attributes attrs) { 
+		if ("keywords".equals(qName)) {
+			doingKeywords = true;
+		}
+		else if (doingKeywords) {
+			if ("keyword".equals(qName)) {
+				name = attrs.getValue("name");
+				type = attrs.getValue("type");
+				returnType = attrs.getValue("returnType");
+				params.clear();
+				definedIn = attrs.getValue("definedIn");
+				inKeyword = true;
+			}
+			else if (inKeyword) {
+				if ("params".equals(qName)) {
+					gettingParams = true;
+				}
+				else if (gettingParams) {
+					if ("param".equals(qName)) {
+						paramName = attrs.getValue("name");
+						paramType = attrs.getValue("type");
+						inParam = true;
+					}
+					if (inParam) {
+						if ("desc".equals(qName)) {
+							gettingParamDesc = true;
+						}
+					}
+				}
+				else if ("desc".equals(qName)) {
+					gettingDesc = true;
+				}
+			}
+		}
+	}
+
+
+}
\ No newline at end of file
diff --git a/src/org/fife/ui/autocomplete/DefaultCompletionProvider.java b/src/org/fife/ui/autocomplete/DefaultCompletionProvider.java
new file mode 100644
index 0000000..4a0dfc9
--- /dev/null
+++ b/src/org/fife/ui/autocomplete/DefaultCompletionProvider.java
@@ -0,0 +1,216 @@
+/*
+ * 12/21/2008
+ *
+ * DefaultCompletionProvider.java - A basic completion provider implementation.
+ * Copyright (C) 2008 Robert Futrell
+ * robert_futrell at users.sourceforge.net
+ * http://fifesoft.com/rsyntaxtextarea
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
+ */
+package org.fife.ui.autocomplete;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.Segment;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.SAXException;
+
+
+/**
+ * A basic completion provider implementation.  This provider has no
+ * understanding of language semantics.  It simply checks the text entered up
+ * to the caret position for a match against known completions.  This is all
+ * that is needed in the marjority of cases.
+ *
+ * @author Robert Futrell
+ * @version 1.0
+ */
+public class DefaultCompletionProvider extends AbstractCompletionProvider {
+
+	protected Segment seg;
+
+
+	/**
+	 * Constructor.  The returned provider will not be aware of any completions.
+	 *
+	 * @see #addCompletion(Completion)
+	 */
+	public DefaultCompletionProvider() {
+		init();
+	}
+
+
+	/**
+	 * Creates a completion provider that provides completion for a simple
+	 * list of words.
+	 *
+	 * @param words The words to offer as completion suggestions.  If this is
+	 *        <code>null</code>, no completions will be known.
+	 * @see WordCompletion
+	 */
+	public DefaultCompletionProvider(String[] words) {
+		init();
+		addWordCompletions(words);
+	}
+
+
+	/**
+	 * Returns the text just before the current caret position that could be
+	 * the start of something auto-completable.<p>
+	 *
+	 * This method returns all characters before the caret that are metched
+	 * by  {@link #isValidChar(char)}.
+	 *
+	 * @param comp The text component.
+	 * @return The text.
+	 */
+	public String getAlreadyEnteredText(JTextComponent comp) {
+		
+		Document doc = comp.getDocument();
+
+		int dot = comp.getCaretPosition();
+		Element root = doc.getDefaultRootElement();
+		int index = root.getElementIndex(dot);
+		Element elem = root.getElement(index);
+		int start = elem.getStartOffset();
+		int len = dot-start;
+		try {
+			doc.getText(start, len, seg);
+		} catch (BadLocationException ble) {
+			ble.printStackTrace();
+			return EMPTY_STRING;
+		}
+
+		int segEnd = seg.offset + len;
+		start = segEnd - 1;
+		while (start>=seg.offset && isValidChar(seg.array[start])) {
+			start--;
+		}
+		start++;
+
+		len = segEnd - start;
+		return len==0 ? EMPTY_STRING : new String(seg.array, start, len);
+
+	}
+
+
+	/**
+	 * Initializes this completion provider.
+	 */
+	protected void init() {
+		completions = new ArrayList();
+		seg = new Segment();
+	}
+
+
+	/**
+	 * Returns whether the specified character is valid in an auto-completion.
+	 * The default implementation is equivalent to
+	 * "<code>Character.isLetterOrDigit(ch) || ch=='_'</code>".  Subclasses
+	 * can override this method to change what characters are matched.
+	 *
+	 * @param ch The character.
+	 * @return Whether the character is valid.
+	 */
+	protected boolean isValidChar(char ch) {
+		return Character.isLetterOrDigit(ch) || ch=='_';
+	}
+
+
+	/**
+	 * Loads completions from an XML file.  The XML should validate against
+	 * the completion XML schema.
+	 *
+	 * @param file An XML file to load from.
+	 * @throws IOException If an IO error occurs.
+	 */
+	public void loadFromXML(File file) throws IOException {
+		BufferedInputStream bin = new BufferedInputStream(
+										new FileInputStream(file));
+		try {
+			loadFromXML(bin);
+		} finally {
+			bin.close();
+		}
+	}
+
+
+	/**
+	 * Loads completions from an XML input stream.  The XML should validate
+	 * against the completion XML schema.
+	 *
+	 * @param in The input stream to read from.
+	 * @throws IOException If an IO error occurs.
+	 */
+	public void loadFromXML(InputStream in) throws IOException {
+
+		long start = System.currentTimeMillis();
+
+		SAXParserFactory factory = SAXParserFactory.newInstance();
+		CompletionXMLParser handler = new CompletionXMLParser(this);
+		BufferedInputStream bin = new BufferedInputStream(in);
+		try {
+			SAXParser saxParser = factory.newSAXParser();
+			saxParser.parse(bin, handler);
+			List completions =  handler.getCompletions();
+			addCompletions(completions);
+		} catch (SAXException se) {
+			throw new IOException(se.toString());
+		} catch (ParserConfigurationException pce) {
+			throw new IOException(pce.toString());
+		} finally {
+			long time = System.currentTimeMillis() - start;
+			System.out.println("XML loaded in: " + time + "ms");
+			bin.close();
+		}
+
+	}
+
+
+	/**
+	 * Loads completions from an XML file.  The XML should validate against
+	 * the completion XML schema.
+	 *
+	 * @param resource A resource the current ClassLoader can get to.
+	 * @throws IOException If an IO error occurs.
+	 */
+	public void loadFromXML(String resource) throws IOException {
+		ClassLoader cl = getClass().getClassLoader();
+		InputStream in = cl.getResourceAsStream(resource);
+		if (in==null) {
+			throw new IOException("No such resource: " + resource);
+		}
+		BufferedInputStream bin = new BufferedInputStream(in);
+		try {
+			loadFromXML(bin);
+		} finally {
+			bin.close();
+		}
+	}
+
+
+}
\ No newline at end of file
diff --git a/src/org/fife/ui/autocomplete/DelegatingCellRenderer.java b/src/org/fife/ui/autocomplete/DelegatingCellRenderer.java
index 54a470c..ff53978 100644
--- a/src/org/fife/ui/autocomplete/DelegatingCellRenderer.java
+++ b/src/org/fife/ui/autocomplete/DelegatingCellRenderer.java
@@ -31,7 +31,8 @@ import javax.swing.ListCellRenderer;
 
 /**
  * List cell renderer that delegates to a {@link CompletionProvider}'s
- * renderer, if it has one.  If it doesn't, it simply renders
+ * renderer, if it has one.  If it doesn't, it calls into a fallback renderer.
+ * If a fallback renderer isn't specified, it simply renders
  * <code>(({@link Completion})value).toString()</code>.
  *
  * @author Robert Futrell
@@ -39,6 +40,23 @@ import javax.swing.ListCellRenderer;
  */
 class DelegatingCellRenderer extends DefaultListCellRenderer {
 
+	/**
+	 * The renderer to fall back on if one isn't specified by a provider.
+	 * This is usually <tt>this</tt>.
+	 */
+	private ListCellRenderer fallback;
+
+
+	/**
+	 * Returns the fallback cell renderer.
+	 *
+	 * @return The fallback cell renderer.
+	 * @see #setFallbackCellRenderer(ListCellRenderer)
+	 */
+	public ListCellRenderer getFallbackCellRenderer() {
+		return fallback;
+	}
+
 
 	/**
 	 * {@inheritDoc}
@@ -52,8 +70,24 @@ class DelegatingCellRenderer extends DefaultListCellRenderer {
 			return r.getListCellRendererComponent(list, value, index, selected,
 													hasFocus);
 		}
-		return super.getListCellRendererComponent(list, value, index, selected,
-													hasFocus);
+		if (fallback==null) {
+			return super.getListCellRendererComponent(list, value, index,
+												selected, hasFocus);
+		}
+		return fallback.getListCellRendererComponent(list, value, index,
+													selected, hasFocus);
+	}
+
+
+	/**
+	 * Sets the fallback cell renderer.
+	 *
+	 * @param fallback The fallback cell renderer.  If this is
+	 *        <code>null</code>, <tt>this</tt> will be used.
+	 * @see #getFallbackCellRenderer()
+	 */
+	public void setFallbackCellRenderer(ListCellRenderer fallback) {
+		this.fallback = fallback;
 	}
 
 
diff --git a/src/org/fife/ui/autocomplete/FunctionCompletion.java b/src/org/fife/ui/autocomplete/FunctionCompletion.java
index 785557e..ff5c05d 100644
--- a/src/org/fife/ui/autocomplete/FunctionCompletion.java
+++ b/src/org/fife/ui/autocomplete/FunctionCompletion.java
@@ -72,11 +72,16 @@ public class FunctionCompletion extends VariableCompletion {
 		for (int i=0; i<getParamCount(); i++) {
 			Parameter param = getParam(i);
 			type = param.getType();
+			String name = param.getName();
 			if (type!=null) {
 				appendPossibleDataType(sb, type);
-				sb.append(' ');
+				if (name!=null) {
+					sb.append(' ');
+				}
+			}
+			if (name!=null) {
+				sb.append(name);
 			}
-			sb.append(param.getName());
 			if (i<params.size()-1) {
 				sb.append(", ");
 			}
@@ -159,6 +164,7 @@ public class FunctionCompletion extends VariableCompletion {
 	 * @param params The parameters.  This should be a list of
 	 *        {@link Parameter}s.
 	 * @see #getParam(int)
+	 * @see #getParamCount()
 	 */
 	public void setParams(List params) {
 		// Deep copy so parsing can re-use its array.
diff --git a/src/org/fife/ui/autocomplete/VariableCompletion.java b/src/org/fife/ui/autocomplete/MarkupTagCompletion.java
similarity index 54%
copy from src/org/fife/ui/autocomplete/VariableCompletion.java
copy to src/org/fife/ui/autocomplete/MarkupTagCompletion.java
index 64fa0d5..c9ad95b 100644
--- a/src/org/fife/ui/autocomplete/VariableCompletion.java
+++ b/src/org/fife/ui/autocomplete/MarkupTagCompletion.java
@@ -1,8 +1,9 @@
 /*
- * 12/22/2008
+ * 01/06/2009
  *
- * VariableCompletion.java - A completion for a variable.
- * Copyright (C) 2008 Robert Futrell
+ * MarkupTagComletion.java - A completion representing a tag in markup, such
+ * as HTML or XML.
+ * Copyright (C) 2009 Robert Futrell
  * robert_futrell at users.sourceforge.net
  * http://fifesoft.com/rsyntaxtextarea
  *
@@ -22,68 +23,94 @@
  */
 package org.fife.ui.autocomplete;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.fife.ui.autocomplete.FunctionCompletion.Parameter;
+
 
 /**
- * A completion for a variable (or constant) in a programming language.
+ * A completion representing a tag in markup, such as HTML or XML.
  *
  * @author Robert Futrell
  * @version 1.0
  */
-public class VariableCompletion extends AbstractCompletion {
+public class MarkupTagCompletion extends AbstractCompletion {
 
 	private String name;
-	private String type;
 	private String desc;
 	private String definedIn;
 
+	/**
+	 * Attributes of the tag.
+	 */
+	private List attrs;
+
 
 	/**
 	 * Constructor.
 	 *
-	 * @param provider The parent provider.
-	 * @param name The name of this variable.
-	 * @param type The type of this variable (e.g. "<code>int</code>",
-	 *        "<code>String</code>", etc.).
+	 * @param provider The parent provider instance.
+	 * @param name The name of the tag.
 	 */
-	public VariableCompletion(CompletionProvider provider, String name,
-							String type) {
+	public MarkupTagCompletion(CompletionProvider provider, String name) {
 		super(provider);
 		this.name = name;
-		this.type = type;
 	}
 
 
-	protected void addDefinitionString(StringBuffer sb) {
+	/**
+	 * Adds HTML describing the attributes of this tag to a buffer.
+	 *
+	 * @param sb The buffer to append to.
+	 */
+	protected void addAttributes(StringBuffer sb) {
+
+		if (attrs!=null && attrs.size()>0) {
+			sb.append("<b>Attributes:</b><br>"); // TODO: Localize me
+			for (int i=0; i<getAttributeCount(); i++) {
+				Parameter attr = getAttribute(i);
+				sb.append("   <b>");
+				sb.append(attr.getName()!=null ? attr.getName() :
+							attr.getType());
+				sb.append("</b> ");
+				String desc = attr.getDescription();
+				if (desc!=null) {
+					sb.append(desc);
+				}
+				sb.append("<br>");
+			}
+			sb.append("<br><br>");
+		}
 
-		sb.append("<html><b>");
+	}
 
-		// Add the return type if applicable (C macros like NULL have no type).
-		if (type!=null) {
-			appendPossibleDataType(sb, type);
-			sb.append(' ');
-		}
 
-		// Add the item being described's name.
-		sb.append(name);
+	protected void addDefinitionString(StringBuffer sb) {
+		sb.append("<html><b>").append(name).append("</b>");
+	}
 
-		sb.append("</b>");
 
+	/**
+	 * Returns the specified {@link Parameter}.
+	 *
+	 * @param index The index of the attribute to retrieve.
+	 * @return The attribute.
+	 * @see #getAttributeCount()
+	 */
+	public Parameter getAttribute(int index) {
+		return (Parameter)attrs.get(index);
 	}
 
 
-	protected void appendPossibleDataType(StringBuffer sb, String type) {
-		if (type!=null) {
-			ProceduralLanguageCompletionProvider p =
-				(ProceduralLanguageCompletionProvider)getProvider();
-			String dataTypeFG = p.isDataType(type);
-			if (dataTypeFG!=null) {
-				sb.append("<font color=\"").append(dataTypeFG).append("\">");
-			}
-			sb.append(type);
-			if (dataTypeFG!=null) {
-				sb.append("</font>");
-			}
-		}
+	/**
+	 * Returns the number of attributes of this tag.
+	 *
+	 * @return The number of attributes of this tag.
+	 * @see #getAttribute(int)
+	 */
+	public int getAttributeCount() {
+		return attrs==null ? 0 : attrs.size();
 	}
 
 
@@ -112,9 +139,9 @@ public class VariableCompletion extends AbstractCompletion {
 
 
 	/**
-	 * Returns the name of this variable.
+	 * Returns the name of this tag.
 	 *
-	 * @return The name.
+	 * @return The name of this tag.
 	 */
 	public String getName() {
 		return name;
@@ -124,36 +151,25 @@ public class VariableCompletion extends AbstractCompletion {
 	/**
 	 * {@inheritDoc}
 	 */
+	public String getReplacementText() {
+		return getName();
+	}
+
+
+	/**
+	 * {@inheritDoc}
+	 */
 	public String getSummary() {
 		StringBuffer sb = new StringBuffer();
 		addDefinitionString(sb);
 		possiblyAddDescription(sb);
+		addAttributes(sb);
 		possiblyAddDefinedIn(sb);
 		return sb.toString();
 	}
 
 
 	/**
-	 * Returns the type of this variable.
-	 *
-	 * @return The type.
-	 */
-	public String getType() {
-		return type;
-	}
-
-
-	/**
-	 * Returns the name of this variable.
-	 *
-	 * @return The text to autocomplete with.
-	 */
-	public String getReplacementText() {
-		return getName();
-	}
-
-
-	/**
 	 * Adds some HTML describing where this variable is defined, if this
 	 * information is known.
 	 *
@@ -194,10 +210,10 @@ public class VariableCompletion extends AbstractCompletion {
 
 
 	/**
-	 * Sets the short description of this variable.  This should be an
+	 * Sets the short description of this tag.  This should be an
 	 * HTML snippet.
 	 *
-	 * @param desc A short description of this variable.  This may be
+	 * @param desc A short description of this tag.  This may be
 	 *        <code>null</code>.
 	 * @see #getDescription()
 	 */
@@ -206,4 +222,17 @@ public class VariableCompletion extends AbstractCompletion {
 	}
 
 
+	/**
+	 * Sets the attributes of this tag.
+	 *
+	 * @param attrs The attributes.
+	 * @see #getAttribute(int)
+	 * @see #getAttributeCount()
+	 */
+	public void setAttributes(List attrs) {
+		// Deep copy so parsing can re-use its array.
+		this.attrs = new ArrayList(attrs);
+	}
+
+
 }
\ No newline at end of file
diff --git a/src/org/fife/ui/autocomplete/ProceduralLanguageCellRenderer.java b/src/org/fife/ui/autocomplete/ProceduralLanguageCellRenderer.java
deleted file mode 100644
index 6e1d4ee..0000000
--- a/src/org/fife/ui/autocomplete/ProceduralLanguageCellRenderer.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 12/23/2008
- *
- * ProceduralLanguageCellRenderer.java - Cell renderer for procedural
- * languages.
- * Copyright (C) 2008 Robert Futrell
- * robert_futrell at users.sourceforge.net
- * http://fifesoft.com/rsyntaxtextarea
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
- */
-package org.fife.ui.autocomplete;
-
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Font;
-
-import javax.swing.DefaultListCellRenderer;
-import javax.swing.JList;
-
-
-/**
- * A cell renderer for {@link ProceduralLanguageCompletionProvider}.
- *
- * @author Robert Futrell
- * @version 1.0
- */
-public class ProceduralLanguageCellRenderer extends DefaultListCellRenderer {
-
-	/**
-	 * The alternating background color.
-	 */
-	private Color altBG;
-
-	/**
-	 * The font to use when rendering items.
-	 */
-	private Font font;
-
-
-	/**
-	 * Constructor.
-	 */
-	public ProceduralLanguageCellRenderer() {
-		font = new Font("Monospaced", Font.PLAIN, 12);
-		altBG = new Color(248,248,248);
-	}
-
-
-	/**
-	 * Returns the background color to use on alternating lines.
-	 *
-	 * @return The altnernate background color.  If this is <code>null</code>,
-	 *         alternating colors are not used.
-	 * @see #setAlternateBackground(Color)
-	 */
-	public Color getAlternateBackground() {
-		return altBG;
-	}
-
-
-	/**
-	 * Returns the font used when rendering completions.
-	 *
-	 * @return The font.
-	 * @see #setDisplayFont(Font)
-	 */
-	public Font getDisplayFont() {
-		return font;
-	}
-
-
-	/**
-	 * Returns the renderer.
-	 *
-	 * @param list The list of choices being rendered.
-	 * @param value The {@link Completion} being rendered.
-	 * @param index The index into <code>list</code> being rendered.
-	 * @param selected Whether the item is selected.
-	 * @param hasFocus Whether the item has focus.
-	 */
-	public Component getListCellRendererComponent(JList list, Object value,
-						int index, boolean selected, boolean hasFocus) {
-
-		super.getListCellRendererComponent(list,value,index,selected,hasFocus);
-//		System.out.println(index);
-		setFont(font); // Overrides super's setFont(list.getFont()).
-
-		if (value instanceof FunctionCompletion) {
-			FunctionCompletion fc = (FunctionCompletion)value;
-			StringBuffer sb = new StringBuffer("<html><b><em>" + fc.getName() + "</em></b>");
-			sb.append('(');
-			int paramCount = fc.getParamCount();
-			for (int i=0; i<paramCount; i++) {
-				FunctionCompletion.Parameter param = fc.getParam(i);
-				String type = param.getType();
-				if (type!=null) {
-					if (!selected) {
-						sb.append("<font color='#aa0077'>");
-					}
-					sb.append(type);
-					if (!selected) {
-						sb.append("</font>");
-					}
-					sb.append(' ');
-				}
-				String name = param.getName();
-				if (name!=null) {
-					sb.append(name);
-				}
-				if (i<paramCount-1) {
-					sb.append(", ");
-				}
-			}
-			sb.append(") : ");
-			if (!selected) {
-				sb.append("<font color='#a0a0ff'>");
-			}
-			sb.append(fc.getType());
-			if (!selected) {
-				sb.append("</font>");
-			}
-			setText(sb.toString());
-		}
-
-		else if (value instanceof VariableCompletion) {
-			VariableCompletion vc = (VariableCompletion)value;
-			StringBuffer sb = new StringBuffer("<html><b><em>" + vc.getName() + "</em></b>");
-			if (vc.getType()!=null) {
-				sb.append(" : ");
-				if (!selected) {
-					sb.append("<font color='#a0a0ff'>");
-				}
-				sb.append(vc.getType());
-				if (!selected) {
-					sb.append("</font>");
-				}
-			}
-			setText(sb.toString());
-		}
-
-		if (!selected && (index&1)==0 && altBG!=null) {
-			setBackground(altBG);
-		}
-
-//		if (index==238) {
-//			Thread.dumpStack();
-//		}
-//setIcon(varIcon);
-		return this;
-
-	}
-
-
-	/**
-	 * Sets the background color to use on alternating lines.
-	 *
-	 * @param altBG The new alternate background color.  If this is
-	 *        <code>null</code>, alternating lines will not use different
-	 *        background colors.
-	 * @see #getAlternateBackground()
-	 */
-	public void setAlternateBackground(Color altBG) {
-		this.altBG = altBG;
-	}
-
-
-	/**
-	 * Sets the font to use when rendering completion items.
-	 *
-	 * @param font The font to use.
-	 * @see #getDisplayFont()
-	 */
-	public void setDisplayFont(Font font) {
-		this.font = font;
-	}
-
-
-}
\ No newline at end of file
diff --git a/src/org/fife/ui/autocomplete/ProceduralLanguageCompletionProvider.java b/src/org/fife/ui/autocomplete/ProceduralLanguageCompletionProvider.java
deleted file mode 100644
index 127b5d8..0000000
--- a/src/org/fife/ui/autocomplete/ProceduralLanguageCompletionProvider.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * 12/21/2008
- *
- * ProceduralLanguageCompletionProvider.java - A provider useful for procedural
- * languages, such as C.
- * Copyright (C) 2008 Robert Futrell
- * robert_futrell at users.sourceforge.net
- * http://fifesoft.com/rsyntaxtextarea
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
- */
-package org.fife.ui.autocomplete;
-
-import java.awt.Color;
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import javax.swing.text.BadLocationException;
-import javax.swing.text.Document;
-import javax.swing.text.Element;
-import javax.swing.text.JTextComponent;
-import javax.swing.text.Segment;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-
-/**
- * A completion provider that reads an XML file for a procedural language API
- * (such as C).  That XML file can define the following things:
- * 
- * <ul>
- *    <li>Functions, their parameters, and return types</li>
- *    <li>Constants (such as <tt>#define</tt>s)</li>
- *    <li>(Global) variables</li>
- * </ul>
- *
- * @author Robert Futrell
- * @version 1.0
- * 
- */
-/*
- * TODO: Make chars '(', ')' and ',' configurable.
- */
-public class ProceduralLanguageCompletionProvider
-									extends AbstractCompletionProvider {
-
-	private Segment seg;
-
-	private String[] dataTypes;
-	private String dataTypeFG;
-	private boolean colorizeHeader;
-
-
-	public ProceduralLanguageCompletionProvider(InputStream in) {
-		try {
-			this.completions = loadXMLFromStream(in);
-			Collections.sort(this.completions);
-		} catch (IOException ioe) {
-			ioe.printStackTrace();
-		}
-		init();
-	}
-
-
-	public ProceduralLanguageCompletionProvider(String fileName) {
-		try {
-			InputStream in = null;
-			File file = new File(fileName);
-			if (file.isFile()) {
-				in = new FileInputStream(file);
-			}
-			else {
-				ClassLoader cl = getClass().getClassLoader();
-				in = cl.getResourceAsStream(fileName);
-			}
-			this.completions = loadXMLFromStream(in);
-			Collections.sort(this.completions);
-		} catch (IOException ioe) {
-			ioe.printStackTrace();
-		}
-		init();
-	}
-
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public String getAlreadyEnteredText(JTextComponent comp) {
-
-		Document doc = comp.getDocument();
-
-		int dot = comp.getCaretPosition();
-		Element root = doc.getDefaultRootElement();
-		int index = root.getElementIndex(dot);
-		Element elem = root.getElement(index);
-		int start = elem.getStartOffset();
-		int len = dot-start;
-		try {
-			doc.getText(start, len, seg);
-		} catch (BadLocationException ble) {
-			ble.printStackTrace();
-			return EMPTY_STRING;
-		}
-
-		int segEnd = seg.offset + len;
-		start = segEnd - 1;
-		while (start>=seg.offset && isValidChar(seg.array[start])) {
-			start--;
-		}
-		start++;
-
-		len = segEnd - start;
-		return len==0 ? EMPTY_STRING : new String(seg.array, start, len);
-
-	}
-
-
-	/**
-	 * Returns whether the description area should have its header information
-	 * syntax highlighted.
-	 *
-	 * @return Whether to color the description area's header.
-	 * @see #setColorizeHeader(boolean)
-	 */
-	public boolean getColorizeHeader() {
-		return colorizeHeader;
-	}
-
-
-	/**
-	 * Does initialization common to various constructors.
-	 */
-	private void init() {
-		seg = new Segment();
-		setColorizeHeader(false);
-		setListCellRenderer(new ProceduralLanguageCellRenderer());
-	}
-
-
-	public String isDataType(String str) {
-		return Arrays.binarySearch(dataTypes, str)>=0 ?
-				dataTypeFG : null;
-	}
-
-
-	private List loadXMLFromStream(InputStream in) throws IOException {
-
-		long start = System.currentTimeMillis();
-
-		SAXParserFactory factory = SAXParserFactory.newInstance();
-		XMLParser handler = new XMLParser();
-		BufferedInputStream bin = new BufferedInputStream(in);
-		try {
-			SAXParser saxParser = factory.newSAXParser();
-			saxParser.parse(bin, handler);
-			return handler.getCompletions();
-		} catch (SAXException se) {
-			throw new IOException(se.toString());
-		} catch (ParserConfigurationException pce) {
-			throw new IOException(pce.toString());
-		} finally {
-			long time = System.currentTimeMillis() - start;
-			System.out.println("XML loaded in: " + time + "ms");
-			bin.close();
-		}
-
-	}
-
-
-	/**
-	 * Sets whether the header text of the description area should be
-	 * syntax highlighted.
-	 *
-	 * @param colorize Whether to colorize the header information in the
-	 *        description area.
-	 * @see #getColorizeHeader()
-	 */
-	public void setColorizeHeader(boolean colorize) {
-		colorizeHeader = colorize;
-	}
-
-
-	/**
-	 * Sets the color to use for data types in the header of a description
-	 * window.
-	 *
-	 * @param fg The foreground color to use.
-	 * @see #setDataTypes(String[])
-	 * @see #getColorizeHeader()
-	 */
-	public void setDataTypeForeground(Color fg) {
-		dataTypeFG = Util.getHexString(fg);
-	}
-
-
-	/**
-	 * Sets the identifiers to color as data types in the header of a
-	 * description window.
-	 *
-	 * @param types The identifiers for data types.  If this is
-	 *        <code>null</code>, nothing will be colorized as a data type.
-	 * @see #setDataTypeForeground(Color)
-	 * @see #getColorizeHeader()
-	 */
-	public void setDataTypes(String[] types) {
-		if (types==null) {
-			dataTypes = null;
-		}
-		else {
-			dataTypes = (String[])types.clone();
-			Arrays.sort(dataTypes, String.CASE_INSENSITIVE_ORDER);
-		}
-	}
-
-
-	/**
-	 * Returns whether the specified character is valid in an auto-completion.
-	 * Subclasses can override this method if their language supports a
-	 * different set of valid chars for auto-completable items.
-	 *
-	 * @param ch The character.
-	 * @return Whether the character is valid.
-	 */
-	protected boolean isValidChar(char ch) { 
-		return Character.isLetterOrDigit(ch) || ch=='_';
-	}
-
-
-	/**
-	 * Parser for an XMl file describing a procedural language such as C.
-	 *
-	 * @author Robert Futrell
-	 * @version 1.0
-	 */
-	private class XMLParser extends DefaultHandler {
-
-		private List completions;
-
-		private String name;
-		private String type;
-		private String returnType;
-		private StringBuffer desc;
-		private String paramName;
-		private String paramType;
-		private StringBuffer paramDesc;
-		private List params;
-		private String definedIn;
-		private boolean doingKeywords;
-		private boolean inKeyword;
-		private boolean gettingDesc;
-		private boolean gettingParams;
-		private boolean inParam;
-		private boolean gettingParamDesc;
-
-		public XMLParser() {
-			completions = new ArrayList();
-			params = new ArrayList(1);
-			desc = new StringBuffer();
-			paramDesc = new StringBuffer();
-		}
-
-		public void characters(char[] ch, int start, int length) {
-			if (gettingDesc) {
-				desc.append(ch, start, length);
-			}
-			else if (gettingParamDesc) {
-				paramDesc.append(ch, start, length);
-			}
-		}
-
-		public void endElement(String uri, String localName, String qName) {
-
-			if ("keywords".equals(qName)) {
-				doingKeywords = false;
-			}
-
-			else if (doingKeywords) {
-
-				if ("keyword".equals(qName)) {
-					Completion c = null;
-					if ("function".equals(type)) {
-						FunctionCompletion fc = new FunctionCompletion(
-								ProceduralLanguageCompletionProvider.this, name, returnType);
-						if (desc.length()>0) {
-							fc.setDescription(desc.toString());
-							desc.setLength(0);
-						}
-						fc.setParams(params);
-						fc.setDefinedIn(definedIn);
-						c = fc;
-					}
-					else if ("constant".equals(type)) {
-						VariableCompletion vc = new VariableCompletion(
-								ProceduralLanguageCompletionProvider.this, name, returnType);
-						if (desc.length()>0) {
-							vc.setDescription(desc.toString());
-							desc.setLength(0);
-						}
-						vc.setDefinedIn(definedIn);
-						c = vc;
-					}
-					else {
-						throw new InternalError("Unexpected type: " + type);
-					}
-					completions.add(c);
-					inKeyword = false;
-				}
-				else if (inKeyword) {
-					if ("desc".equals(qName)) {
-						gettingDesc = false;
-					}
-					else if (gettingParams) {
-						if ("params".equals(qName)) {
-							gettingParams = false;
-						}
-						else if ("param".equals(qName)) {
-							FunctionCompletion.Parameter param =
-								new FunctionCompletion.Parameter(paramType,
-															paramName);
-							if (paramDesc.length()>0) {
-								param.setDescription(paramDesc.toString());
-								paramDesc.setLength(0);
-							}
-							params.add(param);
-							inParam = false;
-						}
-						else if (inParam) {
-							if ("desc".equals(qName)) {
-								gettingParamDesc = false;
-							}
-						}
-					}
-				}
-
-			}
-
-		}
-
-		public List getCompletions() {
-			return completions;
-		}
-
-		public void startElement(String uri, String localName, String qName, Attributes attrs) { 
-			if ("keywords".equals(qName)) {
-				doingKeywords = true;
-			}
-			else if (doingKeywords) {
-				if ("keyword".equals(qName)) {
-					name = attrs.getValue("name");
-					type = attrs.getValue("type");
-					returnType = attrs.getValue("returnType");
-					params.clear();
-					definedIn = attrs.getValue("definedIn");
-					inKeyword = true;
-				}
-				else if (inKeyword) {
-					if ("params".equals(qName)) {
-						gettingParams = true;
-					}
-					else if (gettingParams) {
-						if ("param".equals(qName)) {
-							paramName = attrs.getValue("name");
-							paramType = attrs.getValue("type");
-							inParam = true;
-						}
-						if (inParam) {
-							if ("desc".equals(qName)) {
-								gettingParamDesc = true;
-							}
-						}
-					}
-					else if ("desc".equals(qName)) {
-						gettingDesc = true;
-					}
-				}
-			}
-		}
-
-	}
-
-
-}
\ No newline at end of file
diff --git a/src/org/fife/ui/autocomplete/ShorthandCompletion.java b/src/org/fife/ui/autocomplete/ShorthandCompletion.java
index 1070bd5..8a4700d 100644
--- a/src/org/fife/ui/autocomplete/ShorthandCompletion.java
+++ b/src/org/fife/ui/autocomplete/ShorthandCompletion.java
@@ -33,7 +33,7 @@ package org.fife.ui.autocomplete;
  * @author Robert Futrell
  * @version 1.0
  */
-public class ShorthandCompletion extends WordCompletion {
+public class ShorthandCompletion extends BasicCompletion {
 
 	/**
 	 * The text the user can start typing that will match this completion.
@@ -56,15 +56,36 @@ public class ShorthandCompletion extends WordCompletion {
 
 
 	/**
-	 * Returns the replacement text.  Subclasses can override this method to
-	 * return a more detailed description.
+	 * Constructor.
 	 *
-	 * @return A description of this completion (the text that will be
-	 *         inserted).
-	 * @see #getReplacementText()
+	 * @param provider The provider that returns this completion.
+	 * @param inputText The text the user inputs to get this completion.
+	 * @param replacementText The replacement text of the completion.
+	 * @param shortDesc A short description of the completion.  This will be
+	 *        displayed in the completion list.  This may be <code>null</code>.
 	 */
-	public String getSummary() {
-		return "<html><body><tt>" + getReplacementText();
+	public ShorthandCompletion(CompletionProvider provider, String inputText,
+								String replacementText, String shortDesc) {
+		super(provider, replacementText, shortDesc);
+		this.inputText = inputText;
+	}
+
+
+	/**
+	 * Constructor.
+	 *
+	 * @param provider The provider that returns this completion.
+	 * @param inputText The text the user inputs to get this completion.
+	 * @param replacementText The replacement text of the completion.
+	 * @param shortDesc A short description of the completion.  This will be
+	 *        displayed in the completion list.  This may be <code>null</code>.
+	 * @param summary The summary of this completion.  This should be HTML.
+	 *        This may be <code>null</code>.
+	 */
+	public ShorthandCompletion(CompletionProvider provider, String inputText,
+					String replacementText, String shortDesc, String summary) {
+		super(provider, replacementText, shortDesc, summary);
+		this.inputText = inputText;
 	}
 
 
@@ -78,4 +99,19 @@ public class ShorthandCompletion extends WordCompletion {
 	}
 
 
+	/**
+	 * If a summary has been set, that summary is returned.  Otherwise, the
+	 * replacement text is returned.
+	 *
+	 * @return A description of this completion (the text that will be
+	 *         inserted).
+	 * @see #getReplacementText()
+	 */
+	public String getSummary() {
+		String summary = super.getSummary();
+		return summary!=null ? summary :
+							"<html><body><tt>" + getReplacementText();
+	}
+
+
 }
\ No newline at end of file
diff --git a/src/org/fife/ui/autocomplete/VariableCompletion.java b/src/org/fife/ui/autocomplete/VariableCompletion.java
index 64fa0d5..7ecef75 100644
--- a/src/org/fife/ui/autocomplete/VariableCompletion.java
+++ b/src/org/fife/ui/autocomplete/VariableCompletion.java
@@ -72,18 +72,7 @@ public class VariableCompletion extends AbstractCompletion {
 
 
 	protected void appendPossibleDataType(StringBuffer sb, String type) {
-		if (type!=null) {
-			ProceduralLanguageCompletionProvider p =
-				(ProceduralLanguageCompletionProvider)getProvider();
-			String dataTypeFG = p.isDataType(type);
-			if (dataTypeFG!=null) {
-				sb.append("<font color=\"").append(dataTypeFG).append("\">");
-			}
-			sb.append(type);
-			if (dataTypeFG!=null) {
-				sb.append("</font>");
-			}
-		}
+		sb.append(type);
 	}
 
 
diff --git a/src/org/fife/ui/autocomplete/WordCompletion.java b/src/org/fife/ui/autocomplete/WordCompletion.java
deleted file mode 100644
index a507d91..0000000
--- a/src/org/fife/ui/autocomplete/WordCompletion.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 12/21/2008
- *
- * WordCompletion.java - A completion for a single word.
- * Copyright (C) 2008 Robert Futrell
- * robert_futrell at users.sourceforge.net
- * http://fifesoft.com/rsyntaxtextarea
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
- */
-package org.fife.ui.autocomplete;
-
-
-/**
- * A completion for a single word.  Input that matches any number of the
- * leading characters of this completion will match it.<p>
- *
- * @author Robert Futrell
- * @version 1.0
- */
-public class WordCompletion extends AbstractCompletion {
-
-	/**
-	 * The word that can be auto-completed.
-	 */
-	private String replacementText;
-
-
-	/**
-	 * Constructor.
-	 *
-	 * @param provider The provider that returns this completion.
-	 * @param replacementText The text to be made auto-completable.
-	 */
-	public WordCompletion(CompletionProvider provider, String replacementText) {
-		super(provider);
-		this.replacementText = replacementText;
-	}
-
-
-	/**
-	 * Returns <code>null</code> always.  Subclasses can override this method
-	 * if they wish to provide a description.
-	 *
-	 * @return This item's description.  This will always be
-	 *         <code>null</code>.
-	 */
-	public String getSummary() {
-		return null;
-	}
-
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public String getReplacementText() {
-		return replacementText;
-	}
-
-
-}
\ No newline at end of file
diff --git a/src/org/fife/ui/autocomplete/WordCompletionProvider.java b/src/org/fife/ui/autocomplete/WordCompletionProvider.java
deleted file mode 100644
index 70e68ad..0000000
--- a/src/org/fife/ui/autocomplete/WordCompletionProvider.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 12/21/2008
- *
- * WordCompletionProvider.java - A simple provider that lets the user choose
- * from a list of words.
- * Copyright (C) 2008 Robert Futrell
- * robert_futrell at users.sourceforge.net
- * http://fifesoft.com/rsyntaxtextarea
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
- */
-package org.fife.ui.autocomplete;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import javax.swing.text.BadLocationException;
-import javax.swing.text.Document;
-import javax.swing.text.Element;
-import javax.swing.text.JTextComponent;
-import javax.swing.text.Segment;
-
-
-/**
- * A completion provider that simply uses a list of words.
- *
- * @author Robert Futrell
- * @version 1.0
- */
-public class WordCompletionProvider extends AbstractCompletionProvider {
-
-	protected Segment seg;
-
-
-	/**
-	 * Constructor.
-	 *
-	 * @param words The words to offer as completion suggestions.  This
-	 *        cannot be <code>null</code>.
-	 */
-	public WordCompletionProvider(String[] words) {
-		completions = createCompletions(words);
-		seg = new Segment();
-	}
-
-
-	/**
-	 * Creates the completion array for an array of words.
-	 *
-	 * @param words The words.
-	 * @return The <tt>Completion</tt> list.  This will be sorted
-	 *         alphabetically.
-	 */
-	protected List createCompletions(String[] words) {
-		List completions = new ArrayList(words.length);
-		for (int i=0; i<words.length; i++) {
-			completions.add(new WordCompletion(this, words[i]));
-		}
-		Collections.sort(completions);
-		return completions;
-	}
-
-
-	/**
-	 * Returns the text just before the current caret position that could be
-	 * the start of something auto-completable.<p>
-	 *
-	 * This method returns all characters before the caret that are metched
-	 * by  {@link #isValidChar(char)}.
-	 *
-	 * @param comp The text component.
-	 * @return The text.
-	 */
-	public String getAlreadyEnteredText(JTextComponent comp) {
-		
-		Document doc = comp.getDocument();
-
-		int dot = comp.getCaretPosition();
-		Element root = doc.getDefaultRootElement();
-		int index = root.getElementIndex(dot);
-		Element elem = root.getElement(index);
-		int start = elem.getStartOffset();
-		int len = dot-start;
-		try {
-			doc.getText(start, len, seg);
-		} catch (BadLocationException ble) {
-			ble.printStackTrace();
-			return EMPTY_STRING;
-		}
-
-		int segEnd = seg.offset + len;
-		start = segEnd - 1;
-		while (start>=seg.offset && isValidChar(seg.array[start])) {
-			start--;
-		}
-		start++;
-
-		len = segEnd - start;
-		return len==0 ? EMPTY_STRING : new String(seg.array, start, len);
-
-	}
-
-
-	/**
-	 * Returns whether the specified character is valid in an auto-completion.
-	 * The default implementation is equivalent to
-	 * "<code>Character.isLetterOrDigit(ch) || ch=='_'</code>".  Subclasses
-	 * can override this method to change what characters are matched.
-	 *
-	 * @param ch The character.
-	 * @return Whether the character is valid.
-	 */
-	protected boolean isValidChar(char ch) {
-		return Character.isLetterOrDigit(ch) || ch=='_';
-	}
-
-
-}
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/autocomplete.git



More information about the pkg-java-commits mailing list