Newer
Older
Import / projects / LGN-IP3870 / t / orig / automata.py
# -*- coding: utf_8 -*-

import config, utils
from setting import setting
#import hangul
import struct # KA: [20070813] hangul

FIRSTCAPITAL='first capital'
UPPERCASE='upper'
LOWERCASE='lower'

class AutomataBase:
	def __init__(self, edit):
		pass

	def name(self):
		pass

	def free(self):
		del self._edit

	def reset(self):
		pass

	def set_case_mode(self, case_mode):
		pass

	def ori_set_case_mode(self, case_mode):
		pass

	def case_mode(self):
		pass

	def check_start_of_sentance(self):
		pass

	def handle_key(self, key):
		if len(key) == 2 and key[0] == 'L':
			# it's long key
			self.reset()
			self._edit.insert_unicode_text(unicode(key[1], 'utf-8'), ul=False)
			self.reset()
			return True
		return False

class Automata(AutomataBase):

	MODE_ALPHA = 0
	MODE_NUMBER = 1

	def __init__(self, edit):
		self.table = {
			# shchun : remove european alphabet input, temp.
			# TODO: re-implement european alphabet
			#'1':('.', ',', '?',  '!', '1', '@', '\xc2\x92', '-', '_', '(', ')', ':', ';', '&', '/', '%', '*', '#'),
			'2':('A', 'B', 'C', '2'),
			'3':('D', 'E', 'F', '3'),
			'4':('G', 'H', 'I', '4'),
			'5':('J', 'K', 'L', '5'),
			'6':('M', 'N', 'O', '6'),
			'7':('P', 'Q', 'R', 'S', '7'),
			'8':('T', 'U', 'V', '8'),
			'9':('W', 'X', 'Y', 'Z', '9'),
			'0':('.', ',', '?', '!', '0'),
		}

		self.idx_table = {
			'1':(0, 0),
			'2':(0, 0),
			'3':(0, 0),
			'4':(0, 0),
			'5':(0, 0),
			'6':(0, 0),
			'7':(0, 0),
			'8':(0, 0),
			'9':(0, 0),
			'0':(0, 0),
		}

		print '### AUTOMATA @@@', edit.email_mode, edit.ascii_mode_case0, edit.ascii_mode_case1, edit.ascii_mode_case2, edit.ascii_mode_case3
		
		self._edit = edit
		self._timeout_tag = None
		self._mode = self.MODE_ALPHA
		self._last_ch = ''
		self._case_mode = LOWERCASE
		self.ori_case_mode = LOWERCASE

		if edit.email_mode:
			#self.table['1'] = ('@', '.', ',', '?', '!', '1', '-', '"', ':', ';', '(', ')', '쩔', '징')
			self.table['1'] = ('@', ':', '/', '1')
			self.idx_table['1'] = (0,0)

		if edit.ascii_mode_case0:
			'''
			# old requirement
			self.table = {
				# shchun: according to telio requirement
				'1':('.', ',', '?',  '!', '1', '@', '\'', '-', '_', '(', ')', ':', ';', '&', '/', '%', '*', '#', '+', '<', '=', '>', '\"', '$', '\xc2\xa3', '\xc2\xa7', '\xc2\xa5', '\xc2\xa1'),
				'2':('A', 'B', 'C', '2','\xc3\x84','\xc3\x81', '\xc3\x80', '\xc3\x82', '\xc3\x83', '\xc3\x85', '\xc3\x86', '\xc3\x87'),
				'3':('D', 'E', 'F', '3', '\xc3\x8b', '\xc3\x89', '\xc3\x88', '\xc3\x8a', '\xc4\x90'),
				'4':('G', 'H', 'I', '4', '\xc3\x8f', '\xc3\x8d', '\xc3\x8c', '\xc3\x8e'),
				'5':('J', 'K', 'L', '5', '\xc2\xa3'),
				'6':('M', 'N', 'O', '6'),
				'7':('P', 'Q', 'R', 'S', '7','\xc3\x9f', '$'),
				'8':('T', 'U', 'V', '8', '\xc3\x9c','\xc3\x9a','\xc3\x99','\xc3\x9b'),
				'9':('W', 'X', 'Y', 'Z', '9','\xc3\x9d','\xc3\x9e'),
				'0':(' ', '0',  '\n'),
			}
			'''
			# modified:  2009/01/16
			self.table = {
				# shchun: according to telio requirement
				'1':('.', ',', '?',  '!', '1', '-', '@', '\"', ':', ';', '(', ')', '&', '*', '#', '$', '\xc2\xa3', '\xc2\xa7', '\xc2\xa5', '\xc2\xa1'),
				'2':('A', 'B', 'C', '2','\xc3\x80', '\xc3\x81', '\xc3\x84', '\xc3\x87', '\xc3\x82', '\xc3\x83', '\xc3\x85', '\xc3\x86'),
				'3':('D', 'E', 'F', '3',  '\xc3\x88', '\xc3\x89', '\xc3\x8b', '\xc3\x8a', '\xc4\x90'),
				'4':('G', 'H', 'I', '4', '\xc3\x8c', '\xc3\x8d', '\xc3\x8f', '\xc3\x8e'),
				'5':('J', 'K', 'L', '5', '\xc2\xa3'),
				'6':('M', 'N', 'O', '6', '\xc3\x92', '\xc3\x93', '\xc3\x96', '\xc3\x91' ),
				'7':('P', 'Q', 'R', 'S', '7','\xc3\x9f', '$'),
				'8':('T', 'U', 'V', '8', '\xc3\x99', '\xc3\x9a', '\xc3\x9c', '\xc3\x9b'),
				'9':('W', 'X', 'Y', 'Z', '9','\xc3\x9d','\xc3\x9e'),
				'0':(' ', '0',  '_', '\'', '+', '=', '/', '\\', '<', '>', '%'),
			}

		elif edit.ascii_mode_case1:
			self.table = {
				#'1':('.', ',', '?', '!', '1', '-', '@', ':', ';', '(', ')'),
				'1':('@', ':', '/', '1'),
				'2':('A', 'B', 'C', '2'),
				'3':('D', 'E', 'F', '3'),
				'4':('G', 'H', 'I', '4'),
				'5':('J', 'K', 'L', '5'),
				'6':('M', 'N', 'O', '6'),
				'7':('P', 'Q', 'R', 'S', '7', '*', '$', '&', '[', ']', '|'),
				'8':('T', 'U', 'V', '8'),
				'9':('W', 'X', 'Y', 'Z', '9', '#', '~', '^', '`', '{', '}'),
				#'0':(' ', '0', '_', '\'', '+', '=', '/', '<', '>', '%'),
				'0':('.', ',', '?', '!', '0'),
			}
		elif edit.ascii_mode_case2:
			self.table = {
				#'1':('.', ',', '!', '1', '-', '(', ')'),
				'1':('@', ':', '/', '1'),
				'2':('A', 'B', 'C', '2'),
				'3':('D', 'E', 'F', '3'),
				'4':('G', 'H', 'I', '4'),
				'5':('J', 'K', 'L', '5'),
				'6':('M', 'N', 'O', '6'),
				'7':('P', 'Q', 'R', 'S', '7', '*', '$', '&'),
				'8':('T', 'U', 'V', '8'),
				'9':('W', 'X', 'Y', 'Z', '9', '~'),
				#'0':('0', '_', '\'', '+', '='),
				'0':('.', ',', '?', '!', '0'),
			}
		elif edit.ascii_mode_case3:
			self.table = {
				#'1':('.', ',', '!', '1', '-', '(', ')'),
				'1':('@', ':', '/', '1'),
				'2':('A', 'B', 'C', '2'),
				'3':('D', 'E', 'F', '3'),
				'4':('G', 'H', 'I', '4'),
				'5':('J', 'K', 'L', '5'),
				'6':('M', 'N', 'O', '6'),
				'7':('P', 'Q', 'R', 'S', '7', '&'),
				'8':('T', 'U', 'V', '8'),
				'9':('W', 'X', 'Y', 'Z', '9', '~'),
				#'0':(' ','0', '_', '\'', '+', '='),
				'0':('.', ',', '?', '!', '0'),
			}

	def name(self):
		return 'multitap'

	def free(self):
		self._timeout_tag = None
		AutomataBase.free(self)

	def reset(self):
		self._last_ch = ''
		self.set_timer(False)
		self._edit.t9_helper_ul_reset()
		self._edit.cursor_show()

	def set_timer(self, set):
		def timeout_cb():
			self._last_ch = ''
			self._edit.t9_helper_ul_reset()
			self.check_start_of_sentance()
			self._edit.cursor_show()

			self._timeout_tag = None
			return False

		if set:
			self._timeout_tag = utils.Timer(1000, timeout_cb)
		else:
			self._timeout_tag = None

	def set_case_mode(self, case_mode):
		if self._case_mode != case_mode:
			self._case_mode = case_mode
			self.reset()

	def ori_set_case_mode(self, case_mode):
		self.ori_case_mode = case_mode

	def case_mode(self):
		return self._case_mode

	def char_mode(self, c):
		if c.isdigit():
			return self.MODE_NUMBER
		else:
			return self.MODE_ALPHA

	def check_start_of_sentance(self):
		if self._edit.is_start_of_sentance():
			if self._case_mode == LOWERCASE and self.ori_case_mode == FIRSTCAPITAL:
				self.set_case_mode(FIRSTCAPITAL)
			return
		else:
			if self._case_mode == FIRSTCAPITAL:
				self.set_case_mode(LOWERCASE)

	def handle_key(self, key):
		if AutomataBase.handle_key(self, key):
			return True

		ctrl_keys = []
		text = unicode('')

		if key == config.LongMenu2:
			self.reset()
			self._edit.set_text('')
			self.check_start_of_sentance()
			return True

		if key == 'Right':
			self._last_ch = ''
			self.set_timer(False)
			if self._edit.richtext:
				if self._edit.cursor_end_pos() and not self._edit.richtext.cursor_hidden:
					self._edit.insert_unicode_text(unicode(' ', 'utf-8'), ul=True)
			self._edit.cursor_forward()
			self._edit.t9_helper_ul_reset()
			self._edit.cursor_show()
			self.check_start_of_sentance()
			return True
			
		if key == 'CLR':
			self._last_ch = ''
			self.set_timer(False)
			self._edit.cursor_forward()
			self._edit.t9_helper_ul_reset()
			self._edit.cursor_show()
			self.check_start_of_sentance()
			return True

		if key in ('\b', 'Left', 'Up', 'Down','Home','End'):
			self.reset()
			self._edit.func_key_handler([(key, 1)])
			self.check_start_of_sentance()
			return True

		if self._edit.full() and not self._last_ch:
			return False

		if not key in self.table:
			return False

		if not self._last_ch:
			c = self._edit.cursor_adj_ch()
			if c:
				self._mode = self.char_mode(c)

		if self._last_ch and self._last_ch in self.table[key]:
				ctrl_keys.append(('\b',1))
				last_key_idx = list(self.table[key]).index(self._last_ch)
				if last_key_idx == len(self.table[key]) - 1:
					key_idx = 0
				else:
					key_idx = last_key_idx + 1

				text = self.table[key][key_idx]
		else:
			if self._edit.full():
				return False

			if self._last_ch:
				if self._last_ch not in (' ', '.', '?', '!'):
					if self._case_mode == FIRSTCAPITAL:
						self.set_case_mode(LOWERCASE)
				else:
					if self._case_mode == LOWERCASE:
						self.check_start_of_sentance()

			self.reset()
			text = self.table[key][self.idx_table[key][self._mode]]

		self._last_ch = text

		self._mode = self.char_mode(text)
		self.set_timer(True)
		text = unicode(text, 'utf-8')

		if self._case_mode == UPPERCASE:
			text = text.upper()
		elif self._case_mode == LOWERCASE:
			text = text.lower()
		elif self._case_mode == FIRSTCAPITAL:
			text = text.upper()

		self._edit.start_editing()
		if ctrl_keys: self._edit.func_key_handler(ctrl_keys)
		if text:
			self._edit.cursor_hide()
			self._edit.insert_unicode_text(text, ul=True)
		self._edit.end_editing()

		return True

