#!/usr/bin/env python3
# -*- coding: utf-8 -*-


"""OCRdesktop"""

__version__   = "2.0"
__copyright__ = "Copyright (c) 2015 Chrys"
__license__   = "GPL"
__authors__   = ["chrys"]
__website__   = "https://github.com/chrys87/ocrdesktop"
__appname__   = "OCRdesktop"
__comments__  = "A accessibility tool for woring with inaccessible windows and dialogs"

#Python Utils
import os, sys, getopt, locale, time, re, _thread, shutil

#PIL
from PIL import Image
from PIL import ImageOps

#tesseract
from tesserwrap import Tesseract

#gi
import gi

#GTK/GDK/Wnck/GObject
gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0")
gi.require_version("Wnck", "3.0")
from gi.repository import Gtk, Gdk, GObject, Wnck


# AT-SPI
gi.require_version('Atspi', '2.0')
import pyatspi



# here the class
class OCRNavigation(Gtk.Window):
	def __init__(self, debug_p = False):
		self._debug = debug_p
		self._tree = None
		self._textbox = None
		self._textbuffer = None
		self._saveToMacroButton = None
		self._viewButton = None
		self._viewMode = 0
		self._keyboardOverlayActive = False
		self._screenShotMode = 0 # 0 = Window; 1 = Desktop
		self._sendToClipboard = False
		self._hideGui = False
		self._saveToMacro = False
		self._scrolledWindowTree = None
		self._scrolledWindowText = None
		self._keyboardOverlayLabel = None
		self._grid = None
		self._menubar = None
		self._font_button = None
		self._accelerators = None
		self._OCRWords = None		
		self._OCRWordList = []
		self._OCRText = ''
		self._img = None
		self._modifiedImg = None
		self._grayscaleImg = False
		self._invertImg = False
		self._blackWhiteImg = False
		self._printToStdOut = False
		self._blackWhiteImgValue = 200
		self._scaleFactor = 3
		self._offsetXpos = 0
		self._offsetYpos = 0
		self.GTKmainIsRunning = False
		locale.setlocale(locale.LC_ALL, 'C') #needed by tesseract in non english languages 
		self._macro = OCRMacroManager()
		self._languageCode = 'eng'
		self._tess = None
		self._isRefreshing = False
	def _setHideGui(self, hideGui_p = False):
		self.hideGui = hideGui_p

	def _setlanguageCode(self, languageCode_p = 'eng'):
		self._languageCode = languageCode_p
		
	def _setGrayscaleImg(self, grayscaleImg_p = False):
		self._grayscaleImg = grayscaleImg_p

	def _setInvertImg(self, invertImg_p = False):
		self._invertImg = invertImg_p

	def _setBlackWhiteImg(self, blackWhiteImg_p = False):
		self._blackWhiteImg = blackWhiteImg_p

	def _setBlackWhiteImgValue(self, blackWhiteImgValue_p = 200):
		self._blackWhiteImgValue = blackWhiteImgValue_p

	def _setPrintToStdOut(self, printToStdOut_p = False):
		self._printToStdOut = printToStdOut_p

	def _setSendToClipboard(self, sendToClipboard_p = False):
		self._sendToClipboard = sendToClipboard_p
	
	def _setScreenShotMode(self, screenShotMode_p):
		self._screenShotMode = screenShotMode_p

	def _setMacro(self, macro_p):
		self._macro = macro_p
		
	def _screenShotDesktop(self):
		CurrDesktop = Gdk.get_default_root_window()	
		pixBuff = Gdk.pixbuf_get_from_window(CurrDesktop, 0, 0, CurrDesktop.get_width(), CurrDesktop.get_height())
		if (pixBuff != None):
			self._img = self.pixbuf2image(pixBuff)
			if self._debug: # Debug code
				self._img.save("/tmp/ocrScreenshot.png") 
				print("save screenshot:/tmp/ocrScreenshot.png") 
			self._scaleImg()
			return True
		else:
			if self._debug: # Debug code
				print("Could not take screenshot") 
			return False

	def _screenShotWindow(self): #Mode=0 Desktop Mode=1 CurrWindow
		Gtk.main_iteration_do(False) # workarround segfault
		gdkCurrDesktop = Gdk.get_default_root_window()
		#currWindow = Gdk.gdk_screen_get_active_window(Gdk.gdk_screen_get_default())
		#pixBuff = Gdk.pixbuf_get_from_window(currWindow, 0, 0, currWindow.get_width(), currWindow.get_height())
		try:
			currWnckScreen = Wnck.Screen.get_default()
			currWnckScreen.force_update()
			currWnckWindow = currWnckScreen.get_active_window()
			self._offsetXpos, self._offsetYpos, wnckWidth, wnckHeight = Wnck.Window.get_geometry(currWnckWindow)
			pixBuff = Gdk.pixbuf_get_from_window(gdkCurrDesktop, self._offsetXpos, self._offsetYpos , wnckWidth, wnckHeight)
		except:
			return False

		if self._debug:
			pixBuff.savev('/tmp/ocrpixBuff.bmp', 'bmp', [], []) # Debug code
			print("save pixBuff /tmp/ocrpixBuff.bmp")
		if (pixBuff != None):
			self._img = self.pixbuf2image(pixBuff)
			if self._debug: # Debug code
				self._img.save("/tmp/ocrScreenshot.png") 
				print("save screenshot:/tmp/ocrScreenshot.png") 
			self._scaleImg()
			return True
		else:
			if self._debug: # Debug code
				print("Could not take screenshot") 
			return False

	def pixbuf2image(self, pix):
		"""Convert gdkpixbuf to PIL image"""
		data = pix.get_pixels()
		w = pix.props.width
		h = pix.props.height
		stride = pix.props.rowstride
		mode = "RGB"
		if pix.props.has_alpha == True:
			mode = "RGBA"
		im = Image.frombytes(mode, (w, h), data, "raw", mode, stride)
		return im

	def _scaleImg(self):
		width_screen, height_screen = self._img.size
		width_screen = width_screen * self._scaleFactor
		height_screen = height_screen * self._scaleFactor
		self._img = self._img.resize( (width_screen, height_screen), Image.BICUBIC)
		if self._debug: # Debug code
			self._img.save("/tmp/ocrScreenshotScaled.png")
			print("save scaled screenshot:/tmp/ocrScreenshotScaled.png")


	def _screenShot(self):
		Ok = False
		time.sleep(0.3)
		if self._screenShotMode == 0:
			try: #take care that we get a screenshot
				Ok = self._screenShotWindow()
				if not Ok:
					if self._debug:
						print('FALLBACK: was not able to Screenshot active window. Try Rootwindow now')
					Ok = self._screenShotDesktop()
			except:
				if self._debug:
						print('FALLBACK: was not able to Screenshot active window. Try Rootwindow now')
				Ok = self._screenShotDesktop()		

		elif self._screenShotMode == 1:
			Ok = self._screenShotDesktop()		
		return Ok
				
	def _ocrImage(self):
		if self._modifiedImg is None:
			return False
		if os.path.exists("/usr/share/tesseract-ocr/4.00/tessdata/"):
		    tesseractData = "/usr/share/tesseract-ocr/4.00/tessdata/"		
		elif os.path.exists("/usr/share/tesseract-ocr/tessdata/"):
		    tesseractData = "/usr/share/tesseract-ocr/tessdata/"
		elif os.path.exists("/usr/share/tesseract/tessdata/"):
		    tesseractData = "/usr/share/tesseract/tessdata/"
		elif os.path.exists("/usr/share/tessdata/"):
		    tesseractData = "/usr/share/tessdata/"		
		else:
		    tesseractData = "/usr/share/"

		self._tess = Tesseract(tesseractData, self._languageCode)
		
		self._OCRText = self._tess.ocr_image(self._modifiedImg)
		regexSpace = re.compile('[^\S\r\n]{2,}') #remove double spaces
		self._OCRText = regexSpace.sub(' ',self._OCRText)
		regexSpace = re.compile('\n\s*\n') #remove empty lines
		self._OCRText = regexSpace.sub('\n',self._OCRText)
		regexSpace = re.compile('\s*\n') #remove ending spaces
		self._OCRText = regexSpace.sub('\n',self._OCRText)
		regexSpace = re.compile('\n\s') #remove trailing spaces
		self._OCRText = regexSpace.sub( '\n', self._OCRText)
		regexSpace = re.compile('^\s') #remove trailing space in first line
		self._OCRText = regexSpace.sub( '\n', self._OCRText)
		regexSpace = re.compile('$\n') #remove ending newline
		self._OCRText = regexSpace.sub( '', self._OCRText)
		if self._sendToClipboard:
			self._setTextToClipboard( self._OCRText)
		if self._printToStdOut:
			print(self._OCRText)
		if not self._hideGui:
			self._OCRWords = self._tess.get_words()
			self._fillOCRWordlist()
		return True

	def _fillOCRWordlist(self):
		for OCRWord in self._OCRWords: # fill the list
			if int(OCRWord.confidence) != 0:
				self._OCRWordList.append([OCRWord.value.decode("utf-8"),
				  round((OCRWord.box[3] - OCRWord.box[1]) / 3 * 0.78,0),
				  'unknown',
				  'text',
				  int((OCRWord.box[2] - OCRWord.box[0]) / 2 + OCRWord.box[0]),
				  int((OCRWord.box[3] - OCRWord.box[1]) / 2 + OCRWord.box[1]),
				  int(OCRWord.confidence)])

	def add_accelerator(self, widget, accelerator, signal="activate"):
		"""Adds a keyboard shortcut"""
		if accelerator is not None:
			key, mod = Gtk.accelerator_parse(accelerator)
			widget.add_accelerator(signal, self._accelerators, key, mod, Gtk.AccelFlags.VISIBLE)

	def on_font_set(self, widget):
		font_description = widget.get_font_desc()
		self._textbox.modify_font(font_description)
		
	def _onRefreshContent(self, widget):
		self._refreshContent()
	
	def _transformImg(self):
		self._modifiedImg = self._img
		if self._invertImg:
			self._modifiedImg = ImageOps.invert(self._modifiedImg)
		if self._grayscaleImg:
			self._modifiedImg = ImageOps.grayscale(self._modifiedImg)
		if self._blackWhiteImg:
			lut = [255 if v > self._blackWhiteImgValue else 0 for v in range(256)]
			self._modifiedImg = self._modifiedImg.point(lut)
		if self._debug: # Debug code
			self._modifiedImg.save("/tmp/ocrScreenshotTransformed.png")
			print("save scaled screenshot:/tmp/ocrScreenshotTransformed.png")			
		
	def _refreshContent(self):
		if self._isRefreshing == True:
			print("refresh already running")
			return
		self._isRefreshing = True
		if self._debug:
			print("refresh")
		self._tree = None
		self._OCRWords = None		
		self._OCRWordList = []
		self._OCRText = ''
		self._scrolledWindowTree = None
		self._scrolledWindowText = None
		self._textbox = None
		self._transformImg()
		self._ocrImage()

		self._scrolledWindowText = Gtk.ScrolledWindow()

		self._textbox = Gtk.TextView()
		self._textbox.set_hexpand(True)
		self._textbox.set_vexpand(True)
		self._textbox.show()
		self._textbuffer = self._textbox.get_buffer()
		self._textbuffer.set_text(self._OCRText)
		self._textbox.set_editable(False)
		if not self._textbuffer.get_start_iter() is None:
			self._textbuffer.place_cursor(self._textbuffer.get_start_iter())
		self._scrolledWindowText.add(self._textbox)
		
		self._scrolledWindowTree = Gtk.ScrolledWindow()
		self._tree = Gtk.TreeView()
		self._tree.set_hexpand(True)
		self._tree.set_vexpand(True)
		self._tree.show()
		self._scrolledWindowTree.add(self._tree)

		cols = [GObject.TYPE_STRING]
		cols.extend([GObject.TYPE_STRING])
		cols.extend([GObject.TYPE_INT])	
		cols.extend([GObject.TYPE_STRING])
		cols.extend([GObject.TYPE_STRING])
		cols.extend([GObject.TYPE_INT])		
		cols.extend([GObject.TYPE_INT])
		cols.extend([GObject.TYPE_INT])
		model = Gtk.ListStore(*cols)
		self._tree.set_model(model)
		columnHeaders = ['OCR Text','Fontsize','Color','Object','X Position','Y Position','Confidence']
		
		cell = Gtk.CellRendererText()
		column = Gtk.TreeViewColumn("OCR Text", cell, text=0)
		column.set_visible(False)
		self._tree.append_column(column)

		for i, header in enumerate(columnHeaders):
			cell = Gtk.CellRendererText()
			column = Gtk.TreeViewColumn(header, cell, text=i+1)
			#column.set_sort_column_id(i+1)
			self._tree.append_column(column)

		model = self._tree.get_model()
		for row in self._OCRWordList:
			rowIter = model.append(None)
			i = 0
			for cell in row:
				i = i + 1
				if i == 5:
					cell = cell / self._scaleFactor + self._offsetXpos
				if i == 6:
					cell = cell / self._scaleFactor + self._offsetYpos
