Index: trunk/hiptop/pester/net/sabi/pester/AlarmSetDialog.java
===================================================================
--- trunk/hiptop/pester/net/sabi/pester/AlarmSetDialog.java	(revision 280)
+++ trunk/hiptop/pester/net/sabi/pester/AlarmSetDialog.java	(revision 283)
@@ -71,4 +71,6 @@
 	mDiscardAlarmButton =
 	    (Button)getDescendantWithID(ID_DISCARD_ALARM_BUTTON);
+	mMessageField.setTextFinder(new MessageFinder());
+	mMessageField.setNumCharsNeededForCompletion(0);
 	mInButton.setValue(1);
 	mDateEditor.limitToDangerEpoch();
@@ -228,5 +230,7 @@
 	    if (!isValid())
 		return true;
-	    mEditingAlarm.setMessage(mMessageField.toString());
+	    String message = mMessageField.toString();
+	    mEditingAlarm.setMessage(message);
+	    MessageFinder.usedMessage(message);
 	    // set the period regardless, so it gets saved for future use
 	    mEditingAlarm.setPeriod(editingInterval(),
Index: trunk/hiptop/pester/net/sabi/pester/Alarms.java
===================================================================
--- trunk/hiptop/pester/net/sabi/pester/Alarms.java	(revision 280)
+++ trunk/hiptop/pester/net/sabi/pester/Alarms.java	(revision 283)
@@ -44,4 +44,9 @@
 	    alarm.resume();
 	}
+	try {
+	    MessageFinder.setMessageListFromByteArray(sSettingsDB.getBytes(KEY_RECENT_MESSAGES));
+	} catch (SettingsDBException e) {
+	    MessageFinder.setDefaultMessageList();
+	}
 	sAlarmList = this;
     }
@@ -62,4 +67,8 @@
     public static void removeAlarm(Alarm alarm) {
 	sAlarmList.removeItem(alarm);
+    }
+    public static void recentMessagesChanged() {
+	sSettingsDB.setBytes(KEY_RECENT_MESSAGES,
+			     MessageFinder.messageListAsByteArray());
     }
 
@@ -94,4 +103,5 @@
 
     private static String KEY_DEFAULT_ALARM = "default alarm";
+    private static String KEY_RECENT_MESSAGES = "recent messages";
 
     public static Alarm getDefaultAlarm() {
Index: trunk/hiptop/pester/net/sabi/pester/MessageFinder.java
===================================================================
--- trunk/hiptop/pester/net/sabi/pester/MessageFinder.java	(revision 283)
+++ trunk/hiptop/pester/net/sabi/pester/MessageFinder.java	(revision 283)
@@ -0,0 +1,101 @@
+package net.sabi.pester;
+
+import danger.app.Application;
+import danger.text.Collator;
+import danger.text.DangerCollator;
+import danger.ui.ListSelectMenu;
+import danger.ui.MenuItem;
+import danger.util.DEBUG;
+import danger.util.TextFinder;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.Vector;
+
+class MessageFinder implements TextFinder, Resources {
+    private static final int VERSION_1 = 1;
+    private static final int MAX_MESSAGE_COUNT = 50;
+    private static LinkedList sMessageList = new LinkedList();
+    private Vector mItems;
+
+    public static void setDefaultMessageList() {
+	String messages[] =
+	    Application.getCurrentApp().getStringArray(ID_ALARM_MESSAGES);
+	sMessageList = new LinkedList(Arrays.asList(messages));
+    }
+
+    public static byte[] messageListAsByteArray() {
+	try {
+	    ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+	    DataOutputStream dataStream = new DataOutputStream(byteStream);
+
+	    dataStream.writeByte(VERSION_1);
+	    dataStream.writeInt(sMessageList.size());
+	    ListIterator i = sMessageList.listIterator(0);
+	    while (i.hasNext())
+		dataStream.writeUTF((String)i.next());
+	    dataStream.flush();
+	    return byteStream.toByteArray();
+	} catch (Exception e) {
+	    DEBUG.p("Pester: couldn't serialize message list: " + e);
+	}
+	return null;
+    }
+
+    public static void setMessageListFromByteArray(byte[] data) {
+	try {
+	    ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
+	    DataInputStream dataStream = new DataInputStream(byteStream);
+	    
+	    byte version = dataStream.readByte();
+	    if (version != VERSION_1)
+		throw new Exception();
+	    
+	    int count = dataStream.readInt();
+	    for (int i = 0 ; i < count ; i++)
+		addMessage(dataStream.readUTF());
+	} catch (Exception e) {
+	    setDefaultMessageList();
+	    DEBUG.p("Pester: setting default message list: " + e);
+	}
+    }
+
+    private static boolean addMessage(String message) {
+	int i = sMessageList.indexOf(message);
+	if (i == 0)
+	    return false;
+	if (i != -1)
+	    sMessageList.remove(i);
+	sMessageList.addFirst(message);
+	if (sMessageList.size() > MAX_MESSAGE_COUNT)
+	    sMessageList.removeLast();
+	return true;
+    }
+
+    public static void usedMessage(String message) {
+	if (!addMessage(message))
+	    return;
+	Alarms.recentMessagesChanged();
+    }
+
+    public MessageFinder() {
+	mItems = new Vector(sMessageList.size() / 2);
+    }
+
+    public void search(ListSelectMenu menu, String key) {
+	DangerCollator collator = (DangerCollator)DangerCollator.getInstance();
+	mItems.removeAllElements();
+	ListIterator i = sMessageList.listIterator(0);
+	while (i.hasNext()) {
+	    String message = (String)i.next();
+	    if (collator.startsWith(message, key, Collator.PRIMARY)) {
+		mItems.addElement(new MenuItem(message));
+	    }
+	}
+	menu.updateMenuContents(mItems);
+    }
+}