# KA: [20070813] hangul
class Automata_ko(AutomataBase):

	MODE_ALPHA = 0
	MODE_NUMBER = 1

	def __init__(self, edit):
		self._edit = edit
		self._timeout_tag = None
		self._mode = self.MODE_ALPHA
		self._last_ch = ''
 		self._case_mode = LOWERCASE
 		self.ori_case_mode = LOWERCASE
		
		self.edit_state = 0 # 0: wating 1: picking
		self.text = ''
		
	def name(self):
		return 'hangul'
#		return 'multitap'

	def free(self):
		self._timeout_tag = None
		AutomataBase.free(self)

	def reset(self):
		self._last_ch = ''
		self.set_timer(False)
		self._edit.t9_helper_ul_reset()
		self._edit.cursor_show()

	def set_timer(self, set):
		def timeout_cb():
			self._last_ch = ''
			self._edit.t9_helper_ul_reset()
			self.check_start_of_sentance()
			self._edit.cursor_show()

			self._timeout_tag = None
			self.edit_state = 0	
			return False

		if set:
			self._timeout_tag = None
			# not to set timer in korean automata
			#self._timeout_tag = utils.Timer(2000, timeout_cb)
		else:
			self._timeout_tag = None
###### not use but may not delete.!!!~ #############################################
	def set_case_mode(self, case_mode): 
		if self._case_mode != case_mode:
			self._case_mode = case_mode
			self.reset()

	def ori_set_case_mode(self, case_mode):
 		self.ori_case_mode = case_mode

	def case_mode(self):
		return self._case_mode

	def char_mode(self, c):
		if c.isdigit():
			return self.MODE_NUMBER
		else:
			return self.MODE_ALPHA

	def check_start_of_sentance(self):
		if self._edit.is_start_of_sentance():
			if self._case_mode == LOWERCASE and self.ori_case_mode == FIRSTCAPITAL:
				self.set_case_mode(FIRSTCAPITAL)
			return
		else:
			if self._case_mode == FIRSTCAPITAL:
				self.set_case_mode(LOWERCASE)
