diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644
index 0000000..9181204
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/icon.png b/res/drawable/icon.png
new file mode 100644
index 0000000..6e851aa
Binary files /dev/null and b/res/drawable/icon.png differ
diff --git a/res/layout/about.xml b/res/layout/about.xml
new file mode 100644
index 0000000..e01a830
--- /dev/null
+++ b/res/layout/about.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/main.xml b/res/layout/main.xml
new file mode 100644
index 0000000..d10ec89
--- /dev/null
+++ b/res/layout/main.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
new file mode 100644
index 0000000..842279e
--- /dev/null
+++ b/res/values/arrays.xml
@@ -0,0 +1,79 @@
+
+
+
+ - Adam
+ - Boy
+ - Charlie
+ - David
+ - Edward
+ - Frank
+ - George
+ - Henry
+ - Ida
+ - John
+ - King
+ - Lincoln
+ - Mary
+ - Nora
+ - Ocean
+ - Paul
+ - Queen
+ - Robert
+ - Sam
+ - Tom
+ - Union
+ - Victor
+ - William
+ - X-Ray
+ - Young
+ - Zebra
+ - Zero
+ - One
+ - Two
+ - Three
+ - Four
+ - Five
+ - Six
+ - Seven
+ - Eight
+ - Niner
+
+
+ - Alpha
+ - Bravo
+ - Charlie
+ - Delta
+ - Echo
+ - Foxtrot
+ - Golf
+ - Hotel
+ - India
+ - Juliet
+ - Kilo
+ - Lima
+ - Mike
+ - November
+ - Oscar
+ - Papa
+ - Quebec
+ - Romeo
+ - Sierra
+ - Tango
+ - Uniform
+ - Victor
+ - Whiskey
+ - X-Ray
+ - Yankee
+ - Zulu
+ - Zero
+ - One
+ - Two
+ - Three
+ - Four
+ - Five
+ - Six
+ - Seven
+ - Eight
+ - Nine (Niner)
+
+
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644
index 0000000..b71656e
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,18 @@
+
+
+ SpellIt
+ Spell It!
+ Tap to continue...
+ Tap to repeat...
+ Start typing for history...
+ Please type something...
+ NATO Phonetic
+ G as in Google
+ © 2008 Erik C. Thauvin\nAll Rights Reserved\n\nerik@thauvin.net\n\nhttp://mobile.thauvin.net
+ About
+ OK
+ Cancel
+ as in
+ <space>
+ <done>
+
diff --git a/screenshots/1.psd b/screenshots/1.psd
new file mode 100644
index 0000000..d0c810e
Binary files /dev/null and b/screenshots/1.psd differ
diff --git a/screenshots/2.psd b/screenshots/2.psd
new file mode 100644
index 0000000..e3dc34e
Binary files /dev/null and b/screenshots/2.psd differ
diff --git a/screenshots/3.psd b/screenshots/3.psd
new file mode 100644
index 0000000..aecabc1
Binary files /dev/null and b/screenshots/3.psd differ
diff --git a/screenshots/spellit.gif b/screenshots/spellit.gif
new file mode 100644
index 0000000..3048c28
Binary files /dev/null and b/screenshots/spellit.gif differ
diff --git a/sign.bat b/sign.bat
new file mode 100644
index 0000000..6809692
--- /dev/null
+++ b/sign.bat
@@ -0,0 +1,10 @@
+@echo off
+"%JAVA_HOME%\bin\jarsigner" -verbose -keystore "%USERPROFILE%\personal\android.keystore" "%1" android
+if errorlevel 1 goto ERROR
+"%JAVA_HOME%\bin\jarsigner" -verify "%1"
+if errorlevel 1 goto ERROR
+goto DONE
+:ERROR
+@pause
+:DONE
+@echo on
\ No newline at end of file
diff --git a/src/net/thauvin/erik/android/spellit/R.java b/src/net/thauvin/erik/android/spellit/R.java
new file mode 100644
index 0000000..ac67d21
--- /dev/null
+++ b/src/net/thauvin/erik/android/spellit/R.java
@@ -0,0 +1,48 @@
+/* AUTO-GENERATED FILE. DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found. It
+ * should not be modified by hand.
+ */
+
+package net.thauvin.erik.android.spellit;
+
+public final class R {
+ public static final class array {
+ public static final int alphabet=0x7f040000;
+ public static final int nato_alphabet=0x7f040001;
+ }
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int icon=0x7f020000;
+ }
+ public static final class id {
+ public static final int about_text_fld=0x7f060000;
+ public static final int main_entry_fld=0x7f060001;
+ public static final int main_result_fld=0x7f060003;
+ public static final int main_spell_btn=0x7f060002;
+ public static final int main_tap_lbl=0x7f060004;
+ }
+ public static final class layout {
+ public static final int about=0x7f030000;
+ public static final int main=0x7f030001;
+ }
+ public static final class string {
+ public static final int about_menu_txt=0x7f050009;
+ public static final int about_txt=0x7f050008;
+ public static final int alert_dialog_cancel=0x7f05000b;
+ public static final int alert_dialog_ok=0x7f05000a;
+ public static final int app_name=0x7f050000;
+ public static final int as_in_txt=0x7f05000c;
+ public static final int done_txt=0x7f05000e;
+ public static final int main_entry_err_txt=0x7f050005;
+ public static final int main_entry_hint_txt=0x7f050004;
+ public static final int main_spell_btn_txt=0x7f050001;
+ public static final int main_tap_lbl_repeat_txt=0x7f050003;
+ public static final int main_tap_lbl_txt=0x7f050002;
+ public static final int nato_menu_txt=0x7f050006;
+ public static final int sample_txt=0x7f050007;
+ public static final int space_txt=0x7f05000d;
+ }
+}
diff --git a/src/net/thauvin/erik/android/spellit/SpellIt.java b/src/net/thauvin/erik/android/spellit/SpellIt.java
new file mode 100644
index 0000000..ae52834
--- /dev/null
+++ b/src/net/thauvin/erik/android/spellit/SpellIt.java
@@ -0,0 +1,445 @@
+/*
+ * @(#)SpellIt.java
+ *
+ * Copyright (c) 2008, Erik C. Thauvin (http://erik.thauvin.net/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the authors nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id$
+ *
+ */
+package net.thauvin.erik.android.spellit;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.text.ClipboardManager;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/**
+ * SpellIt
is a alphabet speller for Android.
+ *
+ * @author Erik C. Thauvin
+ * @version $Revision$, $Date$
+ * @created Oct 30, 2008
+ * @since 1.0
+ */
+public class SpellIt extends Activity
+{
+ private static final int MAX_HISTORY_SIZE = 15;
+ private static final int MENU_ABOUT = 0;
+ private static final int MENU_NATO = 1;
+ private static final String PREFS_HISTORY = "history";
+ private static final String PREFS_NAME = "SpellIt";
+ private static final String PREFS_NATO = "nato";
+
+ private String[] mAlphabet;
+ private int mCurrentChar = -1;
+ private String mEntry;
+ private final List mHistory = new ArrayList(MAX_HISTORY_SIZE);
+ private boolean mNato;
+
+ /**
+ * Adds to the history.
+ *
+ * @param entry The entry to add.
+ */
+ private void addHistory(String entry)
+ {
+ if (!mHistory.contains(entry))
+ {
+ if (mHistory.size() >= MAX_HISTORY_SIZE)
+ {
+ mHistory.remove(0);
+ }
+
+ mHistory.add(entry);
+
+ savePrefs();
+ }
+ }
+
+ /**
+ * Returns the specified phonetic alphabet value.
+ *
+ * @param index The desired alphabet index.
+ * @return The specified alphabet value.
+ */
+ private String getAlphabet(int index)
+ {
+ return mAlphabet[index];
+ }
+
+ /**
+ * Returns the current character count.
+ *
+ * @return The current character count.
+ */
+ private int getCurrentChar()
+ {
+ return mCurrentChar;
+ }
+
+ /**
+ * Gets the current entry.
+ *
+ * @return The new entry.
+ */
+ private String getEntry()
+ {
+ return mEntry;
+ }
+
+ /**
+ * Returns the current version number.
+ *
+ * @return The current version number or empty.
+ */
+ private String getVersionNumber()
+ {
+ try
+ {
+ return getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
+ }
+ catch (final NameNotFoundException e)
+ {
+ return "";
+ }
+ }
+
+ /**
+ * Initializes the various controls.
+ */
+ private void init()
+ {
+ final AutoCompleteTextView entryFld = (AutoCompleteTextView) findViewById(R.id.main_entry_fld);
+ final Button spellBtn = (Button) findViewById(R.id.main_spell_btn);
+ final TextView resultFld = (TextView) findViewById(R.id.main_result_fld);
+ final TextView tapLbl = (TextView) findViewById(R.id.main_tap_lbl);
+
+ final SharedPreferences settings = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
+
+ setHistory(settings.getString(PREFS_HISTORY, ""));
+ setNato(settings.getBoolean(PREFS_NATO, false));
+ setAutoComplete(entryFld);
+ setAlphabet(isNato());
+
+ final ClipboardManager clip = (ClipboardManager) getSystemService(android.content.Context.CLIPBOARD_SERVICE);
+ if (clip.hasText())
+ {
+ entryFld.setText(clip.getText());
+ }
+
+ entryFld.setOnClickListener(new Button.OnClickListener()
+ {
+ public void onClick(View view)
+ {
+ spellBtn.performClick();
+ }
+ });
+
+ spellBtn.setOnClickListener(new Button.OnClickListener()
+ {
+ public void onClick(View view)
+ {
+ final String newEntry = entryFld.getText().toString();
+
+ if (!TextUtils.isEmpty(newEntry))
+ {
+ tapLbl.setText(R.string.main_tap_lbl_txt);
+
+ if (!newEntry.equals(getEntry()))
+ {
+ setEntry(newEntry);
+ setCurrentChar(0);
+ addHistory(getEntry());
+ setAutoComplete(entryFld);
+ }
+ showNextChar(resultFld, tapLbl);
+ }
+ else
+ {
+ Toast.makeText(SpellIt.this, R.string.main_entry_err_txt, Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+
+ resultFld.setOnClickListener(new Button.OnClickListener()
+ {
+ public void onClick(View view)
+ {
+ if (getCurrentChar() >= 0)
+ {
+ showNextChar(resultFld, tapLbl);
+ }
+ }
+ });
+
+ tapLbl.setOnClickListener(new Button.OnClickListener()
+ {
+ public void onClick(View view)
+ {
+ if (getCurrentChar() >= 0)
+ {
+ showNextChar(resultFld, tapLbl);
+ }
+ }
+ });
+ }
+
+ /**
+ * Returns the NATO flag.
+ *
+ * @return The NATO flag.
+ */
+ private boolean isNato()
+ {
+ return mNato;
+ }
+
+ /**
+ * Called when the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ init();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu)
+ {
+ menu.add(0, MENU_ABOUT, 0, R.string.about_menu_txt).setIcon(android.R.drawable.ic_menu_info_details);
+ menu.add(0, MENU_NATO, 0, R.string.nato_menu_txt);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item)
+ {
+ if (item.getItemId() == MENU_ABOUT)
+ {
+ final LayoutInflater factory = LayoutInflater.from(this);
+ final View aboutView = factory.inflate(R.layout.about, null);
+
+ new AlertDialog.Builder(this).setView(aboutView).setIcon(android.R.drawable.ic_dialog_info).setTitle(
+ getString(R.string.app_name) + ' ' + getVersionNumber()).setPositiveButton(R.string.alert_dialog_ok,
+ new DialogInterface.OnClickListener()
+ {
+ public void onClick(DialogInterface dialog, int whichButton)
+ {
+ // do nothing
+ }
+ }).show();
+
+ return true;
+ }
+ else if (item.getItemId() == MENU_NATO)
+ {
+ setAlphabet(toggleNato());
+ savePrefs();
+
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu)
+ {
+ super.onPrepareOptionsMenu(menu);
+
+ if (isNato())
+ {
+ menu.findItem(MENU_NATO).setIcon(android.R.drawable.presence_online);
+ }
+ else
+ {
+ menu.findItem(MENU_NATO).setIcon(android.R.drawable.presence_offline);
+ }
+
+ return true;
+ }
+
+ /**
+ * Saves the preferences.
+ */
+ private void savePrefs()
+ {
+ final SharedPreferences settings = getSharedPreferences(getString(R.string.app_name), Context.MODE_PRIVATE);
+ final SharedPreferences.Editor editor = settings.edit();
+ editor.putString(PREFS_HISTORY, TextUtils.join(",", mHistory));
+ editor.putBoolean(PREFS_NATO, isNato());
+ editor.commit();
+ }
+
+ /**
+ * Set the alphabet.
+ *
+ * @param isNato The NATO flag.
+ */
+ private void setAlphabet(Boolean isNato)
+ {
+ if (isNato)
+ {
+ mAlphabet = getResources().getStringArray(R.array.nato_alphabet);
+ }
+ else
+ {
+ mAlphabet = getResources().getStringArray(R.array.alphabet);
+ }
+ }
+
+ /**
+ * Sets the auto-complete values of the specified field.
+ *
+ * @param field The field to the auto-complete for.
+ */
+ private void setAutoComplete(AutoCompleteTextView field)
+ {
+ final ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, mHistory);
+ field.setAdapter(adapter);
+ }
+
+ /**
+ * Sets the current character count.
+ *
+ * @param count The current character count to set.
+ */
+ private void setCurrentChar(int count)
+ {
+ mCurrentChar = count;
+ }
+
+ /**
+ * Sets the current entry.
+ *
+ * @param entry The entry to set.
+ */
+ private void setEntry(String entry)
+ {
+ mEntry = entry;
+ }
+
+ /**
+ * Sets the history.
+ *
+ * @param history The comma-delimited history string.
+ */
+ private void setHistory(String history)
+ {
+ final String[] entries = TextUtils.split(history, ",");
+ for (final String entry : entries)
+ {
+ mHistory.add(entry);
+ }
+ }
+
+ /**
+ * Sets the NATO flag.
+ *
+ * @param nato The new NATO flag.
+ */
+ private void setNato(boolean isNato)
+ {
+ mNato = isNato;
+ }
+
+ private void showNextChar(TextView view, TextView label)
+ {
+ if (getCurrentChar() < getEntry().length())
+ {
+ final char c = getEntry().charAt(getCurrentChar());
+
+ if ((c < 123) && (c > 96))
+ {
+ int offset = 97;
+
+ if ((c < 91) && (c > 64))
+ {
+ offset = 65;
+ }
+
+ view.setText(String.valueOf(c).toUpperCase() + ' ' + getString(R.string.as_in_txt) + ' ' + getAlphabet(c - offset));
+ }
+ else if ((c < 58) && (c > 47))
+ {
+ view.setText(getAlphabet(c - 22));
+ }
+ else if (c == ' ')
+ {
+ view.setText(getString(R.string.space_txt));
+ }
+ else
+ {
+ view.setText(String.valueOf(c));
+ }
+
+ setCurrentChar(getCurrentChar() + 1);
+ }
+ else
+ {
+ view.setText(getString(R.string.done_txt));
+ label.setText(getString(R.string.main_tap_lbl_repeat_txt));
+ setCurrentChar(0);
+ }
+ }
+
+ /**
+ * Toggles the NATO flag.
+ *
+ * @return The NATO flag value.
+ */
+ private boolean toggleNato()
+ {
+ mNato ^= true;
+
+ return mNato;
+ }
+
+}
\ No newline at end of file