#				if i == 1:
				model.set_value(rowIter, i, cell)
#					i = i + 1
#					cell = 12
#					model.set_value(rowIter, i, cell)
#					i = i + 1
#					cell = 'black'
#					model.set_value(rowIter, i, cell)
#				else:
#					model.set_value(rowIter, i, cell)

		self._tree.set_search_column(1)
		self._grid.attach(self._scrolledWindowTree, 0, 1, 10, 10)
		self._grid.attach(self._scrolledWindowText, 0, 1, 10, 10)
		self._setView(False)
		self._isRefreshing = False
		
	def _onSendKey(self, event):
		eventTypeID = 0
		
		if self._debug:
			print("_onSendKey")
			print('Type:' + str(event.type))
			print('String: ' + event.event_string)
			print('ID: ' + str(event.id))
			print('hw_code: ' + str(event.hw_code))

		if event.type == pyatspi.Atspi.EventType.KEY_PRESSED_EVENT:
			if event.event_string =='F4':
				self._keyboardOverlayActive = False
				self._setView(False)
				pyatspi.Registry.deregisterKeystrokeListener(self._onSendKey)
				if self._debug:
					print('deregisterKeystrokeListener')
				return True
			eventTypeID = 0
			
		elif event.type == pyatspi.Atspi.EventType.KEY_RELEASED_EVENT:
			eventTypeID = 1

		self._macro._writeKeyboardToMacro(0, event.event_string, eventTypeID)
		return True
		
	def _sendKeyMode(self, widget):
		self._keyboardOverlayActive = True
		if self._debug:
			print("sendKeyMode")
		pyatspi.Registry.registerKeystrokeListener(self._onSendKey,mask=pyatspi.allModifiers(), kind=(pyatspi.KEY_PRESS,pyatspi.KEY_RELEASE,pyatspi.KEY_PRESSRELEASE), synchronous=True, preemptive=True)
		self._setView(False)
		if self._debug:
			print("Keyboardlistener is registered")

	def _toggleGrayscaleImg(self, widget):
		self._grayscaleImg = widget.get_active()
		if not self._grayscaleImg:
			self.item_barrierbw.set_active(False)

	def _toggleInvertImg(self, widget):
		self._invertImg = widget.get_active()

	def _toggleBlackWhiteImg(self, widget):
		self._blackWhiteImg = widget.get_active()
		if self._blackWhiteImg:
			self.item_grayscale.set_active(True)

	def _createNavListDialog(self):
		Gtk.Window.__init__(self, title="OCR")
		self.set_default_size(700,800)
		self._grid = Gtk.Grid()
	
		self._accelerators = Gtk.AccelGroup()

		self._menubar = Gtk.MenuBar()

		self.menu_ocrdesktop = Gtk.Menu()
		self.item_toggleview = Gtk.MenuItem("Toggle _View")
		self.item_toggleview.set_use_underline(True)
		self.add_accelerator(self.item_toggleview, "<Control>v","activate")
		self.item_ocroptions = Gtk.MenuItem("_OCR Options")
		self.item_ocroptions.set_use_underline(True)
		self.option_sub_menu = Gtk.Menu()
		self.item_ocroptions.set_submenu(self.option_sub_menu)
		self.item_invert = Gtk.CheckMenuItem("_Invert")
		self.item_invert.set_use_underline(True)
		self.item_grayscale = Gtk.CheckMenuItem("_Grayscale")
		self.item_grayscale.set_use_underline(True)
		self.item_barrierbw = Gtk.CheckMenuItem("_Barrier Black White")
		self.item_barrierbw.set_use_underline(True)
		self.option_sub_menu.append(self.item_invert)
		self.option_sub_menu.append(self.item_grayscale)
		self.option_sub_menu.append(self.item_barrierbw)
		self.item_invert.set_active(self._invertImg)
		self.item_grayscale.set_active(self._grayscaleImg)
		self.item_barrierbw.set_active(self._blackWhiteImg)
		self.item_invert.connect("activate", self._toggleInvertImg)
		self.item_grayscale.connect("activate", self._toggleGrayscaleImg)
		self.item_barrierbw.connect("activate", self._toggleBlackWhiteImg)
		
		self.item_retry = Gtk.MenuItem("_Retry OCR")
		self.item_retry.set_use_underline(True)
		self.add_accelerator(self.item_retry, "F5","activate")
		self.item_clipboard = Gtk.MenuItem("Send to _Clipboard")
		self.item_clipboard.set_use_underline(True)
		self.add_accelerator(self.item_clipboard, "<Control>b","activate")
		self.item_font = Gtk.MenuItem("_Font")
		self.item_font.set_use_underline(True)
		self.item_close = Gtk.MenuItem("_Close")
		self.add_accelerator(self.item_close, "<Control>q","activate")
		self.item_close.set_use_underline(True)
		self.menu_ocrdesktop.append(self.item_toggleview)
		self.menu_ocrdesktop.append(self.item_ocroptions)
		self.menu_ocrdesktop.append(self.item_retry)
		self.menu_ocrdesktop.append(self.item_clipboard)
		#self.menu_ocrdesktop.append(self.item_font)
		self.menu_ocrdesktop.append(self.item_close)
		self.item_toggleview.connect("activate", self._onSetView,True)
		self.item_retry.connect("activate", self._onRefreshContent)
		self.item_clipboard.connect("activate", self._onSetTextToClipboard)
		self.item_close.connect("activate", Gtk.main_quit)
		
		self.menu_interact = Gtk.Menu()
		self.item_preclick = Gtk.CheckMenuItem("_Preclick")
		self.item_preclick.set_use_underline(True)
		self.add_accelerator(self.item_preclick, "<Control>p","activate")
		self.item_leftclick = Gtk.MenuItem("_Left Click")
		self.item_leftclick.set_use_underline(True)
		self.add_accelerator(self.item_leftclick, "<Control>l","activate")
		self.item_doubletclick = Gtk.MenuItem("_Double Click")
		self.item_doubletclick.set_use_underline(True)
		self.add_accelerator(self.item_doubletclick, "<Control>d","activate")
		self.item_rightclick = Gtk.MenuItem("_Right Click")
		self.item_rightclick.set_use_underline(True)
		self.add_accelerator(self.item_rightclick, "<Control>r","activate")
		self.item_middleclick = Gtk.MenuItem("_Middle Click")
		self.item_middleclick.set_use_underline(True)
		self.add_accelerator(self.item_middleclick, "<Control>m","activate")
		self.item_routeto = Gtk.MenuItem("Route _To")
		self.item_routeto.set_use_underline(True)
		self.add_accelerator(self.item_routeto, "<Control>t","activate")
		self.item_sendkey = Gtk.MenuItem("Send _Key")
		self.item_sendkey.set_use_underline(True)
		self.add_accelerator(self.item_sendkey, "<Control>k","activate")
		self.menu_interact.append(self.item_preclick)
		self.menu_interact.append(self.item_leftclick)
		self.menu_interact.append(self.item_doubletclick)
		self.menu_interact.append(self.item_rightclick)
		self.menu_interact.append(self.item_middleclick)
		self.menu_interact.append(self.item_routeto)
		self.menu_interact.append(self.item_sendkey)
		self.item_preclick.connect("activate", self._setSaveToMacro)
		self.item_leftclick.connect("activate", self._onLeftClick)
		self.item_doubletclick.connect("activate", self._onDoubleLeftClick)
		self.item_rightclick.connect("activate", self._onRightClick)
		self.item_middleclick.connect("activate", self._onMiddleClick)
		self.item_routeto.connect("activate", self._routeToPoint)
		self.item_sendkey.connect("activate", self._sendKeyMode)
		
		self.menu_macro = Gtk.Menu()
		self.item_save = Gtk.MenuItem("_Save As")
		self.item_save.set_use_underline(True)
		self.add_accelerator(self.item_save, "<Control>s","activate")
		self.item_load = Gtk.MenuItem("_Load")
		self.item_load.set_use_underline(True)
		self.add_accelerator(self.item_load, "<Control>o","activate")
		self.item_delete = Gtk.MenuItem("_Unload")
		self.item_delete.set_use_underline(True)
		self.add_accelerator(self.item_delete, "<Control>u","activate")
		self.item_run = Gtk.MenuItem("_Run")
		self.item_run.set_use_underline(True)
		self.add_accelerator(self.item_run, "<Control>n","activate")
		self.menu_macro.append(self.item_save)
		self.menu_macro.append(self.item_load)
		self.menu_macro.append(self.item_delete)
		self.menu_macro.append(self.item_run)
		self.item_save.connect("activate", self._macro._saveMacro, self)
		self.item_load.connect("activate", self._macro._onLoadMacro, self)
		self.item_delete.connect("activate", self._macro._onDeleteMacro, False)
		self.item_run.connect("activate", self._onRunMacro)
		
		self.menu_help = Gtk.Menu()
		self.item_about = Gtk.MenuItem("_About")
		self.item_about.set_use_underline(True)	
		self.menu_help.append(self.item_about)
		self.item_about.connect("activate", self._onRunAboutDialog, self)

		self.item_ocrdesktop = Gtk.MenuItem("_OCRDesktop")
		self.item_ocrdesktop.set_use_underline(True)
		self.item_interact = Gtk.MenuItem("_Interact")
		self.item_interact.set_use_underline(True)
		self.item_macro = Gtk.MenuItem("_Macro")
		self.item_macro.set_use_underline(True)
		self.item_help = Gtk.MenuItem("_Help")
		self.item_help.set_use_underline(True)

		self.item_ocrdesktop.set_submenu(self.menu_ocrdesktop)
		self.item_interact.set_submenu(self.menu_interact)
		self.item_macro.set_submenu(self.menu_macro)
		self.item_help.set_submenu(self.menu_help)
		self._menubar.append(self.item_ocrdesktop)
		self._menubar.append(self.item_interact)
		self._menubar.append(self.item_macro)
		self._menubar.append(self.item_help)
		self.add_accel_group(self._accelerators)
		
		self._keyboardOverlayLabel = Gtk.Label("Please insert keyboard commands. exit with: F4")
		self._keyboardOverlayLabel.set_selectable(True)

		self._font_button = Gtk.FontButton()
		self._font_button.connect('font-set', self.on_font_set)
		
		self._refreshContent()

		self.connect("delete-event", Gtk.main_quit)
		self.connect('key-release-event', self._onKeyRelease)
		#self._textbuffer.connect("notify::cursor-position", self._onCursorTextPositionChanged)
		#self._tree.connect("notify::cursor-position", self._onCursorTreePositionChanged)
		

		self._grid.attach(self._menubar,0,0,10,1)
		self._grid.attach(self._keyboardOverlayLabel, 0, 1, 10, 1)
		self._grid.attach(self._font_button, 0, 11, 3, 1)
		self.add(self._grid)

	def _onCursorTextPositionChanged(self, widget, event):
		#print(widget.props.cursor_position)
		#position = widget.get_iter_at_offset(widget.props.cursor_position)
		#if not widget.get_start_iter() is None:
		#	print(widget.get_text(widget.get_start_iter(),position,False).count('\n')+widget.get_text(widget.get_start_iter(),position,True).count(' '))