########################################################################
	def key_exchange(self,input):
		ret = 0
		if input == '*':
			ret = int(11)
		elif input == '#':
			ret = int(12)
		elif input == '0':
			ret = int(10)
		elif input == '\b':
			ret = int(18)
		else:
			ret = int(input)

		return ret

	def output_exchange(self,ret): # change byte object -> python string object
		print ret
		t_key = []

		t_key.append(ret[0]) # return value

		b = ret[1]
		print b
		b_1 = b >> 8
		b_2 = b & 255
		tmp_data1 = struct.pack('hh',b_1,b_2)

		tmp_key1 = tmp_data1[1] + tmp_data1[3]
		t_key.append(tmp_key1)	# output value 1

		c = ret[2]
		print c
		c_1 = c >> 8
		c_2 = c & 255
		tmp_data2 = struct.pack('hh',c_1,c_2)
		tmp_key2 = tmp_data2[1] + tmp_data2[3]
		t_key.append(tmp_key2)	# output value 2

		return t_key


	def handle_key(self, key):
		if AutomataBase.handle_key(self, key):
			return True
		ctrl_keys = []
		self.text = unicode('')

		if key == config.LongMenu2:
			self.reset()
			self.edit_state = 0
			self._edit.set_text('')
 
			return True

		if key == 'Right':
			self._last_ch = ''
			self.edit_state = 0			
			self.set_timer(False)
			if self._edit.richtext:
				if self._edit.cursor_end_pos() and not self._edit.richtext.cursor_hidden:
					self._edit.insert_unicode_text(unicode(' ', 'utf-8'), ul=True)
			self._edit.cursor_forward()
			self._edit.t9_helper_ul_reset()
			self._edit.cursor_show()
 
			return True

		if key in ('Left', 'Up', 'Down','Home','End','MMS'):
			self.reset()
			self.edit_state = 0			
			if key == 'MMS':
				self._edit.func_key_handler([('Space', 1)])
			else:
				self._edit.func_key_handler([(key, 1)])
 
			return True

