	public boolean onKey(View v, int keycode, KeyEvent event) {
		if (keycode == KeyEvent.KEYCODE_ENTER && event.getAction()==KeyEvent.ACTION_UP) {
			tabCompletingInProgress=false;
			runOnUiThread(messageSender);
			return true;
		} else if((keycode == KeyEvent.KEYCODE_TAB || keycode == KeyEvent.KEYCODE_SEARCH) && event.getAction() == KeyEvent.ACTION_DOWN) {
			if (!enableTabComplete || nickCache == null) return true;
			String txt = inputBox.getText().toString();
			if (tabCompletingInProgress == false) {
				int currentPos = inputBox.getSelectionStart()-1;
				int start = currentPos;
				while(start>0 && txt.charAt(start) != ' ') start--;
				if (start>0) start++;
				String prefix = txt.substring(start, currentPos+1).toLowerCase();
				if (prefix.length()<2) {
					return true;
				}
				Vector<String> matches = new Vector<String>();
				for(String possible: nickCache) {
					String temp = possible.toLowerCase().trim();
					if (temp.startsWith(prefix)) {
						matches.add(possible.trim());
					}
				}
				if (matches.size() == 0) return true;
				tabCompletingInProgress = true;
				tabCompleteMatches = matches;
				tabCompleteCurrentIndex = 0;
				tabCompleteWordStart = start;
				tabCompleteWordEnd = currentPos;
			} else {
				tabCompleteWordEnd = tabCompleteWordStart + tabCompleteMatches.get(tabCompleteCurrentIndex).length()-1; 
				tabCompleteCurrentIndex = (tabCompleteCurrentIndex+1)%tabCompleteMatches.size(); 
			}
			String newtext = txt.substring(0, tabCompleteWordStart) + tabCompleteMatches.get(tabCompleteCurrentIndex) + txt.substring(tabCompleteWordEnd+1);
			tabCompleteWordEnd = tabCompleteWordStart + tabCompleteMatches.get(tabCompleteCurrentIndex).length(); 
			inputBox.setText(newtext);
			inputBox.setSelection(tabCompleteWordEnd);
			return true;
		} else if(KeyEvent.isModifierKey(keycode) || keycode == KeyEvent.KEYCODE_TAB || keycode == KeyEvent.KEYCODE_SEARCH) {
			return true;
		}
		tabCompletingInProgress = false;
		return false;
	}

	public boolean onKey(View v, int keycode, KeyEvent event) {
		if (keycode == KeyEvent.KEYCODE_ENTER && event.getAction()==KeyEvent.ACTION_UP) {
			tabCompletingInProgress=false;
			runOnUiThread(messageSender);
			return true;
		} else if((keycode == KeyEvent.KEYCODE_TAB || keycode == KeyEvent.KEYCODE_SEARCH) && event.getAction() == KeyEvent.ACTION_DOWN) {
			if (!enableTabComplete || nickCache == null) return true;
			String txt = inputBox.getText().toString();
			if (tabCompletingInProgress == false) {
				int currentPos = inputBox.getSelectionStart()-1;
				int start = currentPos;
				while(start>0 && txt.charAt(start) != ' ') start--;
				if (start>0) start++;
				String prefix = txt.substring(start, currentPos+1).toLowerCase();
				if (prefix.length()<2) {
					return true;
				}
				Vector<String> matches = new Vector<String>();
				for(String possible: nickCache) {
					String temp = possible.toLowerCase().trim();
					if (temp.startsWith(prefix)) {
						matches.add(possible.trim());
					}
				}
				if (matches.size() == 0) return true;
				tabCompletingInProgress = true;
				tabCompleteMatches = matches;
				tabCompleteCurrentIndex = 0;
				tabCompleteWordStart = start;
				tabCompleteWordEnd = currentPos;
			} else {
				tabCompleteWordEnd = tabCompleteWordStart + tabCompleteMatches.get(tabCompleteCurrentIndex).length()-1; 
				tabCompleteCurrentIndex = (tabCompleteCurrentIndex+1)%tabCompleteMatches.size(); 
			}
			String newtext = txt.substring(0, tabCompleteWordStart) + tabCompleteMatches.get(tabCompleteCurrentIndex) + txt.substring(tabCompleteWordEnd+1);
			tabCompleteWordEnd = tabCompleteWordStart + tabCompleteMatches.get(tabCompleteCurrentIndex).length(); 
			inputBox.setText(newtext);
			inputBox.setSelection(tabCompleteWordEnd);
			return true;
		} else if(KeyEvent.isModifierKey(keycode) || keycode == KeyEvent.KEYCODE_TAB || keycode == KeyEvent.KEYCODE_SEARCH) {
			return false;
		}
		tabCompletingInProgress = false;
		return false;
	}