#TODO set the pos correct		
	#wtf is thist not working		self._tree.set_cursor(widget.get_text(widget.get_start_iter(),position,True).count('\n')+widget.get_text(widget.get_start_iter(),position,True).count(' '))
		pass

	def _onCursorTreePositionChanged(self, widget, event):
#TODO set the pos correct
		#print(widget.props.cursor_position)
		#position = widget.get_iter_at_offset(widget.props.cursor_position)
		#if not widget.get_start_iter() is None:
		#	print(widget.get_text(widget.get_start_iter(),position,False).count('\n')+widget.get_text(widget.get_start_iter(),position,True).count(' '))
		#	self._tree.set_cursor(widget.get_text(widget.get_start_iter(),position,True).count('\n')+widget.get_text(widget.get_start_iter(),position,True).count(' '))
		pass

	def _setSaveToMacro(self, widget):
		self._saveToMacro = widget.get_active()

	def setFocus(self):
		if self._viewMode == 0:		
			position = self._textbuffer.get_iter_at_offset(self._textbuffer.props.cursor_position)
			if not self._textbuffer.get_start_iter() is None:
				self._tree.set_cursor(self._textbuffer.get_text(self._textbuffer.get_start_iter(),position,True).count('\n')+self._textbuffer.get_text(self._textbuffer.get_start_iter(),position,True).count(' '))

	def showGUI(self):
		self._gui = self._createNavListDialog()
		self.set_modal(True)
		self.show_all()
		self._setView(False)
		self.startMain()
		
	def startMain(self):
		self.GTKmainIsRunning = True
		Gtk.main()

	def _onRunAboutDialog(self,widget,window):
		dialog = Gtk.AboutDialog(window)
		dialog.set_authors(__authors__)
		dialog.set_website(__website__)
		dialog.set_copyright(__copyright__)
		dialog.set_license(__license__)
		dialog.set_version(__version__)
		dialog.set_program_name(__appname__)
		dialog.set_comments(__comments__)
		dialog.run()
		dialog.destroy()
		
	def _onSetView(self, widget, Toggle=True):
		self._setView(Toggle)
			
	def _setView(self, Toggle):
		
		self._scrolledWindowTree.hide()	
		self._scrolledWindowText.hide()	
		self._keyboardOverlayLabel.hide()
		
		if self._keyboardOverlayActive:
			self._keyboardOverlayLabel.show()
			return

		self.setFocus()
			
		if Toggle:
			if self._viewMode == 0:
				self._viewMode = 1
			elif self._viewMode == 1:
				self._viewMode = 0
		
		if self._viewMode == 1:	
			self._scrolledWindowTree.show()
			self._tree.grab_focus()
		elif self._viewMode == 0:
			self._scrolledWindowText.show()
			self._textbox.grab_focus()


	def _onKeyRelease(self, widget, event):
		keycode = event.hardware_keycode
		keymap = Gdk.Keymap.get_default()
		entries_for_keycode = keymap.get_entries_for_keycode(keycode)
		entries = entries_for_keycode[-1]
		eventString = Gdk.keyval_name(entries[0])