# ka...hangul 2007.01.22 
		if key == 'SOFT3':
			self.reset()
			self.edit_state = 0
			return True
# --- end of Adding

		if key == 'CLR':
			self._last_ch = ''
			self.edit_state = 0			
			self.set_timer(False)
			self._edit.cursor_forward()
			self._edit.t9_helper_ul_reset()
			self._edit.cursor_show()
			return True
			
		if key =='\b':
			self.reset()
			#ka...hangul TEST 2007.01.18
			if self.edit_state == 0:
				self.edit_state = 0					
				self._edit.func_key_handler([(key, 1)])		
 			
				return True
			elif self.edit_state == 1:
				# KA: [20070905] hangul lvp-2000 When reaching max entry, cannot delete.
				if self._edit.full():
					self.edit_state = 0					
					self._edit.func_key_handler([(key, 1)])
					return True
				else:
					pass
# KA: [20070914] input max check moved
#		if self._edit.full() and not self._last_ch:
#			return False
 
		self._last_ch = self.text
		if key in ('0', '1', '2', '3','4','5','6','7','8','9','0','*','#','\b'):
			self.reset()
			self.set_timer(True)
			if config.hangul_debug:
				print '[hangul] edit_state = ', self.edit_state
			if self.edit_state == 0: 				# If the beginning of hangul input : ex) 'ㅁ'
				hangul.ClearHangulTable()
				if key == '*' or key == '#':		# press '*' or '#' when waiting state
					return True
				# KA: [20070914] input max check
				if self._edit.full():
					return True
				# KA: [20070914] input max ==
				hangul.AddHangulTable(self.key_exchange(key))
				ret_tmp = hangul.GetHangulTable()
				ret_obj = self.output_exchange(ret_tmp)
				print ret_obj	
				self.text = utils.f_unicode_encoding(ret_obj[1])
				self._edit.start_editing()
  				if self.text:
					self._edit.cursor_hide()
					self._edit.insert_unicode_text(self.text, ul=True)
				self._edit.end_editing()
				
				self.edit_state = 1
				return True

			elif self.edit_state == 1:			# If the hangul automata is in progress
				hangul.AddHangulTable(self.key_exchange(key))
				ret_tmp = hangul.GetHangulTable()
				ret_obj = self.output_exchange(ret_tmp)
				ret_num = int(ret_obj[0])
				if config.hangul_debug:
					print '[hangul] edit_state = 1 / ret_num = ', ret_num
				# KA: [20070914] input max check
				if self._edit.full() and ret_num == 1:
					self.edit_state = 0	
					self.set_timer(False)
					return True
				# KA: [20070914] input max ==
				if ret_num == 0:				# Update the first data(han1) in current position. ex) '마'
					if ret_obj[1] != '\x00\x00':
						# KA: [20070823] delete ex) 삼육 ->삼유 ->삼ㅇ 
						self._edit.func_key_handler([('\b', 1)])
						self.text = utils.f_unicode_encoding(ret_obj[1])
						self._edit.start_editing()
						if self.text:
							self._edit.cursor_hide()
							self._edit.insert_unicode_text(self.text, ul=True)
						self._edit.end_editing()
						return True
					else:		
						self._edit.func_key_handler([('\b', 1)])
						# KA: [20070823] editing중이던 글자의 마지막 자음마저 삭제시에 이곳을 탄다. ex) 삼ㅇ -> 삼 
						self.edit_state = 0
						return True
						
				elif ret_num == -1: 			#Delete a data of current position and Update the first data(han1) in previous position. ex) '많'
						self._edit.func_key_handler([('\b', 1)])
						self._edit.func_key_handler([('\b', 1)])						
						self.text = utils.f_unicode_encoding(ret_obj[1])
 						if self.text:
							self._edit.cursor_hide()
							self._edit.insert_unicode_text(self.text, ul=True)
						# KA: [20070917] 많 + ㅏ ->  만하 
						#self._edit.end_editing()						
						#self.edit_state = 0				
						return True					
				elif ret_num == 1 :			#Update the first data(han1) in current position and the second data(han2) in next position. ex) '마ㄴ'
							
						if ret_obj[1] == '\x00\x00' or ret_obj[2] == '\x00\x00':
							self.edit_state = 0
							return True

						self._edit.func_key_handler([('\b', 1)])
						self.text = utils.f_unicode_encoding(ret_obj[1])
						self._edit.start_editing()
						if config.hangul_debug:
	 						print '[hangul] ret_obj[1]=', ret_obj[1]
	 						print '[hangul] ret_obj[2]=', ret_obj[2]
 						
						if self.text:
							self._edit.cursor_hide()
							self._edit.insert_unicode_text(self.text, ul=True)
						self._edit.end_editing()

						self._edit.cursor_forward()
						self._edit.t9_helper_ul_reset()
						self._edit.cursor_show()

						self.text = utils.f_unicode_encoding(ret_obj[2])
						self._edit.start_editing()
 
						if self.text:
							self._edit.cursor_hide()
							self._edit.insert_unicode_text(self.text, ul=True)
						self._edit.end_editing()

						return True

		else:
			 #ka...hangul 2007.01.26 Green/Red/Back...key 동작을 위해
			return False 
			
		return True
