def initialise_database(exception=None): Log(__name__).debug("Initialising database, %s", exception.__str__()) Base.metadata.create_all(app.config["DATABASE"]["ENGINE"]) # populate default data. with app.config["DATABASE"]["SESSION"]() as db_session: try: # Add in any program privileges. for privilege_name in list(PrivilegeNames): init_privilege( db_session, privilege_name.value, privilege_name.name ) # If there is no admin in the database, add the default admin. if not ( db_session.query(UserPrivilege) .join(Privilege) .filter(Privilege.name == PrivilegeNames.ADMIN.name) .first() ): db_session.add(User(**default_user)) add_user_privilege( db_session, user_value=default_user["name"], user_field=User.name, privilege=PrivilegeNames.ADMIN.name, privilege_field=Privilege.name, ) except (SQLAlchemyError, UOSDatabaseError) as sql_exception: Log(__name__).error( "Failed to populate defaults into database %s.", sql_exception.__str__(), ) db_session.rollback() else: db_session.commit()
def __init__(self): self.stage.align = StageAlign.TOP_LEFT self.stage.scaleMode = StageScaleMode.NO_SCALE wurl = None newparams = {} for k, v in items(self.loaderInfo.parameters): if k == 'wrapped_url': wurl = v else: newparams[k] = v self.params = newparams self.namespace = { 'load': self.load, 'params': newparams, 'unload': self.unload, 'root': self.get_root, '_root': self, 'print': self.print, 'repr': repr, 'locals': self.print_namespace, } self.console = Console(self, Evaluator(self.namespace)) self.namespace.console = self.console Log.add_handler(self.console) if wurl: Log.info("Loading url " + repr(wurl)) self.load(wurl)
def decode_and_capture(byte_index: int, byte_in: bytes, packet: list) -> (int, list): """Parser takes in a byte and vets it against UOS packet. :param byte_index: The index of the last 'valid' byte found. :param byte_in: The current byte for inspection. :param packet: The current packet of validated bytes. :return: Tuple containing the updated byte index and updated packet. """ if byte_index == -1: # start symbol if byte_in == b">": byte_index += 1 if byte_index >= 0: Log(__name__).debug( "read %s byte index = %s", byte_in, byte_index, ) payload_len = packet[3] if len(packet) > 3 else 0 if byte_index == 3 + 2 + payload_len: # End packet symbol if byte_in == b"<": byte_index = -2 # packet complete Log(__name__).debug("Found end packet symbol") else: # Errored data byte_index = -1 packet = [] packet.append(int.from_bytes(byte_in, byteorder="little")) return byte_index, packet
def check_privileges(privilege_names: list, session, user) -> bool: """Function for checking a user's privileges match requirements. Authorised if no privilege names in argument and user is logged in. Authorised if user has listed privilege or admin. :param: List of names of privileges with access, empty means logged in. :param: SQLAlchemy session instance to lookup user privileges. :param: User to check against privilege list. :return: True if authorised, False otherwise. """ if not user.is_authenticated: return False Log(__name__).debug("Checking user privileges for %s", user.name) if len(privilege_names) == 0: # essentially just login_required return True # iterate through privileges of user and check for a match user_privileges = get_user_privileges(session, user.id) Log(__name__).debug( "Has privileges %s", [user_privilege.name for user_privilege in user_privileges], ) for user_privilege in user_privileges: if (user_privilege.name in privilege_names or user_privilege.name == PrivilegeNames.ADMIN.name): return True return False
def __init__(self, connection: str, **kwargs): """Constructor for a NPCSerialPort device. :param connection: OS connection string for the serial port. """ self._connection = connection self._port = self.check_port_exists(connection) self._kwargs = kwargs if self._port is None: Log(__name__).error("%s port does not exist", connection) else: Log(__name__).debug("%s located", self._port)
def start_processes(parse_res, count_cpu_param=1): user = [parse_res.user["host"], parse_res.user["name"], parse_res.user["password"]] processes = [] log = Log(os.path.dirname(os.path.abspath(__file__))) queue_of_paths = Queue() if not FTPLoader.check_login(*user, log): return for path in parse_res.paths: queue_of_paths.put(path) if queue_of_paths.qsize() < count_cpu_param: loader = FTPLoader(*user, log) loader.start_load(queue_of_paths) else: for i in range(count_cpu_param - 1): another_loader = FTPLoader(*user, log) # you can change Process to Thread and it will be work(don't forget import threading) process = Process(target=another_loader.start_load, args=(queue_of_paths, )) process.start() processes.append(process) loader = FTPLoader(*user, log) loader.start_load(queue_of_paths)
def wrapped_function(*args, **kwargs): """Handling web-app route selection for the wrapped route. :param args: Wrapped function's positional arguments. :param kwargs: Wrapped function's keyword arguments. :return: Wrapped route if authorised, otherwise redirect to error. """ with current_app.config["DATABASE"]["SESSION"]() as session: if check_privileges(privilege_names, session, current_user): Log(__name__).debug("Authenticated %s.", current_user.name) return func(*args, **kwargs) Log(__name__).info( "Attempt to access %s protected route while not logged in.", func.__name__, ) return url_for("auth_blueprint.route_error", error=401)
def close(self): """Closes the serial connection and clears the device. :return: Success boolean. """ if not self.check_open(): return True # already closed try: self._device.close() except SerialException as exception: Log(__name__).debug("Closing the connection threw error %s", exception.__str__()) self._device = None return False Log(__name__).debug("Connection closed successfully") self._device = None return True
def __init__(self, logger=None): """Constructor :param Logger logger: Logger """ if logger: self.logger = logger else: self.logger = Log("Config Generator") self.logs = []
def __init__(self): self.stage.align = StageAlign.TOP_LEFT self.stage.scaleMode = StageScaleMode.NO_SCALE self.tf = TextField() Holder.textbox = self.tf self.addChild(self.tf) self.tf.width = 640 self.tf.height = 480 MyLog.warning("My Warning Function Called") Log.add_handler(Console(self, Evaluator())) Log.info("Some info message") Log.warning("Some warning") Log.error("Some error message")
def open(self): """Opens a connection to the the port and creates the device object. :return: Success boolean. """ try: self._port = self.check_port_exists(self._connection) if self._port is None: Log(__name__).error("%s device was not present to open", self._connection) return False self._device = serial.Serial() self._device.port = self._connection if "baudrate" in self._kwargs: self._device.baudrate = self._kwargs["baudrate"] if platform.system( ) == "Linux": # DTR transient workaround for Unix Log(__name__).debug( "Linux platform found so using DTR workaround") with open(self._connection) as port: attrs = termios.tcgetattr(port) attrs[2] = attrs[2] & ~termios.HUPCL termios.tcsetattr(port, termios.TCSAFLUSH, attrs) else: # DTR transient workaround for Windows self._device.dtr = False self._device.open() Log(__name__).debug("%s opened successfully", self._port.device) return True except (SerialException, FileNotFoundError) as exception: Log(__name__).error( "Opening %s threw error %s", self._port.device if self._port is not None else "None", exception.__str__(), ) if (exception.errno == 13 ): # permission denied another connection open to this device. Log(__name__).error( "Cannot open connection, account has insufficient permissions." ) self._device = None return False
def hard_reset(self): """Manually drives the DTR line low to reset the device. :return: Tuple containing a status boolean and index 0 and a result-set dict at index 1. """ if not self.check_open(): return ComResult(False, exception="Connection must be open first.") Log(__name__).debug("Resetting the device using the DTR line") self._device.dtr = not self._device.dtr sleep(0.2) self._device.dtr = not self._device.dtr return ComResult(True)
def temp_build_dir(lib_name, build_path=None): if build_path is None: Log.warn("Building in tmp directory") folder = tempfile.mkdtemp(prefix='cpy-') else: Log.info("Building at {}".format(build_path)) assert os.path.exists(build_path), "Build path must exist!" folder = build_path targ = cmake.Target(lib_name, ['test.cc'], { 'Boost': '1.45.0', 'PythonLibs': '2.7', 'Eigen3': None }, executable=False) cmake_file = cmake.CMake('.', python=True) cmake_file.add_target(targ) formatting.put_file(folder, 'CMakeLists.txt', cmake_file.text) build_folder = os.path.join(folder, 'build') os.mkdir(build_folder) return folder
def execute_instruction(self, address, payload): """Builds and executes a new packet. :param address: An 8 bit unsigned integer of the UOS subsystem targeted by the instruction. :param payload: A tuple containing the uint8 parameters of the UOS instruction. :return: Tuple containing a status boolean and index 0 and a result-set dict at index 1. """ if not self.check_open(): return ComResult(False, exception="Connection must be opened first.") packet = self.get_npc_packet(to_addr=address, from_addr=0, payload=payload) Log(__name__).debug("packet formed %s", packet) try: # Send the packet. num_bytes = self._device.write(packet) self._device.flush() Log(__name__).debug("Sent %s bytes of data", num_bytes) except serial.SerialException as exception: return ComResult(False, exception=str(exception)) finally: self._device.reset_output_buffer() return ComResult(num_bytes == len(packet))
def create_app(testing: bool, base_path: Path, static_path: Path): """Creates the flask app and registers all addons.""" app = Flask( __name__, static_folder=static_path.__str__(), template_folder=static_path.joinpath(Path("templates/")).__str__(), ) csrf.init_app(app) app.config["TESTING"] = testing app.config["SECRET_KEY"] = secrets.token_urlsafe(32) register_database(app) register_blueprints(app) register_logs(DEBUG, base_path=base_path) Log(__name__).debug("Static resolved to %s", static_path.__str__()) return app
def read_response(self, expect_packets: int, timeout_s: float): """Reads ACK and response packets from the serial device. :param expect_packets: How many packets including ACK to expect. :param timeout_s: The maximum time this function will wait for data. :return: ComResult object. """ response_object = ComResult(False) if not self.check_open(): return response_object start_ns = time_ns() packet = [] byte_index = -1 # tracks the byte position index of the current packet packet_index = 0 # tracks the packet number being received 0 = ACK try: while (timeout_s * 1000000000) > time_ns( ) - start_ns and byte_index > -2: # read until packet or timeout num_bytes = self._device.in_waiting for _ in range(num_bytes): byte_in = self._device.read(1) byte_index, packet = self.decode_and_capture( byte_index, byte_in, packet) if byte_index == -2: if packet_index == 0: response_object.ack_packet = packet else: response_object.rx_packets.append(packet) packet_index += 1 if expect_packets == packet_index: break byte_index = -1 packet = [] byte_index += 1 sleep(0.05) # Don't churn CPU cycles waiting for data Log(__name__).debug("Packet received %s", packet) if expect_packets != packet_index or len( packet) < 6 or byte_index != -2: response_object.rx_packets.append(packet) response_object.exception = "did not receive all the expected data" return response_object response_object.status = True return response_object except serial.SerialException as exception: response_object.exception = str(exception) return response_object
def __init__( self, identity: Union[str, Device], address: str, interface: Interface = Interface.USB, **kwargs, ): """Instantiate a UOS device instance for communication. :param identity: Specify the type of device, this must exist in the device dictionary. :param address: Compliant connection string for identifying the device and interface. :param interface: Set the type of interface to use for communication. :param kwargs: Additional optional connection parameters as defined in documentation. """ self.identity = identity self.address = address if isinstance(identity, str): self.device = get_device_definition(identity) else: self.device = identity self.__kwargs = kwargs if self.device is None: raise UOSUnsupportedError( f"'{self.identity}' does not have a valid look up table" ) if interface == Interface.USB and Interface.USB in self.device.interfaces: self.__device_interface = NPCSerialPort( address, baudrate=self.device.aux_params["default_baudrate"], ) elif interface == Interface.STUB and Interface.STUB in self.device.interfaces: self.__device_interface = NPCStub( connection=address, errored=(kwargs["errored"] if "errored" in kwargs else False), ) else: raise UOSCommunicationError( f"Could not correctly open a connection to {self.identity} - {self.address}" ) if not self.is_lazy(): # eager connections open when they are created self.open() Log(__name__).debug("Created device %s", self.__device_interface.__repr__())
def check_required_args( possible_arguments: dict[APIargument], arguments_found: dict, add_device: bool = False, ) -> (APIresult, dict): """Adds common arguments and vets user request against parameters.""" if add_device: possible_arguments = dict( possible_arguments, **{ "identity": APIargument(True, str, None), "address": APIargument(True, str, None), }, ) for argument in possible_arguments: if argument not in arguments_found and possible_arguments[ argument].required: return ( APIresult( False, f"Required argument '{argument}' not found in request."), possible_arguments, ) try: if argument in arguments_found: possible_arguments[argument].arg_value = possible_arguments[ argument].arg_type(arguments_found[argument]) except ValueError: return ( APIresult( False, f"Expected '{argument}' to have type {possible_arguments[argument].arg_type} " f"not {type(arguments_found[argument])}.", ), possible_arguments, ) Log(__name__).debug("API arguments %s", possible_arguments.__str__()) return APIresult(True), possible_arguments
def load(self, url): if self.child: self.unload() context = LoaderContext() context.securityDomain = SecurityDomain.currentDomain context.applicationDomain = ApplicationDomain() context.checkPolicyFile = True req = URLRequest() req.url = url loader = Loader() for k, v in items(self.params): loader.contentLoaderInfo.parameters[k] = v self.addChild(loader) try: loader.load(req, context) except SecurityError as e: Log.error(str(e)) Log.info("Trying different security domain, " "some functionality may be absent") Log.info("(It's ok if you are on local filesystem)") loader.load(req) self.child = loader loader.contentLoaderInfo.addEventListener( Event.COMPLETE, self._bindcontent)
"""Root class for starting the daemon/webapp.""" from logging import DEBUG from logging import getLogger as Log from os import environ from gevent.pywsgi import WSGIServer from uosinterface import base_dir from uosinterface import static_dir from uosinterface.hardware import register_logs as register_hardware_logs from uosinterface.util import configure_logs from uosinterface.webapp import create_app from uosinterface.webapp.dashboard import shutdown_server __flask_debug = environ.get("FLASK_DEBUG", "false") == "true" __host = environ.get("FLASK_HOST", "127.0.0.1") app = create_app(__flask_debug, base_path=base_dir, static_path=static_dir) register_hardware_logs(DEBUG, base_dir) configure_logs("server", DEBUG, base_dir) server = WSGIServer((__host, 5000), app, log=Log("server")) server.start() try: shutdown_server.wait() except KeyboardInterrupt: pass # allow exit via ctrl-C. server.stop()
def PingSystem(self, destination_id): toSend = Message('car123', 'mls', 'destination_id', '100', 'Status Update') Log.Parse_Message_To_Collection(toSend)
def ProcessMessage(self, recieved_message): Log.Parse_Message_To_Collection(recieved_message) SetLastHeardFrom(recieved_message.Return_Origin_ID()) if(recieved_message.Return_Payload()[:2:] == "HC"):
Purpose: To test the Logging class to ensure that a message can come in, and the message will be stored in the correct collections. ''' #Import the message and log class from Message import Message from logging import Log #Create several messages to test with message01 = [ Message("CAR12345", "mls", "clc", 100, "SUR:HC"), Message("CAR12345", "brk", "mls", 100, "HC1: NOT SLOWING DOWN"), Message("CAR12345", "clc", "mls", 100, "HC3: TEMP 50F HUMIDITY 6%"), Message("CAR12345", "brk", "lis", 100, "SUR: BRK LT ON"), Message("CAR12345", "ccs", "dts", 100, "SUR: DR 23%") ] logging = Log() #Drop all of the previous collections to ensure new features of logging are working logging.bobby_drop_tables() #Go through all messages for i in message01: logging.Parse_Message_To_Collection(i) #Puts message at index i in MongoDB logging.RetrieveAll() print("Success")
def main(): """ Voorbeelden: 1. Initialiseer een database: python bagextract.py -H localhost -d bag -U postgres -W postgres -c 2. Importeer een extract in de database: python bagextract.py -H localhost -d bag -U postgres -W postgres -e 9999STA01052011-000002.xml of python bagextract.py -H localhost -d bag -U postgres -W postgres -e 9999STA01052011.zip Importeer gemeente_woonplaats informatie van het kadaster http://www.kadaster.nl/bag/docs/BAG_Overzicht_aangesloten_gemeenten.zip python bagextract.py -H localhost -d bag -U postgres -W postgres -e BAG_Overzicht_aangesloten_gemeenten.zip Theoretisch is het mogelijk de hele bag in te lezen vanuit de "hoofd" zip, maar dit is nog niet getest op geheugen-problemen. """ parser = ArgParser( description= 'bag-extract, commandline tool voor het extraheren en inlezen van BAG bestanden', epilog= "Configureer de database in extract.conf of geef eigen versie van extract.conf via -f of geef parameters via commando regel expliciet op" ) parser.add_argument( '-c', '--dbinit', action='store_true', help= 'verwijdert (DROP TABLE) alle tabellen en maakt (CREATE TABLE) nieuwe tabellen aan' ) parser.add_argument('-d', '--database', metavar='<naam>', help='geef naam van de database') parser.add_argument('-s', '--schema', metavar='<naam>', help='geef naam van het database schema') parser.add_argument( '-f', '--config', metavar='<bestand>', help='gebruik dit configuratiebestand i.p.v. extract.conf') parser.add_argument( '-q', '--query', metavar='<bestand>', help='voer database bewerkingen uit met opgegeven SQL bestand') parser.add_argument( '-e', '--extract', metavar='<naam>', help= 'importeert of muteert de database met gegeven BAG-bestand of -directory' ) parser.add_argument('-H', '--host', metavar='<hostnaam of -adres>', help='verbind met de database op deze host') parser.add_argument('-U', '--username', metavar='<naam>', help='verbind met database met deze gebruikersnaam') parser.add_argument('-p', '--port', metavar='<poort>', help='verbind met database naar deze poort') parser.add_argument('-W', '--password', metavar='<paswoord>', help='gebruikt dit wachtwoord voor database gebruiker') parser.add_argument( '-w', '--no-password', action='store_true', help='gebruik geen wachtwoord voor de database verbinding') parser.add_argument( '-v', '--verbose', action='store_true', help='toon uitgebreide informatie tijdens het verwerken') # Initialiseer args = parser.parse_args() # Initialize singleton Log object so we can use one global instance Log(args) # Init globale configuratie BAGConfig(args) # Database database = Database() # Print start time Log.log.time("Start") if args.dbinit: # Dumps all tables and recreates them db_script = os.path.realpath(BAGConfig.config.bagextract_home + '/db/script/bag-db.sql') Log.log.info("alle database tabellen weggooien en opnieuw aanmaken...") database.initialiseer(db_script) Log.log.info("Initieele data (bijv. gemeenten/provincies) inlezen...") myreader = BAGFileReader(BAGConfig.config.bagextract_home + '/db/data') myreader.process() Log.log.info("Views aanmaken...") db_script = os.path.realpath( BAGConfig.config.bagextract_home + '/db/script/bag-view-actueel-bestaand.sql') database.file_uitvoeren(db_script) elif args.extract: # Extracts any data from any source files/dirs/zips/xml/csv etc myreader = BAGFileReader(args.extract) myreader.process() elif args.query: # Voer willekeurig SQL script uit uit database = Database() database.file_uitvoeren(args.query) else: Log.log.fatal( "je geeft een niet-ondersteunde optie. Tip: probeer -h optie") # Print end time Log.log.time("End") sys.exit()
def easy_build(code, clean_up=True, build_path=None): path = temp_build_dir('my_test_lib', build_path) formatting.put_file(path, 'test.cc', code, True) Log.br() Log.note("Cmaking...") build_folder = os.path.join(path, 'build') cmake_output = cmake.cmake(path, build_folder) Log.note('CMake Output:') Log.br() print(cmake_output) Log.br() Log.note("Building...") make_output, success = cmake.make(build_folder) Log.br() if success: Log.note("Success! Make Output:") else: Log.error("ERROR: Make failed, output:") compilers.gcc.prettify_output(make_output) Log.br() # Clean up the build folder, now that the output has been generated if clean_up: Log.warn('Cleaning up build output...') shutil.rmtree(path)
def shutdown_database(exception=None): Log(__name__).debug("Shutting down database engine, %s", exception.__str__()) app.config["DATABASE"]["ENGINE"].dispose()
def __execute_instruction( self, function_name: str, volatility, instruction_data: InstructionArguments, retry: bool = True, ) -> ComResult: """Common functionality for execution of all UOS instructions. :param function_name: The name of the function in the OOL. :param volatility: How volatile should the command be, use constants in HardwareCOM. :param instruction_data: device_functions from the LUT, payload ect. :param retry: Allows the instruction to retry execution when fails. :return: ComResult object :raises: UOSUnsupportedError if function is not possible on the loaded device. """ if ( function_name not in self.device.functions_enabled or volatility not in self.device.functions_enabled[function_name] or ( instruction_data.check_pin is not None and instruction_data.check_pin not in self.device.get_compatible_pins(function_name) ) ): Log(__name__).debug( "Known functions %s", self.device.functions_enabled.keys().__str__() ) raise UOSUnsupportedError( f"{function_name}({volatility}) has not been implemented for {self.identity}" ) rx_response = ComResult(False) if self.is_lazy(): # Lazy loaded self.open() if ( instruction_data.device_function_lut[function_name][volatility] >= 0 ): # a normal instruction tx_response = self.__device_interface.execute_instruction( instruction_data.device_function_lut[function_name][volatility], instruction_data.payload, ) if tx_response.status: rx_response = self.__device_interface.read_response( instruction_data.expected_rx_packets, 2 ) if rx_response.status: # validate checksums on all packets for count in range(len(rx_response.rx_packets) + 1): current_packet = ( rx_response.ack_packet if count == 0 else rx_response.rx_packets[count - 1] ) computed_checksum = self.__device_interface.get_npc_checksum( current_packet[1:-2] ) Log(__name__).debug( "Calculated checksum %s must match rx %s", computed_checksum, current_packet[-2], ) rx_response.status = rx_response.status & ( computed_checksum == current_packet[-2] ) else: # run a special action rx_response = getattr(self.__device_interface, function_name)() if self.is_lazy(): # Lazy loaded self.close() if ( not rx_response.status and retry ): # allow one retry per instruction due to DTR resets return self.__execute_instruction( function_name, volatility, instruction_data, False ) return rx_response
def key(self, event): if self.visible: if event.keyCode == 192: # tilde self.hide() elif event.keyCode == 13: if event.shiftKey or (self.evaluator \ and self.evaluator.need_continue(self.inputlines)): self.inputlines.splice(self.cursor.y+1, 0, "") self.cursor.y += 1 self.cursor.x = 0 self.resize() else: code = self.inputlines.join('\n') if self.evaluator: self.evaluator.eval(self, self.inputlines) else: Log.info(code) self.history.push(code) self.history_index = -1 elif event.keyCode == 33: # pageup oldline = self.firstvisible if oldline < 0: self.firstvisible = max(0, self.lines.length - self.visible_lines*3/2) else: self.firstvisible = max(oldline - self.visible_lines/2, 0) if oldline != self.firstvisible: self.refresh() elif event.keyCode == 34: # pagedown oldline = self.firstvisible if oldline < 0: return self.firstvisible = oldline + self.visible_lines if self.firstvisible + self.visible_lines > self.lines.length: self.firstvisible = -1 if oldline != self.firstvisible: self.refresh() elif event.keyCode == 37: # left if self.cursor.x == 0: if self.inputlines.length > 1 and self.cursor.y: self.cursor.y -= 1 self.cursor.x = self.inputlines[self.cursor.y].length else: self.cursor.x -= 1 self.refreshinput() elif event.keyCode == 39: # right if self.cursor.x == self.inputlines[self.cursor.y].length: if self.inputlines.length > self.cursor.y+1: self.cursor.y += 1 self.cursor.x = 0 else: self.cursor.x += 1 self.refreshinput() elif event.keyCode == 38: # up if event.shiftKey: self.cursor.y = max(self.cursor.y-1, 0) else: if self.history_index < 0: self._storedlines = self.inputlines self.history_index = self.history.length if self.history_index > 0: self.inputlines = self.history[self.history_index-1]\ .split('\n') self.cursor = Point( self.inputlines[self.inputlines.length-1].length, self.inputlines.length-1) self.history_index -= 1 self.refreshinput() elif event.keyCode == 40: # down if event.shiftKey: self.cursor.y = min(self.cursor.y+1, self.inputlines.length-1) else: if self.history_index+1 < self.history.length: self.inputlines = self.history[self.history_index+1]\ .split('\n') self.history_index += 1 elif self._storedlines: self.inputlines = self._storedlines self.history_index = -1 del self._stored_lines self.cursor = Point( self.inputlines[self.inputlines.length-1].length, self.inputlines.length-1) self.refreshinput() elif event.keyCode == 0x08: #backspace if self.cursor.x: ln = self.inputlines[self.cursor.y] if self.cursor.x == ln.length: nln = ln.substr(0, ln.length-1) else: nln = ln.substr(0, self.cursor.x-1)+ln.substr(self.cursor.x) self.inputlines[self.cursor.y] = nln self.cursor.x -= 1 self.refreshinput() elif self.cursor.y: self.cursor.y -= 1 prevline = self.inputlines[self.cursor.y-1] self.cursor.x = prevline.length self.inputlines[self.cursor.y-1] \ = prevline + self.inputlines[self.cursor.y] self.resize() elif event.charCode >= 0x20: # all chars starting from space ln = self.inputlines[self.cursor.y] ch = String.fromCharCode(event.charCode) if self.cursor.x == ln.length: nln = ln+ch else: nln = ln.substr(0,self.cursor.x)+ch+ln.substr(self.cursor.x) self.inputlines[self.cursor.y] = nln self.cursor.x += 1 self.refreshinput() else: if event.keyCode == 192: # tilde self.show()