def _crashHandler(exceptionInfo): threadId = ctypes.windll.kernel32.GetCurrentThreadId() # An exception might have been set for this thread. # Clear it so that it doesn't get raised in this function. ctypes.pythonapi.PyThreadState_SetAsyncExc(threadId, None) # Write a minidump. dumpPath = os.path.abspath(os.path.join(globalVars.appArgs.logFileName, "..", "nvda_crash.dmp")) try: with file(dumpPath, "w") as mdf: mdExc = MINIDUMP_EXCEPTION_INFORMATION(ThreadId=threadId, ExceptionPointers=exceptionInfo, ClientPointers=False) if not ctypes.windll.DbgHelp.MiniDumpWriteDump( ctypes.windll.kernel32.GetCurrentProcess(), os.getpid(), msvcrt.get_osfhandle(mdf.fileno()), 0, # MiniDumpNormal ctypes.byref(mdExc), None, None ): raise ctypes.WinError() except: log.critical("NVDA crashed! Error writing minidump", exc_info=True) else: log.critical("NVDA crashed! Minidump written to %s" % dumpPath) # Log Python stacks for every thread. for logThread, logFrame in sys._current_frames().iteritems(): log.info("Python stack for thread %d" % logThread, stack_info=traceback.extract_stack(logFrame)) log.info("Restarting due to crash") core.restart() return 1 # EXCEPTION_EXECUTE_HANDLER
def _crashHandler(exceptionInfo): # An exception might have been set for this thread. # Clear it so that it doesn't get raised in this function. ctypes.pythonapi.PyThreadState_SetAsyncExc(threading.currentThread().ident, None) import core core.restart() return 1 # EXCEPTION_EXECUTE_HANDLER
def previousLine(self, start=False): try: dest = self._readingInfo.copy() dest.collapse() if start: unit = self._getReadingUnit() else: # If the end of the reading unit is desired, move to the last # character. unit = textInfos.UNIT_CHARACTER moved = dest.move(unit, -1) if not moved: if self.allowPageTurns and isinstance( dest.obj, textInfos.DocumentWithPageTurns): try: dest.obj.turnPage(previous=True) except RuntimeError: pass else: dest = dest.obj.makeTextInfo(textInfos.POSITION_LAST) dest.expand(unit) else: # no page turn support return dest.collapse() self._setCursor(dest) sayCurrentLine() except BaseException as e: log.error("Error with scroll function patch, disabling: %s" % e) configBE.conf["patch"]["scrollBraille"] = False configBE.conf["general"]["speakScroll"] = False core.restart()
def processUpdate(): url = addonInfos["url"] if url.endswith('/'): url = url[0:-1] url = "%s.nvda-addon?%s" % (url, urlencode(paramsDL())) fp = os.path.join(globalVars.appArgs.configPath, "%s.nvda-addon" % sectionName) try: dl = URLopener() dl.retrieve(url, fp) try: curAddons = [] for addon in addonHandler.getAvailableAddons(): curAddons.append(addon) bundle = addonHandler.AddonBundle(fp) prevAddon = None bundleName = bundle.manifest['name'] for addon in curAddons: if not addon.isPendingRemove and bundleName == addon.manifest[ 'name']: prevAddon = addon break if prevAddon: prevAddon.requestRemove() addonHandler.installAddonBundle(bundle) core.restart() except BaseException as e: log.error(e) os.startfile(fp) except BaseException as e: log.error(e) return wx.CallAfter(errorUpdateDialog)
def _crashHandler(exceptionInfo): threadId = ctypes.windll.kernel32.GetCurrentThreadId() # An exception might have been set for this thread. # Clear it so that it doesn't get raised in this function. ctypes.pythonapi.PyThreadState_SetAsyncExc(threadId, None) # Write a minidump. dumpPath = os.path.abspath(os.path.join(globalVars.appArgs.logFileName, "..", "nvda_crash.dmp")) try: with file(dumpPath, "w") as mdf: mdExc = MINIDUMP_EXCEPTION_INFORMATION(ThreadId=threadId, ExceptionPointers=exceptionInfo, ClientPointers=False) if not ctypes.windll.DbgHelp.MiniDumpWriteDump( ctypes.windll.kernel32.GetCurrentProcess(), os.getpid(), msvcrt.get_osfhandle(mdf.fileno()), 0, # MiniDumpNormal ctypes.byref(mdExc), None, None ): raise ctypes.WinError() except: log.critical("NVDA crashed! Error writing minidump", exc_info=True) else: log.critical("NVDA crashed! Minidump written to %s" % dumpPath) log.info("Restarting due to crash") core.restart() return 1 # EXCEPTION_EXECUTE_HANDLER
def updateAll(self): updated = 0 if len(self.updates) is 0: self.refreshAddons(True) if len(self.updates) == 0: ui.message(_(u"NVDAStore: No update available.")) return for update in self.updates: gui.mainFrame.prePopup() progressDialog = gui.IndeterminateProgressDialog( gui.mainFrame, _("NVDAStore"), _(u"Updating {name}...".format(name=update.name))) ui.message(_("Updating {name}".format(name=update.name))) try: gui.ExecAndPump(storeUtils.installAddon, self.storeClient, update, False, True) except: progressDialog.done() del progressDialog gui.mainFrame.postPopup() break progressDialog.done() del progressDialog updated += 1 gui.mainFrame.postPopup() if updated: core.restart()
def onSaveAndRestartNVDA(self, evt): checkedItems = list(self.addonsListBox.GetCheckedItems()) if checkedItems == self.curActivatedAddons: # no change # Translators: Title for message asking if the user wishes to restart NVDA even if there were no changes restartTitle = NVDAString("Restart NVDA") # Translators: A message asking the user if they wish to restart NVDA # even if there were no changes restartMessage = _( "There is no change. Do you want to restart NVDA anyway?") result = gui.messageBox(message=restartMessage, caption=restartTitle, style=wx.YES | wx.NO | wx.ICON_WARNING) if wx.YES == result: core.restart() return # there is change, so set state of all cur addons for index in range(0, len(self.curAddons)): oldActivation = index in self.curActivatedAddons newActivation = index in checkedItems if newActivation == oldActivation: continue addon = self.curAddons[index] shouldEnable = index in checkedItems try: addon.enable(shouldEnable) except addonHandler.AddonError: log.error("Couldn't change state for %s add-on" % addon.name, exc_info=True) continue core.restart()
def updateAddonsGenerator(addons, auto=True): """Updates one add-on after the other. The auto parameter is used to show add-ons manager after all add-ons were updated. """ if not len(addons): # Only present messages if add-osn were actually updated. if len(_updatedAddons): # This is possible because all add-ons were updated. if gui.messageBox( translate( "Changes were made to add-ons. You must restart NVDA for these changes to take effect. " "Would you like to restart now?"), translate("Restart NVDA"), wx.YES | wx.NO | wx.ICON_WARNING) == wx.YES: core.restart() return # #3208: Update (download and install) add-ons one after the other, # done by retrieving the first item (as far as current add-ons container is concerned). addonInfo = addons.pop(0) downloader = AddonUpdateDownloader([addonInfo["urls"]], addonInfo["summary"], addonsToBeUpdated=addons, auto=auto) downloader.start() yield
def processUpdate(): url = configBE._addonURL + "latest?" + urlencode(paramsDL()) fp = os.path.join(globalVars.appArgs.configPath, "brailleExtender.nvda-addon") try: dl = URLopener() dl.retrieve(url, fp) try: curAddons = [] for addon in addonHandler.getAvailableAddons(): curAddons.append(addon) bundle = addonHandler.AddonBundle(fp) prevAddon = None bundleName = bundle.manifest['name'] for addon in curAddons: if not addon.isPendingRemove and bundleName == addon.manifest[ 'name']: prevAddon = addon break if prevAddon: prevAddon.requestRemove() addonHandler.installAddonBundle(bundle) core.restart() except BaseException as e: log.error(e) os.startfile(fp) except BaseException as e: log.error(e) ui.message( _("Unable to save or download update file. Opening your browser" )) os.startfile(url) return
def options(): argus = sys.argv[1:] if not sys.argv[1:]: option_usage() sys.exit() cmd = parse_arguments(argus) for command in cmd: if command == "build": argc = len(cmd[command]) if argc == 2: if cmd[command][1] == "nginx": nversion = conf.NGINXVERSION core.install_nginx(nversion) elif cmd[command][1] == "vhosts": core.rebuild_all_vhost() elif cmd[command][1] == "sslcerts": core.buildsslcerts() elif cmd[command][1] == "remoteip": core.buildremoteip() else: invalid_option() elif argc == 4: if cmd[command][1] == "nginx" and cmd[command][ 2] == "--version": nversion = cmd[command][3].strip() core.install_nginx(nversion) else: invalid_option() else: invalid_option() elif command == "rebuildvhost": rvhdom = cmd[command][1] core.rebuildvhost(rvhdom) elif command == "rmvhost": rvhdom = cmd[command][1] core.rmvhost(rvhdom) elif command == "rebuilduservhost": cpuser = cmd[command][1] core.rebuilduservhost(cpuser) elif command == "rmuservhost": cpuser = cmd[command][1] core.rmuservhost(cpuser) elif command == "templaterebuild": core.templaterebuild() elif command == "restart": core.restart() elif command == "setupphpfpm": core.setupphpfpm() elif command == "help": option_usage() elif command == "enable": core.enable() elif command == "disable": core.disable() elif command == "status": core.status() elif command == "version": core.version() else: invalid_option()
def update_check(self, add_notif=True, install=True): logging.info('Checking for updates.') data = self._update_check() # if data['status'] == 'current', nothing to do. if data['status'] == 'error': notif = { 'title': 'Error Checking for Updates <br/>', 'message': data['error'] } notification.add(notif, type_='danger') elif data['status'] == 'behind': if data['behind_count'] == 1: title = '1 Update Available <br/>' else: title = '{} Updates Available <br/>'.format( data['behind_count']) compare = '{}/compare/{}...{}'.format(core.GIT_URL, data['local_hash'], data['new_hash']) notif = { 'type': 'update', 'title': title, 'message': 'Click <a onclick="_start_update(event)"><u>here</u></a> to update now.<br/> Click <a href="{}" target="_blank" rel="noopener"><u>here</u></a> to view changes.' .format(compare) } notification.add(notif, type_='success') if install and core.CONFIG['Server']['installupdates']: logging.info( 'Currently {} commits behind. Updating to {}.'.format( core.UPDATE_STATUS['behind_count'], core.UPDATE_STATUS['new_hash'])) core.UPDATING = True core.scheduler_plugin.stop() update = self.execute_update() core.UPDATING = False if not update: logging.error('Update failed.') core.scheduler_plugin.restart() logging.info('Update successful, restarting.') core.restart() else: logging.info( 'Currently {} commits behind. Automatic install disabled'. format(core.UPDATE_STATUS['behind_count'])) return data
def onClose(self,evt): self.Destroy() if self.needsRestart: # Translators: A message asking the user if they wish to restart NVDA as addons have been added or removed. if gui.messageBox(_("Add-ons have been added or removed. You must restart NVDA for these changes to take effect. Would you like to restart now?"), # Translators: Title for message asking if the user wishes to restart NVDA as addons have been added or removed. _("Restart NVDA"), wx.YES|wx.NO|wx.ICON_WARNING)==wx.YES: core.restart()
def install(): # To remove the old version ourAddon.requestRemove() # to install the new version addonHandler.installAddonBundle(bundle) # to delete the downloads folder shutil.rmtree(directory, ignore_errors=True) # to restart NVDA core.restart()
def promptUserForRestart(): # Translators: A message asking the user if they wish to restart NVDA as addons have been added, enabled/disabled or removed. restartMessage = _( "Changes were made to add-ons. " "You must restart NVDA for these changes to take effect. " "Would you like to restart now?") # Translators: Title for message asking if the user wishes to restart NVDA as addons have been added or removed. restartTitle = _("Restart NVDA") result = gui.messageBox(message=restartMessage, caption=restartTitle, style=wx.YES | wx.NO | wx.ICON_WARNING) if wx.YES == result: core.restart()
def promptUserForRestart(): # Translators: A message asking the user if they wish to restart NVDA as addons have been added, enabled/disabled or removed. restartMessage = _( "Changes were made to add-ons. " "You must restart NVDA for these changes to take effect. " "Would you like to restart now?" ) # Translators: Title for message asking if the user wishes to restart NVDA as addons have been added or removed. restartTitle = _("Restart NVDA") result = gui.messageBox( message=restartMessage, caption=restartTitle, style=wx.YES | wx.NO | wx.ICON_WARNING ) if wx.YES == result: core.restart()
def onClose(self,evt): self.Destroy() needsRestart = False for addon in self.curAddons: if (addon.isPendingInstall or addon.isPendingRemove or addon.isDisabled and addon.isPendingEnable or addon.isRunning and addon.isPendingDisable): needsRestart = True break if needsRestart: # Translators: A message asking the user if they wish to restart NVDA as addons have been added, enabled/disabled or removed. if gui.messageBox(_("Changes were made to add-ons. You must restart NVDA for these changes to take effect. Would you like to restart now?"), # Translators: Title for message asking if the user wishes to restart NVDA as addons have been added or removed. _("Restart NVDA"), wx.YES|wx.NO|wx.ICON_WARNING)==wx.YES: core.restart()
def onClose(self,evt): self.Destroy() needsRestart = False for addon in addonHandler.getAvailableAddons(): if (addon.isPendingInstall or addon.isPendingRemove or addon.isDisabled and addon.isPendingEnable or addon.isRunning and addon.isPendingDisable): needsRestart = True break if needsRestart: # Translators: A message asking the user if they wish to restart NVDA as addons have been added, enabled/disabled or removed. # if gui.messageBox(_("Changes were made to add-ons. You must restart NVDA for these changes to take effect. Would you like to restart now?"), # Translators: Title for message asking if the user wishes to restart NVDA as addons have been added or removed. # _("Restart NVDA"), # wx.YES|wx.NO|wx.ICON_WARNING)==wx.YES: core.restart()
def getAddon(): import tempfile, os addon = opener(updateInfo["downloadUrl"]) content = addon.read() addon.close() if updateInfo["size"] != len(content): gui.messageBox(_("Data load error"), _("Error"), style=wx.OK | wx.ICON_ERROR) return fd, path = tempfile.mkstemp(".nvda-addon", "tcmd_addon_update-") with open(path, "wb") as file: file.write(content) import core bundle = addonHandler.AddonBundle(path) try: if not addonHandler.addonVersionCheck.isAddonCompatible(bundle): gui.messageBox(_( "This version of NVDA is incompatible. To install the add-on, NVDA version {year}.{major} or higher is required. Please update NVDA or download an older version of the add-on here: \n{link}" ).format( year=bundle.minimumNVDAVersion[0], major=bundle.minimumNVDAVersion[1], link= "https://github.com/jawhien/extendedTotalCmd/releases/tag/2.5" ), _("Error"), style=wx.OK | wx.ICON_ERROR) os.close(fd) os.unlink(path) return except: pass gui.ExecAndPump(addonHandler.installAddonBundle, bundle) for addon in addonHandler.getAvailableAddons(): if not addon.isPendingRemove and manifest["name"].lower( ) == addon.manifest["name"].lower(): addon.requestRemove() break os.close(fd) os.unlink(path) if gui.messageBox(_( "Changes were made to add-ons. You must restart NVDA for these changes to take effect. Would you like to restart now?" ), _("Restart NVDA"), style=wx.YES | wx.NO | wx.ICON_WARNING) == wx.YES: core.restart()
def onClose(self,evt): self.Destroy() # #7077: If the instance flag isn't cleared, it causes issues when add-ons manager reopens or another add-on is installed remotely. AddonsDialog._instance = None needsRestart = False for addon in self.curAddons: if (addon.isPendingInstall or addon.isPendingRemove or addon.isDisabled and addon.isPendingEnable or addon.isRunning and addon.isPendingDisable): needsRestart = True break if needsRestart: # Translators: A message asking the user if they wish to restart NVDA as addons have been added, enabled/disabled or removed. if gui.messageBox(_("Changes were made to add-ons. You must restart NVDA for these changes to take effect. Would you like to restart now?"), # Translators: Title for message asking if the user wishes to restart NVDA as addons have been added or removed. _("Restart NVDA"), wx.YES|wx.NO|wx.ICON_WARNING)==wx.YES: core.restart()
def onClose(self, evt): self.Destroy() # #7077: If the instance flag isn't cleared, it causes issues when add-ons manager reopens or another add-on is installed remotely. AddonsDialog._instance = None needsRestart = False for addon in self.curAddons: if (addon.isPendingInstall or addon.isPendingRemove or addon.isDisabled and addon.isPendingEnable or addon.isRunning and addon.isPendingDisable): needsRestart = True break if needsRestart: # Translators: A message asking the user if they wish to restart NVDA as addons have been added, enabled/disabled or removed. if gui.messageBox( _("Changes were made to add-ons. You must restart NVDA for these changes to take effect. Would you like to restart now?" ), # Translators: Title for message asking if the user wishes to restart NVDA as addons have been added or removed. _("Restart NVDA"), wx.YES | wx.NO | wx.ICON_WARNING) == wx.YES: core.restart()
def onSave(self): config.conf["brailleExtender"]["outputTables"] = ','.join(self.oTables) config.conf["brailleExtender"]["inputTables"] = ','.join(self.iTables) config.conf["brailleExtender"]["inputTableShortcuts"] = addoncfg.tablesUFN[self.inputTableShortcuts.GetSelection() - 1] if self.inputTableShortcuts.GetSelection() > 0 else '?' addoncfg.loadPreferedTables() postTableID = self.postTable.GetSelection() postTable = "None" if postTableID == 0 else addoncfg.tablesFN[postTableID] config.conf["brailleExtender"]["postTable"] = postTable if self.tabSpace.IsChecked() and config.conf["brailleExtender"]["tabSpace"] != self.tabSpace.IsChecked(): restartRequired = True else: restartRequired = False config.conf["brailleExtender"]["tabSpace"] = self.tabSpace.IsChecked() config.conf["brailleExtender"]["tabSize_%s" % addoncfg.curBD] = self.tabSize.Value if restartRequired: res = gui.messageBox( _("NVDA must be restarted for changes to take effect. Would you like to restart now?"), _("Braille Extender"), style=wx.YES_NO|wx.ICON_INFORMATION ) if res == wx.YES: core.restart()
def processUpdate(expectedSHA256Sum): url = addonInfos["url"] if url.endswith('/'): url = url[0:-1] url = "%s.nvda-addon?%s" % (url, urlencode(paramsDL())) fp = os.path.join(globalVars.appArgs.configPath, "%s.nvda-addon" % sectionName) try: with urllib.request.urlopen(url) as res: with open(fp, "wb") as out: out.write(res.read()) actualSHA256Sum = SHA256Sum(fp) if expectedSHA256Sum != actualSHA256Sum: log.info("Invalid hash for %s. Actual: %s, expected: %s" % (fp, actualSHA256Sum, expectedSHA256Sum)) msg = _( "Hashes do not match! Actual value is '{actualHash}'. Expected is '{expectedHash}'." ).format(actualHash=actualSHA256Sum, expectedHash=expectedSHA256Sum) wx.CallAfter(errorUpdateDialog, msg) return curAddons = [] for addon in addonHandler.getAvailableAddons(): curAddons.append(addon) bundle = addonHandler.AddonBundle(fp) prevAddon = None bundleName = bundle.manifest['name'] for addon in curAddons: if not addon.isPendingRemove and bundleName == addon.manifest[ "name"]: prevAddon = addon break if prevAddon: prevAddon.requestRemove() addonHandler.installAddonBundle(bundle) core.restart() except BaseException as e: log.error(e) return wx.CallAfter(errorUpdateDialog, e)
def _crashHandler(exceptionInfo): threadId = ctypes.windll.kernel32.GetCurrentThreadId() # An exception might have been set for this thread. # Clear it so that it doesn't get raised in this function. ctypes.pythonapi.PyThreadState_SetAsyncExc(threadId, None) # Write a minidump. dumpPath = os.path.abspath( os.path.join(globalVars.appArgs.logFileName, "..", "nvda_crash.dmp")) try: # Though we aren't using pythonic functions to write to the dump file, # open it in binary mode as opening it in text mode (the default) doesn't make sense. with open(dumpPath, "wb") as mdf: mdExc = MINIDUMP_EXCEPTION_INFORMATION( ThreadId=threadId, ExceptionPointers=exceptionInfo, ClientPointers=False) if not ctypes.windll.DbgHelp.MiniDumpWriteDump( ctypes.windll.kernel32.GetCurrentProcess(), os.getpid(), msvcrt.get_osfhandle(mdf.fileno()), 0, # MiniDumpNormal ctypes.byref(mdExc), None, None): raise ctypes.WinError() except: log.critical("NVDA crashed! Error writing minidump", exc_info=True) else: log.critical("NVDA crashed! Minidump written to %s" % dumpPath) # Log Python stacks for every thread. stacks = getFormattedStacksForAllThreads() log.info(f"Listing stacks for Python threads:\n{stacks}") log.info("Restarting due to crash") core.restart() return 1 # EXCEPTION_EXECUTE_HANDLER
def nextLine(self): try: dest = self._readingInfo.copy() moved = dest.move(self._getReadingUnit(), 1) if not moved: if self.allowPageTurns and isinstance( dest.obj, textInfos.DocumentWithPageTurns): try: dest.obj.turnPage() except RuntimeError: pass else: dest = dest.obj.makeTextInfo(textInfos.POSITION_FIRST) else: # no page turn support return dest.collapse() self._setCursor(dest) sayCurrentLine() except BaseException as e: log.error("Error with scroll function patch, disabling: %s" % e) configBE.conf["patch"]["scrollBraille"] = False configBE.conf["general"]["speakScroll"] = False core.restart()
def draw(): global space global points global str_points if pyxel.game_over: pyxel.cls(pyxel.COLOR_RED) pyxel.text(110, 80, "YOU DIED", pyxel.COLOR_WHITE) pyxel.text(100, 100, "You scored " + str_points, pyxel.COLOR_WHITE) pyxel.text(80, 120, "PRESS <SPACE> TO TRY AGAIN", pyxel.COLOR_WHITE) space = restart(space) else: pyxel.cls(pyxel.COLOR_BLACK) draw_game(space) points = dt + points str_points = str(int(points)) pyxel.text(190, 10, "POINTS " + str_points, pyxel.COLOR_WHITE)
def update_check(install=True): ''' Checks for any available updates install (bool): install updates if found Setting 'install' for False will ignore user's config for update installation If 'install' is True, user config must also allow automatic updates Creates notification if updates are available. Returns dict from core.version.Version.manager.update_check(): {'status': 'error', 'error': <error> } {'status': 'behind', 'behind_count': #, 'local_hash': 'abcdefg', 'new_hash': 'bcdefgh'} {'status': 'current'} ''' data = ver.manager.update_check() # if data['status'] == 'current', nothing to do. if data['status'] == 'error': notif = { 'title': 'Error Checking for Updates <br/>', 'message': data['error'] } notification.add(notif, type_='danger') elif data['status'] == 'behind': if data['behind_count'] == 1: title = '1 Update Available <br/>' else: title = '{} Updates Available <br/>'.format( data['behind_count']) compare = '{}/compare/{}...{}'.format(core.GIT_URL, data['local_hash'], data['new_hash']) notif = { 'type': 'update', 'title': title, 'message': 'Click <a onclick="_start_update(event)"><u>here</u></a> to update now.<br/> Click <a href="{}{}" target="_blank" rel="noopener"><u>here</u></a> to view changes.' .format(core.URL_BASE, compare) } notification.add(notif, type_='success') if install and core.CONFIG['Server']['installupdates']: logging.info( 'Currently {} commits behind. Updating to {}.'.format( core.UPDATE_STATUS['behind_count'], core.UPDATE_STATUS['new_hash'])) core.UPDATING = True core.scheduler_plugin.stop() update = ver.manager.execute_update() core.UPDATING = False if not update: logging.error('Update failed.') core.scheduler_plugin.restart() logging.info('Update successful, restarting.') core.restart() else: logging.info( 'Currently {} commits behind. Automatic install disabled'. format(core.UPDATE_STATUS['behind_count'])) return data
def update(self): """Update this region. Subclasses should extend this to update L{rawText}, L{cursorPos}, L{selectionStart} and L{selectionEnd} if necessary. The base class method handles translation of L{rawText} into braille, placing the result in L{brailleCells}. Typeform information from L{rawTextTypeforms} is used, if any. L{rawToBraillePos} and L{brailleToRawPos} are updated according to the translation. L{brailleCursorPos}, L{brailleSelectionStart} and L{brailleSelectionEnd} are similarly updated based on L{cursorPos}, L{selectionStart} and L{selectionEnd}, respectively. @postcondition: L{brailleCells}, L{brailleCursorPos}, L{brailleSelectionStart} and L{brailleSelectionEnd} are updated and ready for rendering. """ try: mode = louis.dotsIO if config.conf["braille"][ "expandAtCursor"] and self.cursorPos is not None: mode |= louis.compbrlAtCursor try: text = unicode(self.rawText).replace('\0', '') braille, self.brailleToRawPos, self.rawToBraillePos, brailleCursorPos = louis.translate( configBE.preTable + [ os.path.join(brailleTables.TABLES_DIR, config.conf["braille"]["translationTable"]), os.path.join(brailleTables.TABLES_DIR, "braille-patterns.cti") ] + configBE.postTable, text, # liblouis mutates typeform if it is a list. typeform=tuple(self.rawTextTypeforms) if isinstance( self.rawTextTypeforms, list) else self.rawTextTypeforms, mode=mode, cursorPos=self.cursorPos or 0) except BaseException: if len(configBE.postTable) == 0: log.error( "Error with update braille function patch, disabling: %s") braille.Region.update = backupUpdate core.restart() return log.warning( 'Unable to translate with secondary table: %s and %s.' % (config.conf["braille"]["translationTable"], configBE.postTable)) configBE.postTable = [] config.conf["brailleExtender"]["postTable"] = "None" update(self) return # liblouis gives us back a character string of cells, so convert it to a list of ints. # For some reason, the highest bit is set, so only grab the lower 8 # bits. self.brailleCells = [ord(cell) & 255 for cell in braille] # #2466: HACK: liblouis incorrectly truncates trailing spaces from its output in some cases. # Detect this and add the spaces to the end of the output. if self.rawText and self.rawText[-1] == " ": # rawToBraillePos isn't truncated, even though brailleCells is. # Use this to figure out how long brailleCells should be and thus # how many spaces to add. correctCellsLen = self.rawToBraillePos[-1] + 1 currentCellsLen = len(self.brailleCells) if correctCellsLen > currentCellsLen: self.brailleCells.extend( (0, ) * (correctCellsLen - currentCellsLen)) if self.cursorPos is not None: # HACK: The cursorPos returned by liblouis is notoriously buggy (#2947 among other issues). # rawToBraillePos is usually accurate. try: brailleCursorPos = self.rawToBraillePos[self.cursorPos] except IndexError: pass else: brailleCursorPos = None self.brailleCursorPos = brailleCursorPos if self.selectionStart is not None and self.selectionEnd is not None: try: # Mark the selection. self.brailleSelectionStart = self.rawToBraillePos[ self.selectionStart] if self.selectionEnd >= len(self.rawText): self.brailleSelectionEnd = len(self.brailleCells) else: self.brailleSelectionEnd = self.rawToBraillePos[ self.selectionEnd] for pos in xrange(self.brailleSelectionStart, self.brailleSelectionEnd): self.brailleCells[pos] |= SELECTION_SHAPE() except IndexError: pass else: if instanceGP.hideDots78: for i, j in enumerate(self.brailleCells): self.brailleCells[i] &= 63 except BaseException as e: log.error("Error with update braille patch, disabling: %s" % e) braille.Region.update = backupUpdate