# KA: [20070813] hangul ==


class AddWordAutomata(Automata):
	def handle_key(self, key):
		if key in ('0', '1', '*', '#', 'Space'):
			return True

		if AutomataBase.handle_key(self, key):
			return True

		ctrl_keys = []
		text = unicode('')

		if key == 'Right':
			self._last_ch = ''
			self.set_timer(False)
			self._edit.cursor_forward()
			self._edit.t9_helper_ul_reset()
			self._edit.cursor_show()
			return True

		if key in ('\b', 'Left', 'Up', 'Down','Home','End'):
			self.reset()
			self._edit.func_key_handler([(key, 1)])
			return True

		if not key in self.table:
			return False

		if self._last_ch and self._last_ch in self.table[key]:
				ctrl_keys.append(('\b',1))
				last_key_idx = list(self.table[key]).index(self._last_ch)
				if last_key_idx == len(self.table[key]) - 1:
					key_idx = 0
				else:
					key_idx = last_key_idx + 1

				text = self.table[key][key_idx]
		else:
			self.reset()
			text = self.table[key][self.idx_table[key][self._mode]]

		self._last_ch = text
		self._mode = self.char_mode(text)
		self.set_timer(True)
		text = unicode(text, 'utf-8')

		if self._case_mode == UPPERCASE:
			text = text.upper()
		elif self._case_mode == LOWERCASE:
			text = text.lower()

		if ctrl_keys:
			self._edit.func_key_handler(ctrl_keys)
		if text:
			self._edit.cursor_hide()
			self._edit.insert_unicode_text(text, ul=True)

		return True

		
