gt: 			s = Enigma.removeDigit(s, max_protocol_version);
context: /**
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * any later version.
   *
   * This program 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 General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  package de.vanitasvitae.enigmandroid;
  
  import android.app.Activity;
  import android.app.AlertDialog;
  import android.app.Dialog;
  import android.content.ClipData;
  import android.content.DialogInterface;
  import android.content.Intent;
  import android.content.SharedPreferences;
  import android.content.pm.PackageInfo;
  import android.content.pm.PackageManager;
  import android.net.Uri;
  import android.os.Bundle;
  import android.preference.PreferenceManager;
  import android.text.InputType;
  import android.util.Log;
  import android.view.Menu;
  import android.view.MenuItem;
  import android.view.View;
  import android.widget.Button;
  import android.widget.EditText;
  import android.widget.LinearLayout;
  import android.widget.TextView;
  import android.widget.Toast;
  
  import com.google.zxing.integration.android.IntentIntegrator;
  import com.google.zxing.integration.android.IntentResult;
  
  import java.math.BigInteger;
  import java.security.SecureRandom;
  
  import de.vanitasvitae.enigmandroid.enigma.Enigma;
  import de.vanitasvitae.enigmandroid.enigma.EnigmaStateBundle;
  import de.vanitasvitae.enigmandroid.enigma.inputPreparer.InputPreparer;
  import de.vanitasvitae.enigmandroid.layout.LayoutContainer;
  import de.vanitasvitae.enigmandroid.layout.PassphraseDialogBuilder;
  
  public class MainActivity extends Activity
  {
  	private static final int RESULT_SETTINGS = 1;
  	private static final String URI_CHANGELOG =
  			"https://github.com/vanitasvitae/EnigmAndroid/blob/master/CHANGELOG.txt";
  	public static final String APP_ID = "EnigmAndroid";
  	public static final int latest_protocol_version = 1;
  	public static final int max_protocol_version = 256;
  
  	private LayoutContainer layoutContainer;
  
  	private SecureRandom secureRandom;
  
  	@Override
  	public void onCreate(Bundle savedInstanceState)
  	{
  		super.onCreate(savedInstanceState);
  		secureRandom = new SecureRandom();
  		ActivitySingleton.getInstance().setActivity(this);
  		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
  		SettingsActivity.SettingsSingleton.getInstance(prefs, getResources());
  		layoutContainer = LayoutContainer.createLayoutContainer();
  
  		//Handle shared text
  		Intent intent = getIntent();
  		String action = intent.getAction();
  		String type = intent.getType();
  		if (Intent.ACTION_SEND.equals(action) && type != null) {
  			if ("text/plain".equals(type))
  			{
  				String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
  				if (sharedText != null)
  				{
  					//If shared text consists of an encoded configuration, try to restore it
  					if(sharedText.startsWith(APP_ID+"/"))
  						restoreStateFromCode(sharedText);
  						//Else put it in the input text box
  					else
  						layoutContainer.getInput().setRawText(sharedText);
  				}
  			}
  		}
  	}
  
  	public SecureRandom getSecureRandom()
  	{
  		return this.secureRandom;
  	}
  
  	public void onDialogFinished(EnigmaStateBundle state)
  	{
  		layoutContainer.getEnigma().setState(state);
  	}
  
  	@Override
  	public boolean onCreateOptionsMenu(Menu menu)
  	{
  		this.getMenuInflater().inflate(R.menu.main, menu);
  		return true;
  	}
  
  	@Override
  	/**
  	 * Handle Options menu clicks
  	 */
  	public boolean onOptionsItemSelected(MenuItem item)
  	{
  		int id = item.getItemId();
  		if (id == R.id.action_reset)
  		{
  			layoutContainer.resetLayout();
  			Toast.makeText(getApplicationContext(), R.string.message_reset,
  					Toast.LENGTH_SHORT).show();
  			return true;
  		}
  		else if (id == R.id.action_send_message)
  		{
  			if(layoutContainer.getOutput().getText().length() == 0)
  			{
  				Toast.makeText(this, R.string.error_no_text_to_send, Toast.LENGTH_SHORT).show();
  			}
  			else
  			{
  				Intent sendIntent = new Intent();
  				sendIntent.setAction(Intent.ACTION_SEND);
  				sendIntent.putExtra(Intent.EXTRA_TEXT, layoutContainer.getOutput().getModifiedText());
  				sendIntent.setType("text/plain");
  				startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
  			}
  		}
  		else if (id == R.id.action_choose_ringsetting)
  		{
  			layoutContainer.showRingSettingsDialog();
  			return true;
  		}
  		else if(id == R.id.action_share_configuration)
  		{
  			showShareConfigurationDialog();
  		}
  		else if (id == R.id.action_restore_configuration)
  		{
  			showReceiveConfigurationDialog();
  			return true;
  		}
  		else if (id == R.id.action_random_configuration)
  		{
  			layoutContainer.getEnigma().randomState();
  			layoutContainer.syncStateFromEnigmaToLayout();
  			Toast.makeText(getApplicationContext(), R.string.message_random,
  					Toast.LENGTH_SHORT).show();
  			layoutContainer.getOutput().setText("");
  			return true;
  		}
  		else if (id == R.id.action_settings)
  		{
  			Intent i = new Intent(this, SettingsActivity.class);
  			startActivityForResult(i, RESULT_SETTINGS);
  		}
  		else if (id == R.id.action_about)
  		{
  			showAboutDialog();
  			return true;
  		}
  		return super.onOptionsItemSelected(item);
  	}
  
  	/**
  	 * Set the chosen Configuration to the enigma, get the input string from the input text box and
  	 * prepare it, set the input to the prepared text, encrypt the prepared input and set the
  	 * encrypted string to the output text box and update the spinners to their new positions.
  	 * @param v View
  	 */
  	public void doCrypto(View v)
  	{
  		layoutContainer.doCrypto();
  	}
  
  	/**
  	 * Start an intent to share the configuration as QR-Code via Barcode Scanner
  	 */
  	private void shareConfigurationAsQR()
  	{
  		IntentIntegrator QRIntegrator = new IntentIntegrator(this);
  		layoutContainer.syncStateFromLayoutToEnigma();
  		String encoded_state = APP_ID+"/"+layoutContainer.getEnigma().getEncodedState().toString(16);
  		Log.d(APP_ID, "Sharing configuration to QR: "+encoded_state);
  		QRIntegrator.shareText(encoded_state);
  	}
  
  	/**
  	 * Start an intent to share the configuration as text
  	 */
  	private void shareConfigurationAsText()
  	{
  		Intent sendIntent = new Intent();
  		sendIntent.setAction(Intent.ACTION_SEND);
  		sendIntent.putExtra(Intent.EXTRA_TEXT,
  				APP_ID+"/"+layoutContainer.getEnigma().getEncodedState().toString(16));
  		sendIntent.setType("text/plain");
  		startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
  	}
  
  	/**
  	 * Start the barcode app to scan a barcode for configuration
  	 */
  	private void receiveConfigurationQR()
  	{
  		IntentIntegrator integrator = new IntentIntegrator(this);
  		integrator.initiateScan();
  	}
  
  	/**
  	 * Show a dialog to restore a configuration
  	 */
  	private void receiveConfigurationText()
  	{
  		new PassphraseDialogBuilder().showDialog();
  	}
  
  	/**
  	 * Show a Dialog containing information about the app, license, usage, author and a link
  	 * to the changelog
  	 */
  	private void showAboutDialog()
  	{
  		final View aboutView = View.inflate(this, R.layout.dialog_about, null);
  		//Get and set Version code
  		PackageInfo pInfo = null;
  		try{ pInfo = getPackageManager().getPackageInfo(this.getPackageName(), 0);}
  		catch (PackageManager.NameNotFoundException e){ e.printStackTrace();}
  		assert pInfo != null;
  		String version = pInfo.versionName+ " ("+pInfo.versionCode+")";
  		TextView versionText = (TextView) aboutView.findViewById(R.id.about_version_section);
  		versionText.setText(version);
  
  		//Build and show dialog
  		AlertDialog.Builder builder = new AlertDialog.Builder(this);
  		builder.setTitle(R.string.title_about_dialog);
  		builder.setView(aboutView)
  				.setCancelable(true)
  				.setPositiveButton(R.string.dialog_positive, new DialogInterface.OnClickListener()
  				{
  					public void onClick(DialogInterface dialog, int id)
  					{
  						dialog.dismiss();
  					}
  				})
  				.setNegativeButton(R.string.button_show_changelog, new DialogInterface.OnClickListener()
  				{
  					public void onClick(DialogInterface dialog, int id)
  					{
  						dialog.cancel();
  						openWebPage(URI_CHANGELOG);
  					}
  				}).show();
  	}
  
  	/**
  	 * Show a dialog where the user can choose between sharing the configuration via QR-code or
  	 * via string (intent or copy-to-clipboard)
  	 */
  	private void showShareConfigurationDialog()
  	{
  		final String configuration = APP_ID+"/"+layoutContainer.getEnigma().getEncodedState().toString(16);
  		final View shareView = View.inflate(this, R.layout.dialog_two_options, null);
  		LinearLayout l = (LinearLayout) shareView.findViewById(R.id.dialog_two_options_lay);
  		EditText e = new EditText(this);
  		e.setText(configuration);
  		e.setInputType(InputType.TYPE_NULL);
  		e.setOnClickListener(new View.OnClickListener()
  		{
  			@Override
  			public void onClick(View v)
  			{
  				if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB){
  					android.content.ClipboardManager clipboard =  (android.content.ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
  					ClipData clip;
  					clip = ClipData.newPlainText("label", configuration);
  					clipboard.setPrimaryClip(clip);
  				} else{
  					@SuppressWarnings("deprecation")
  					android.text.ClipboardManager clipboard = (android.text.ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
  					clipboard.setText(configuration);
  				}
  				Toast.makeText(getApplicationContext(), R.string.message_clipboard, Toast.LENGTH_SHORT).show();
  			}
  		});
  		l.addView(e);
  		AlertDialog.Builder builder = new AlertDialog.Builder(this);
  		builder.setTitle(R.string.dialog_title_share_configuration)
  				.setView(shareView).setCancelable(true);
  		final Dialog d = builder.create();
  		Button one = (Button) shareView.findViewById(R.id.dialog_two_options_1);
  		one.setText(R.string.dialog_share_qr);
  		one.setOnClickListener(new View.OnClickListener()
  		{
  			@Override
  			public void onClick(View v)
  			{
  				shareConfigurationAsQR();
  				d.dismiss();
  			}
  		});
  		Button two = (Button) shareView.findViewById(R.id.dialog_two_options_2);
  		two.setText(R.string.dialog_share_code);
  		two.setOnClickListener(new View.OnClickListener()
  		{
  			@Override
  			public void onClick(View v)
  			{
  				shareConfigurationAsText();
  				d.dismiss();
  			}
  		});
  		d.show();
  	}
  
  	/**
  	 * Show a dialog, where the user can choose between scanning QR-code and entering a string to
  	 * restore the encoded configuration
  	 */
  	private void showReceiveConfigurationDialog()
  	{
  		final View shareView = View.inflate(this, R.layout.dialog_two_options, null);
  		AlertDialog.Builder builder = new AlertDialog.Builder(this);
  		builder.setTitle(R.string.dialog_title_restore_configuration)
  				.setView(shareView).setCancelable(true);
  		final Dialog d = builder.create();
  		Button one = (Button) shareView.findViewById(R.id.dialog_two_options_1);
  		one.setText(R.string.dialog_restore_qr);
  		one.setOnClickListener(new View.OnClickListener()
  		{
  			@Override
  			public void onClick(View v)
  			{
  				receiveConfigurationQR();
  				d.dismiss();
  			}
  		});
  		Button two = (Button) shareView.findViewById(R.id.dialog_two_options_2);
  		two.setText(R.string.dialog_restore_code);
  		two.setOnClickListener(new View.OnClickListener()
  		{
  			@Override
  			public void onClick(View v)
  			{
  				receiveConfigurationText();
  				d.dismiss();
  			}
  		});
  		d.show();
  	}
  
  	/**
  	 * Handle Activity Results
  	 * @param requestCode requestCode
  	 * @param resultCode resultCode (RESULT_SETTINGS is defined at the top)
  	 * @param data data
  	 */
  	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  		super.onActivityResult(requestCode, resultCode, data);
  		switch (requestCode) {
  			//Come back from Settings
  			case RESULT_SETTINGS:
  			{
  				applyPreferenceChanges();
  				break;
  			}
  			// Receive from QR
  			case IntentIntegrator.REQUEST_CODE:
  				IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
  				if (scanResult != null) {
  					String content = scanResult.getContents();
  					if(content == null) Log.e(APP_ID, "Error! Received nothing from QR-Code!");
  					else {
  						Log.d(APP_ID, "Received " + content + " from QR-Code!");
  						restoreStateFromCode(content);
  					}
  				}
  		}
  	}
  
  	/**
  	 * Handle changes in preferences and apply those changes to the app
  	 */
  	private void applyPreferenceChanges()
  	{
  		SettingsActivity s = SettingsActivity.SettingsSingleton.getInstance();
  		if(s.prefMachineTypeChanged())
  		{
  			layoutContainer = LayoutContainer.createLayoutContainer();
  		}
  		if(s.prefMessageFormattingChanged())
  		{
  			layoutContainer.setEditTextAdapter(s.getPrefMessageFormatting());
  		}
  		if(s.prefNumericLanguageChanged())
  		{
  			layoutContainer.setInputPreparer(InputPreparer.createInputPreparer());
  		}
  	}
  
  	/**
  	 * Set EnigmAndroid into a certain state as described in the QR-Code
  	 * @param mem content of the QR-Code
  	 */
  	public void restoreStateFromCode(String mem)
  	{
  		if(!mem.startsWith(APP_ID+"/"))
  		{
  			Toast.makeText(this, R.string.error_no_valid_qr, Toast.LENGTH_LONG).show();
  		}
  		else
  		{
  			String inputString = layoutContainer.getInput().getText();
  			mem = mem.substring((APP_ID+"/").length());
  			BigInteger s = new BigInteger(mem, 16);
  			int protocol_version = Enigma.getValue(s, max_protocol_version);
  