#		if self._debug:
#			print(eventString)
#		if eventString == 'Escape':
#			Gtk.main_quit()
#		if eventString == 'Return':
#			self._leftClickButton.grab_focus()

	def _cancel(self):
		if self.GTKmainIsRunning:
			Gtk.main_quit()
			GTKmainIsRunning = False

	def _routeToPoint(self, widget):
		self.setFocus()
		self.hide()
		xpos, ypos = self._getSelectedEntry()
		_thread.start_new_thread( self._threadrouteToPoint, (xpos,ypos, ) )

	def _onRightClick(self, widget):
		self.setFocus()
		xpos, ypos = self._getSelectedEntry()
		self.hide()
		_thread.start_new_thread( self._threadDoClick, (xpos,ypos,"b3c", ) )	

	def _onLeftClick(self, widget):
		self.setFocus()
		xpos, ypos = self._getSelectedEntry()
		self.hide()
		_thread.start_new_thread( self._threadDoClick, (xpos,ypos, "b1c", ) )		

	def _onDoubleLeftClick(self, widget):
		self.setFocus()
		xpos, ypos = self._getSelectedEntry()
		self.hide()
		_thread.start_new_thread( self._threadDoClick, (xpos,ypos,"b1d", ) )	

	def _onMiddleClick(self, widget):
		self.setFocus()
		xpos, ypos = self._getSelectedEntry()
		self.hide()
		_thread.start_new_thread( self._threadDoClick, (xpos,ypos,"b2c", ) )	

	def _threadrouteToPoint(self, xpos=1,ypos=1,delay=0.8, posRelation = "abs"):
		if self._saveToMacro:
			self._macro._writeMouseToMacro(xpos,ypos,'None')
		else:
			time.sleep(delay)
			pyatspi.Registry.generateMouseEvent(xpos,ypos,posRelation)
		self._cancel()
		
	def _onRunMacro(self, widget):
		if self._macro._macroExists():
			self.hide()
			_thread.start_new_thread( self._threadRunMacro, () )
		else:
			dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO,
				Gtk.ButtonsType.OK, "No Macro loaded")
			dialog.format_secondary_text(
				"You have to load a macro for execution.")
			dialog.run()
			dialog.destroy()	

	def _threadRunMacro(self):
		self._macro._threadRunMacro()	
		self._cancel()

	def _threadDoClick(self, xpos=1,ypos=1,mouseEvent='b1c',delay=0.8):
		if self._saveToMacro:
			self._macro._writeMouseToMacro(xpos,ypos,mouseEvent)
		else:
			time.sleep(delay)
			pyatspi.Registry.generateMouseEvent(xpos,ypos, mouseEvent)
		self._cancel()

	def _onSetTextToClipboard(self, widget):
		self._setTextToClipboard(self._OCRText)

	def _setTextToClipboard(self, text_p):
		if self._debug:
			print("----_setTextToClipboard Start--")
			print(text_p)
			print("----_setTextToClipboard End----")
			
		ClipboardObj = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
		ClipboardObj.set_text(text_p, -1)
		ClipboardObj.store()

	def _getSelectedEntry(self):
		if not self._tree:
			return None

		selection = self._tree.get_selection()
		if not selection:
			return None

		model, paths = selection.get_selected_rows()
		if not paths:
			return None

		return model.get_value(model.get_iter(paths[0]), 5),model.get_value(model.get_iter(paths[0]), 6)