class NumericAutomata(AutomataBase):
	def __init__(self, edit):
		self._edit = edit
		self._timeout_tag = None

	def free(self):
		self._timeout_tag = None
		AutomataBase.free(self)

	def reset(self):
		self.set_timer(False)
		self._edit.t9_helper_ul_reset()
		self._edit.cursor_show()

	def set_timer(self, set):
		def timeout_cb():
			self._edit.t9_helper_ul_reset()
			self._edit.cursor_show()

			self._timeout_tag = None
			return False

		if set:
			self._timeout_tag = utils.Timer(1000, timeout_cb)
		else:
			self._timeout_tag = None

	def name(self):
		return '123'

	def handle_key(self, key):
		if AutomataBase.handle_key(self, key):
			return True

		if key == config.LongMenu2:
			self.reset()
			self._edit.set_text('')
			return True

		if key == config.CLEAR_LONG:
			self.reset()
			self._edit.set_text('')
			return True

		if key == 'Right':
			self.set_timer(False)
			# 숫자모드에서는 오른쪽 navigation key로 space 입력 안 됨.
			# 전화번호 입력시 space 들어가는 것 방지를 위해
			# 2008.08.18 통일성을 위해 다시 살리기로 함
			if self._edit.richtext:
				if self._edit.cursor_end_pos() and not self._edit.richtext.cursor_hidden:
					self._edit.insert_unicode_text(unicode(' ', 'utf-8'), ul=True)
			# =============================
			self._edit.cursor_forward()
			self._edit.t9_helper_ul_reset()
			self._edit.cursor_show()
			return True

		if key in ('Left', 'Up', 'Down','Home','End','\b'):
			self.reset()
			self._edit.func_key_handler([(key,1)])
			return True

		if len(key) == 1:
			import status
			if status.password_style:
				self._edit.t9_helper_ul_reset()
				self._timeout_tag = None
				self.set_timer(True)
				self._edit.cursor_hide()
				self._edit.insert_unicode_text(unicode(key, 'utf-8'), True)
			else:
				self._edit.insert_unicode_text(unicode(key, 'utf-8'))
			return True

		return False

class IPAddrAutomata(NumericAutomata):
# shchun : for ip address input.
#		- input '.' for '*' key
	def handle_key(self, key):
		print '### IPAddrAutomata key=', key
		if key == '*':
			self._edit.insert_unicode_text(unicode('.', 'utf-8'))
			return True
					
		elif key == 'CLR':	
			if len(self._edit.get_text()) > 0:
				self._edit.backspace(1)
			return True	
		elif key == config.LongMenu2:
			self.reset()
			self._edit.set_text('')
			return True
			
		if NumericAutomata.handle_key(self, key):
			return True
		return False

class T9Automata(AutomataBase):
	add_words = []
	def __init__(self, edit):
		from t9 import T9
		self._t9 = T9(32)
		self._last_buf = ''
		self._timeout_tag = None
		self._edit = edit
		self._add_word_mode = False
		self._case_mode = LOWERCASE
		self.ori_case_mode = LOWERCASE

		self._t9.set_lang(('spanish', 'english', 'italian','deutsch', 'france', 'turkish', 'norwegian')[setting.t9_language])

		if not self.add_words:
			try:
				for l in file(config.t9_word_list):
					l = l.strip()
					self.add_words.append(unicode(l, 'utf-8'))
			except IOError:
				pass

		for w in self.add_words:
			self._t9.add_word(w)

		self.reset()

	def free(self):
		self._t9.reset()
		self._timeout_tag = None
		del self._t9
		AutomataBase.free(self)

	def name(self):
		return 't9'

	def set_timer(self, set):
		return

	def set_case_mode(self, mode):
		if self._case_mode != mode:
			self._case_mode = mode
			self.reset()

	def ori_set_case_mode(self, case_mode):
		self.ori_case_mode = case_mode

	def case_mode(self):
		return self._case_mode

	def reset(self):
		self._t9.reset()
		self._last_buf = ''

		self._edit.t9_helper_ul_reset()
		self._edit.cursor_show()

		self._add_word_mode = False
		self._edit.set_ul_shape()

	def check_start_of_sentance(self):
		if self._edit.is_start_of_sentance():
			if self._case_mode == LOWERCASE and self.ori_case_mode == FIRSTCAPITAL:
				self.set_case_mode(FIRSTCAPITAL)
			return
		else:
			if self._case_mode == FIRSTCAPITAL:
				self.set_case_mode(LOWERCASE)

	def set_edit_t9buffer(self, text):
		if text == self._last_buf:
			return True

		ctrl_keys =  [('\b', len(self._last_buf))]

		self._last_buf = text

		if self._case_mode == UPPERCASE:
			text = text.upper()
		elif self._case_mode == LOWERCASE:
			text = text.lower()
		elif self._case_mode == FIRSTCAPITAL:
			text = text.lower()
			if text: text = text[0].upper() + text[1:]

		self._edit.start_editing()
		if ctrl_keys:
			self._edit.func_key_handler(ctrl_keys)

		if text:
			self._edit.cursor_hide()
			self._edit.insert_unicode_text(text, ul=True)
		self._edit.end_editing()

	def handle_key(self, key):
		if AutomataBase.handle_key(self, key):
			return True


		if key == config.LongMenu2:
			self.reset()
			self._edit.set_text('')
			return True

		self.set_timer(False)
		ctrl_keys = []
		text = unicode('')

		if self._add_word_mode:
			return False

		if key == 'Right':
			self._t9.reset()
			self._last_buf = ''
			ctrl_keys.append((key,1))
			self._edit.cursor_forward()
			self._edit.t9_helper_ul_reset()
			self._edit.cursor_show()
			self._add_word_mode = False
			self._edit.set_ul_shape()
			self.check_start_of_sentance()
			return True

		if key in ('Left', 'Up', 'Down'):
			self.reset()
			ctrl_keys.append((key,1))
			self._edit.func_key_handler(ctrl_keys)
			self.check_start_of_sentance()
			return True
		elif key == '\r':
			self.reset()
			self._edit.insert_unicode_text('\n', ul=False)
			return True
		elif key == '0':
			ctrl_keys.append(('Space',1))
			self.reset()
			self._edit.func_key_handler(ctrl_keys)
			self.check_start_of_sentance()
			return True
		else:
			if self._edit.full():
				if key not in ('\b'):
					return False

			if key == '\b':
				self.set_timer(True)
				if self._last_buf:
					self._t9.backspace()
				else:
					self._edit.func_key_handler([(key, 1)])
					self.check_start_of_sentance()
					return True

			elif len(key) == 1:
				self.set_timer(True)
				self._t9.handle_key(key)
			else:
				return False

			text = self._t9.get_buf()
			self.set_edit_t9buffer(text)
			return True

	def handle_next(self):
		self.set_timer(True)
		if not self._add_word_mode:
			self._t9.next()
			if self._t9.get_objnum() == 1:
				self._add_word_mode = True
				self._edit.set_ul_shape('rectangle')
				ctrl_keys =  [('\b', len(self._last_buf))]
				self._edit.cursor_hide()
				if setting.lang == 'Spain':
					add_word_text = 'A\xc3\xb1adir palabra'
				else:
					add_word_text = 'Add word'

				self._last_buf = unicode(add_word_text)
				self._edit.start_editing()
				self._edit.func_key_handler(ctrl_keys)
				self._edit.insert_unicode_text(self._last_buf, ul=True)
				self._edit.end_editing()
				return True

		self._edit.set_ul_shape()
		self._add_word_mode = False

		text = self._t9.get_buf()
		self.set_edit_t9buffer(text)
		return True

	def handle_previous(self):
		self.set_timer(True)
		self._t9.prev()

		self._add_word_mode = False
		self._edit.set_ul_shape()
		self._edit.cursor_hide()

		text = self._t9.get_buf()
		self.set_edit_t9buffer(text)

		if self._t9.get_objnum() == 1:
			return False
		else:
			return True

	def get_t9_objnum(self):
		if self._add_word_mode:
			return 0
		return self._t9.get_objnum()

	def is_add_word_mode(self):
		return self._add_word_mode

	def is_edit_buffer_empty(self):
		if self._last_buf:
			return False
		return True

	def t9_add_word(self, word):
		if not word:
			return

		try:
			if utils.get_file_size(config.t9_word_list) > config.t9_word_list_max:
				import basemodel
				raise basemodel.StorageFullError, 't9 storage full'
		except OSError:
			pass

		w = unicode(word, 'utf-8')
		self._t9.add_word(w);
		self._add_word_mode = False
		self._edit.set_ul_shape()
		self._edit.func_key_handler([('\b', len(self._last_buf))])

		if self._case_mode == UPPERCASE:
			w = w.upper()
		elif self._case_mode == LOWERCASE:
			w = w.lower()
		elif self._case_mode == FIRSTCAPITAL:
			w = w.lower()
			w = w[0].upper() + w[1:]

		self._edit.insert_unicode_text(w)
		self.reset()

		if not w.lower() in self.add_words:
			self.add_words.append(w.lower())

			try:
				for l in file(config.t9_word_list):
					l = l.strip()
					if l == word:
						return
			except IOError:
				pass

			open(config.t9_word_list, 'a+').write(w.lower().encode('utf-8') + '\n')