class OCRScreenReader():
	def __init__(self):
		self._sendToClipboard = False
		self._hideGui = False
		self._screenShotMode = 0 # 0 = Window; 1 = Desktop
		self._macroFile = os.path.expanduser('~') + '/.activeOCRMacro.ocrm'
		self._showHelp = False
		self._debug = False
		self._languageCode = 'eng'
		self._grayscaleImg = False
		self._invertImg = False
		self._blackWhiteImg = False
		self._blackWhiteImgValue = 200
		self._printToStdOut = False
		self._setCommandLineOptions()

		if self._showHelp:
			return

		#MACRO
		self._macro = OCRMacroManager(self._debug)
		self._macro._loadMcroFile(self._macroFile)
		if not self._hideGui:
			self._macro.showGUI()
		else:
			if self._macro._macroExists():
				self._macro._RunMacro()

		#NAVIGATION
		self._Navigation = OCRNavigation(self._debug)
		self._Navigation._setlanguageCode(self._languageCode)
		self._Navigation._setGrayscaleImg(self._grayscaleImg)
		self._Navigation._setInvertImg(self._invertImg)
		self._Navigation._setBlackWhiteImg(self._blackWhiteImg)
		self._Navigation._setBlackWhiteImgValue(self._blackWhiteImgValue)
		self._Navigation._setSendToClipboard(self._sendToClipboard)
		self._Navigation._setScreenShotMode(self._screenShotMode)
		self._Navigation._setHideGui(self._hideGui)
		self._Navigation._setPrintToStdOut(self._printToStdOut)
		if self._debug:
			print("PreWaitForFinish")
		self._macro.WaitForFinish()
		self._Navigation._setMacro(self._macro)
		time.sleep(0.5)
		if self._Navigation._screenShot():
			if not self._hideGui:
				self._Navigation.showGUI()
			else:
				self._Navigation._transformImg()
				self._Navigation._ocrImage()

		#FUNCTIONS
	def _setCommandLineOptions(self):
		try:
			myopts, args = getopt.getopt(sys.argv[1:],"hl:vndocgibt:m:")
			###############################
			# o == option
			# a == argument passed to the o
			###############################
			for o, a in myopts:
				if o == '-v':
					self._debug = True
					print('Debugmode ON')
				elif o == '-d':
					self._screenShotMode = 1
				elif o == '-g':
					self._grayscaleImg = True
				elif o == '-i':
					self._invertImg = True
				elif o == '-b':
					self._grayscaleImg = True
					self._blackWhiteImg = True
				elif o == '-t':
					self._blackWhiteImgValue = int(a)
				elif o == '-c':
					self._sendToClipboard = True
				elif o == '-l':
					self._languageCode = a
				elif o == '-m':
					self._macroFile = a
				elif o == '-n':
					self._hideGui = True
				elif o == '-o':
					self._printToStdOut = True
				elif o == '-h':
					self._printHelp()
		except:
					self._printHelp()

	def _printHelp(self):
		print(__version__)
		print("ocrdesktop -h -l -p -n -d -c -o -i -g -b -t -m")
		print("-h               Print help with start")
		print("-l <lang>        set the OCR language default=eng")
		print("-n               hide GUI (use with -c,-o or -m")
		print("-o               print to STDOUT")
		print("-v               print debug messages")
		print("-d               OCR the Destkop")
		print("-c               Send to Clipboard")
		print("-i               Invert the picture colors")
		print("-g               Grayscale picture")
		print("-b               break into hard black and white")
		print("-t               the value for braking into black and white (-b) 0 (black) - 255 (white)")
		print("-m <MacroFile>   run a macro before starting.")	
		self._showHelp = True				


class OCRMacroManager:

	def __init__(self,debug_p = False):
		self._cancelButton = None
		self._runMacroButton = None
		self._deleteMacroButton = None
		self._menubar = None
		self._accelerators = None
		self._grid = None
		self._labelAutoClickExists = None
		self._macroFile = os.path.expanduser('~') + '/.activeOCRMacro.ocrm'
		self._gui = None
		self._MacroFinished = False
		self._debug = debug_p
		
	def _loadMcroFile(self, macroFile_p):
		if self._loadMacroExists(macroFile_p):
			if macroFile_p != self._macroFile:
				shutil.copy(macroFile_p, self._macroFile)
		
	def _setDebug(self, debug_p):
		self._debug = debug_p

	def add_accelerator(self, widget, accelerator, signal="activate"):
		"""Adds a keyboard shortcut"""
		if accelerator is not None:
			key, mod = Gtk.accelerator_parse(accelerator)
			widget.add_accelerator(signal, self._accelerators, key, mod, Gtk.AccelFlags.VISIBLE)


	def _createMacroConfirm(self):

		dialog = Gtk.Window( title="Preclicks Manager")
		dialog.set_default_size(500, 60)
		dialog.set_modal(True)
		self._accelerators = Gtk.AccelGroup()
		self._menubar = Gtk.MenuBar()

		self._menubar = Gtk.MenuBar()
		
		self.menu_macro = Gtk.Menu()
		self.item_save = Gtk.MenuItem("_Save As")
		self.item_save.set_use_underline(True)
		self.add_accelerator(self.item_save, "<Control>s","activate")
		self.item_load = Gtk.MenuItem("_Load")
		self.item_load.set_use_underline(True)
		self.add_accelerator(self.item_load, "<Control>o","activate")
		self.item_delete = Gtk.MenuItem("_Unload")
		self.item_delete.set_use_underline(True)
		self.add_accelerator(self.item_delete, "<Control>u","activate")
		self.item_run = Gtk.MenuItem("_Run")
		self.item_run.set_use_underline(True)
		self.add_accelerator(self.item_run, "<Control>n","activate")
		self.menu_macro.append(self.item_save)
		self.menu_macro.append(self.item_load)
		self.menu_macro.append(self.item_delete)
		self.menu_macro.append(self.item_run)
		self.item_save.connect("activate", self._saveMacro, dialog)
		self.item_load.connect("activate", self._onLoadMacro, dialog)
		self.item_delete.connect("activate", self._onDeleteMacro, False)
		self.item_run.connect("activate", self._onRunMacro)
		
		self.menu_help = Gtk.Menu()
		self.item_about = Gtk.MenuItem("_About")
		self.item_about.set_use_underline(True)	
		self.menu_help.append(self.item_about)
		self.item_about.connect("activate", self._onRunAboutDialog, dialog)

		self.item_macro = Gtk.MenuItem("_Macro")
		self.item_macro.set_use_underline(True)
		self.item_help = Gtk.MenuItem("_Help")
		self.item_help.set_use_underline(True)

		self.item_macro.set_submenu(self.menu_macro)
		self.item_help.set_submenu(self.menu_help)

		self._menubar.append(self.item_macro)
		self._menubar.append(self.item_help)

		dialog.add_accel_group(self._accelerators)

		self._labelAutoClickExists = Gtk.Label("Preclicks are existing. What do you want do do with the preclicks?")
		self._labelAutoClickExists.set_selectable(True)

		self._runMacroButton = Gtk.Button(label="_Run")
		self._runMacroButton.set_use_underline(True)
		self._runMacroButton.connect('clicked', self._onRunMacro)

		self._deleteMacroButton = Gtk.Button(label='_Unload')
		self._deleteMacroButton.set_use_underline(True)
		self._deleteMacroButton.connect('clicked', self._onDeleteMacro)

		self._cancelButton = Gtk.Button(label='_Cancel')
		self._cancelButton.set_use_underline(True)
		self._cancelButton.connect('clicked', self._onCancel)

		self._grid = Gtk.Grid()

		dialog.connect("delete-event", self._onCancel)
		dialog.connect('key-release-event', self._onKeyRelease)
		self._grid.attach(self._menubar,0,0,3,1)
		self._grid.attach(self._labelAutoClickExists, 0 , 1, 3, 1)
		self._grid.attach(self._runMacroButton , 0, 2, 1, 1)
		self._grid.attach(self._deleteMacroButton, 1, 2, 1, 1)
		self._grid.attach(self._cancelButton, 2, 2, 1, 1)
		dialog.add(self._grid)
		
		return dialog
	
	def _onRunMacro(self, widget):
		self._gui.hide()
		_thread.start_new_thread( self._threadRunMacro, () )	
		self._cancel(False)
		
	def _onDeleteMacro(self, widget, close_p=True):
		self._deleteMacro()
		if close_p:
			self._cancel(True)

	def _onCancel(self, widget, event=None):
		self._cancel(True)

	def _cancel(self, setMacroFinished):
		if self._gui != None:
			self._gui.hide()
		if setMacroFinished:
			self._MacroFinished = True
		Gtk.main_quit()


	def _macroExists(self):
		return (os.path.exists(self._macroFile) and os.path.isfile(self._macroFile))

	def _loadMacroExists(self, newMacro_p):
		return (os.path.exists(newMacro_p) and os.path.isfile(newMacro_p))

	def _RunMacro(self):
		if not self._macroExists():
			if self._debug:
				print("No Macro loaded..")
			return
		self._MacroFinished = False
		macroFile = open(self._macroFile, "r")
		while 1:
			line = macroFile.readline()
			if not line:
				break
			if self._debug:
				print("_RunMacro: " + line)
			line = line.split(',')
			# doing stuff
			if line[0] == 'c':
				if line[1] == 'delay':
					time.sleep(float(line[2]))

			if line[0] == 'k':
				self._doKeyboardMacroStep(int(line[1]), line[2], int(line[3]))
			if line[0] == 'm':
				self._doMouseMacroStep(int(line[1]), int(line[2]), line[3])
		macroFile.close()
		self._MacroFinished = True
		
	def getMacroFinished(self):
		return self._MacroFinished
		
	def WaitForFinish(self):
		while not self.getMacroFinished() and self._macroExists():
			time.sleep(0.3)
			if self._debug:
				print(self.getMacroFinished())
		time.sleep(0.2)
		self._MacroFinished = False
		if self._debug:
			print("WaitForFinish complete")
		
	def _deleteMacro(self):
		if self._macroExists():
			os.remove(self._macroFile)
	
	def _saveMacro(self, widget, window):
		if not self._macroExists():
			return
		fileDialog = Gtk.FileChooserDialog("Save As", window,Gtk.FileChooserAction.SAVE,("_Cancel",Gtk.ResponseType.CANCEL,"_Save",Gtk.ResponseType.OK))
		fileDialog.set_modal(True)
		fileDialog.set_default_size(800, 400)
		fileDialog.set_local_only(False)
		self.add_filters(fileDialog)
		Gtk.FileChooser.set_current_name(fileDialog, "NewOCRdesktopMakro.ocrm")

		response = fileDialog.run()

		if response == Gtk.ResponseType.OK:
			shutil.copy( self._macroFile, fileDialog.get_filename(),)
		elif response == Gtk.ResponseType.CANCEL:
			pass

		fileDialog.destroy()

	def _onRunAboutDialog(self,widget,window):
		dialog = Gtk.AboutDialog(window)
		dialog.set_authors(__authors__)
		dialog.set_website(__website__)
		dialog.set_copyright(__copyright__)
		dialog.set_license(__license__)
		dialog.set_version(__version__)
		dialog.set_program_name(__appname__)
		dialog.set_comments(__comments__)
		dialog.run()
		dialog.destroy()

	def _onLoadMacro(self, widget, window):
		fileDialog = Gtk.FileChooserDialog("Please choose a file", window,Gtk.FileChooserAction.OPEN,("_Cancel",Gtk.ResponseType.CANCEL,"_Open",Gtk.ResponseType.OK))
		fileDialog.set_modal(True)
		fileDialog.set_default_size(800, 400)
		fileDialog.set_local_only(False)
		self.add_filters(fileDialog)

		response = fileDialog.run()
		if response == Gtk.ResponseType.OK:
			shutil.copy(fileDialog.get_filename(), self._macroFile)
		elif response == Gtk.ResponseType.CANCEL:
			pass

		fileDialog.destroy()

	def add_filters(self, fileDialog):
		filter_text = Gtk.FileFilter()
		filter_text.set_name("Macro Textfiles")
		filter_text.add_mime_type("text/plain")
		filter_text.add_pattern("*.ocrm")
		fileDialog.add_filter(filter_text)

		filter_any = Gtk.FileFilter()
		filter_any.set_name("Any files")
		filter_any.add_pattern("*")
		fileDialog.add_filter(filter_any)

	def _doKeyboardMacroStep(self,keyValue_p, keyString_p, eventType_p = 2):
		"""
		Arguments:
		- keyValue_p: a long integer indicating the keycode or keysym of the key event
			being synthesized.
		- keyString_p: an (optional) UTF-8 string which, if keyval is NULL,
			indicates a 'composed' keyboard input string which is
			being synthesized; this type of keyboard event synthesis does
			not emulate hardware keypresses but injects the string
			as though a composing input method (such as XIM) were used.
		- eventType_p: an AccessibleKeySynthType flag indicating whether keyval
			is to be interpreted as a keysym rather than a keycode
			(pyatspi.KEY_SYM), or whether to synthesize
			KEY_PRESS = 0, KEY_RELEASE = 1, or both (KEY_PRESSRELEASE = 2).
		"""
		if keyValue_p == 0:
			if keyString_p != '':
				keyValue_p = KEY_CODE[keyString_p]
			else:
				if self._debug:
					print("invalid keyboard macro",keyValue_p,keyString_p)
					print("format:")
					print("c, KeyValue, KeyString, eventType")
				return 	
		if eventType_p == 0:
			pyatspi.Registry.generateKeyboardEvent(keyValue_p, keyString_p, pyatspi.KEY_PRESS)
		elif eventType_p == 1:
			pyatspi.Registry.generateKeyboardEvent(keyValue_p, keyString_p, pyatspi.KEY_RELEASE)
		elif eventType_p == 2:
			pyatspi.Registry.generateKeyboardEvent(keyValue_p, keyString_p, pyatspi.KEY_PRESSRELEASE)

	def _doMouseMacroStep(self,xpos, ypos, mouseEvent, posRelation = "abs"):
		pyatspi.Registry.generateMouseEvent(xpos,ypos,posRelation)
		if (mouseEvent != 'None'):
			pyatspi.Registry.generateMouseEvent(xpos,ypos,mouseEvent)
			
	def _threadRunMacro(self):
		if self._debug:
			print("_threadRunMacro starts")
		self._RunMacro()

	def _writeKeyboardToMacro(self,keyValue_p, keyString_p, eventType_p):
		if eventType_p == pyatspi.KEY_PRESS:
			eventTypeID = 0
		elif eventType_p == pyatspi.KEY_RELEASE:
			eventTypeID = 1
		elif eventType_p == pyatspi.KEY_PRESSRELEASE:
			eventTypeID = 2
		macroFile = open(self._macroFile, "a")
		macroFile.write('k,' + str(keyValue_p) + ',' + str(keyString_p) + ',' + str(eventTypeID) + '\n')
		macroFile.close()

	def _writeMouseToMacro(self, Xpos_p, Ypos_p, MouseEvent_p):
		macroFile = open(self._macroFile, "a")
		macroFile.write('c,' + 'delay' + ',0.9\n')
		macroFile.write('m,' + str(Xpos_p) + ',' + str(Ypos_p) + ',' + MouseEvent_p + '\n')
		macroFile.close()

	def showGUI(self):
		if not self._macroExists():
			return

		self._gui = self._createMacroConfirm()
		self._gui.show_all()
		ts = Gtk.get_current_event_time()
		self._gui.present_with_time(ts)
		self._runMacroButton.grab_focus()
		Gtk.main()

	def _onKeyRelease(self, widget, event):
		keycode = event.hardware_keycode
		keymap = Gdk.Keymap.get_default()
		entries_for_keycode = keymap.get_entries_for_keycode(keycode)
		entries = entries_for_keycode[-1]
		eventString = Gdk.keyval_name(entries[0])
#		if self._debug:
#			print(eventString)
#		if eventString == 'Escape':
#			self._cancel(True)
#		if eventString == 'Return':
#			self._leftClickButton.grab_focus()


KEY_CODE = {
	'¼':13,
	'½':14,
	'0':19,
	'!':10,
	'/':106,
	'"':11,
	'1':10,
	'¹':10,
	'§':12,
	'$':13,
	'%':14,
	'¬':15,
	'&':15,
	'/':16,
	'{':16,
	'(':17,
	'[':17,
	')':18,
	']':18,
	'=':19,
	'}':19,
	'?':20,
	'\\':20,
	'2':11,
	'²':11,
	'@':24,
	'€':26,
	'¶':27,
	'←':29,
	'↓':30,
	'→':31,
	'3':12,
	'³':12,
	'~':35,
	'*':35,
	'+':35,
	'':37,
	'4':13,
	'°':49,
	'′':49,
	"'":51,
	'#':51,
	'5':14,
	'»':52,
	'«':53,
	'¢':54,
	'„':55,
	'“':56,
	'”':57,
	'µ':58,
	',':59,
	';':59,
	'·':59,
	':':60,
	'.':60,
	'…':60,
	'_':61,
	'-':61,
	'–':61,
	'6':15,
	'*':63,
	'7':16,
	'7':79,
	'8':17,
	'-':82,
	'+':86,
	'':9,
	'9':18,
	'<':94,
	'>':94,
	'|':94,
	'a':38,
	'A':38,
	'ä':48,
	'Ä':48,
	'Alt_L':64,
	'b':56,
	'B':56,
	'BackSpace':22,
	'c':54,
	'C':54,
	'Caps_Lock':66,
	'd':40,
	'D':40,
	'đ':41,
	'dead_acute':21,
	'dead_cedilla':21,
	'dead_circumflex':49,
	'dead_diaeresis':34,
	'dead_grave':21,
	'Delete':119,
	'Down':116,
	'e':26,
	'E':26,
	'End':115,
	'Escape':9,
	'F10':76,
	'F11':95,
	'F12':96,
	'F1':67,
	'F2':68,
	'F3':69,
	'f':41,
	'F':41,
	'F4':70,
	'F5':71,
	'F6':72,
	'F7':73,
	'F8':74,
	'F9':75,
	'g':42,
	'G':42,
	'h':43,
	'H':43,
	'Home':110,
	'i':31,
	'I':31,
	'Insert':118,
	'ISO_Left_Tab':23,
	'ISO_Level3_Shift':108,
	'j':44,
	'J':44,
	'k':45,
	'K':45,
	'KP_Begin':84,
	'KP_Delete':91,
	'KP_Down':88,
	'KP_End':87,
	'KP_Enter':104,
	'KP_Home':79,
	'KP_Insert':90,
	'KP_Left':83,
	'KP_Next':89,
	'KP_Page_Up':81,
	'KP_Right':85,
	'KP_Up':80,
	'ł':25,
	'l':46,
	'L':46,
	'Left':113,
	'm':58,
	'M':58,
	'Menu':135,
	'n':57,
	'N':57,
	'Num_Lock':77,
	'o':32,
	'O':32,
	'ø':32,
	'ö':47,
	'Ö':47,
	'p':33,
	'P':33,
	'Page_Down':117,
	'Page_Up':112,
	'Pause':127,
	'q':24,
	'Q':24,
	'r':27,
	'R':27,
	'Return':36,
	'Right':114,
	's':39,
	'S':39,
	'Scroll_Lock':78,
	'Shift_L':50,
	'Shift_R':62,
	'space':65,
	'ß':20,
	'Super_R':134,
	't':28,
	'T':28,
	'ŧ':28,
	'Tab':23,
	'u':30,
	'U':30,
	'ü':34,
	'Ü':34,
	'Up':111,
	'v':55,
	'V':55,
	'w':25,
	'W':25,
	'x':53,
	'X':53,
	'y':52,
	'Y':52,
	'z':29,
	'Z':29,
	'þ':33,
	}

if __name__ == "__main__":
	Application = OCRScreenReader()

