コード例 #1
0
    def export(self):
        """Export the data."""

        global active_thread
        self.view = self.window.active_view()
        if self.handshake != -1 and self.handshake == self.view.id():
            try:
                sublime.set_timeout(
                    lambda: sublime.status_message("Writing..."), 0)
                self.row = self.view.rowcol(self.view.size())[0] + 1
                self.hex_buffer = StringIO(
                    self.view.substr(sublime.Region(0, self.view.size())))
                self.thread = ThreadedWrite(self.hex_buffer, self.export_path,
                                            parse_view_data, self.row)
                self.thread.start()
                self.export_thread()
                active_thread = self.thread
            except Exception:
                print(str(traceback.format_exc()))
                error("Failed to export to " + self.export_path)
                self.reset()
                return

        else:
            error("Hex view is no longer in focus! File not saved.")
            self.reset()
コード例 #2
0
ファイル: hex_checksum.py プロジェクト: JPuge/HexViewer
 def run(self, hash_algorithm=None, panel=False):
     global active_thread
     if active_thread is not None and active_thread.is_alive():
         error("HexViewer is already checksumming a file!\nPlease run the abort command to stop the current checksum.")
     else:
         if not panel:
             self.get_checksum(hash_algorithm)
         else:
             self.window.show_quick_panel(VALID_HASH, self.select_checksum)
コード例 #3
0
    def run(self, hash_algorithm=None, panel=False):
        """Run command."""

        if active_thread is not None and active_thread.is_alive():
            error("HexViewer is already checksumming a file!\n"
                  "Please run the abort command to stop the current checksum.")
        else:
            if not panel:
                self.get_checksum(hash_algorithm)
            else:
                self.window.show_quick_panel(VALID_HASH, self.select_checksum)
コード例 #4
0
ファイル: hex_viewer.py プロジェクト: JPuge/HexViewer
 def discard_changes(self, value):
     if value.strip().lower() == "yes":
         if self.switch_type == "hex":
             view = sublime.active_window().active_view()
             if self.handshake == view.id():
                 view.set_scratch(True)
                 self.read_bin(self.file_name)
             else:
                 error("Target view is no longer in focus!  Hex view aborted.")
         else:
             self.read_file(self.file_name)
     self.reset()
コード例 #5
0
 def prepare_export(self, file_path):
     self.export_path = file_path
     if exists(dirname(file_path)):
         if exists(file_path):
             self.window.show_input_panel("Overwrite File? (yes | no):",
                                          "no", self.overwrite, None,
                                          self.reset)
         else:
             self.export()
     else:
         error("Directory does not exist!")
         self.export_path = self.view.settings().get("hex_viewer_file_name")
         self.export_panel()
コード例 #6
0
    def run(self, edit):
        viewer = hv_settings("external_viewer", {}).get("viewer", "")
        if not exists(viewer):
            error("Can't find the external hex viewer!")
            return

        file_name = self.view.file_name()
        if file_name is not None and exists(file_name):
            cmd = [viewer] + hv_settings("external_viewer", {}).get("args", [])

            for x in range(0, len(cmd)):
                cmd[x] = cmd[x].replace("${FILE}", file_name)

            subprocess.Popen(cmd)
コード例 #7
0
ファイル: hex_viewer.py プロジェクト: justintung/HexViewer
    def discard_changes(self, value):
        """Discard changes."""

        if value.strip().lower() == "yes":
            if self.switch_type == "hex":
                view = sublime.active_window().active_view()
                if self.handshake == view.id():
                    view.set_scratch(True)
                    self.read_bin(self.file_name)
                else:
                    error("Target view is no longer in focus!  Hex view aborted.")
            else:
                self.read_file(self.file_name)
        self.reset()
コード例 #8
0
ファイル: hex_viewer.py プロジェクト: JPuge/HexViewer
    def run(self, edit):
        viewer = hv_settings("external_viewer", {}).get("viewer", "")
        if not exists(viewer):
            error("Can't find the external hex viewer!")
            return

        file_name = self.view.file_name()
        if file_name is not None and exists(file_name):
            cmd = [viewer] + hv_settings("external_viewer", {}).get("args", [])

            for x in range(0, len(cmd)):
                cmd[x] = cmd[x].replace("${FILE}", file_name)

            subprocess.Popen(cmd)
コード例 #9
0
    def run(self):
        """Run command."""

        if active_thread is not None and active_thread.is_alive():
            error("HexViewer is already exporting a file!\nPlease run the abort command to stop the current export.")
        else:
            self.view = self.window.active_view()

            # Identify view
            if self.handshake != -1 and self.handshake == self.view.id():
                self.reset()
            self.handshake = self.view.id()

            self.export_path = self.view.settings().get("hex_viewer_file_name")

            self.export_panel()
コード例 #10
0
ファイル: hex_writer.py プロジェクト: kwembel/HexViewer
    def run(self):
        """Run command."""

        if active_thread is not None and active_thread.is_alive():
            error("HexViewer is already exporting a file!\nPlease run the abort command to stop the current export.")
        else:
            self.view = self.window.active_view()

            # Identify view
            if self.handshake != -1 and self.handshake == self.view.id():
                self.reset()
            self.handshake = self.view.id()

            self.export_path = self.view.settings().get("hex_viewer_file_name")

            self.export_panel()
コード例 #11
0
ファイル: hex_viewer.py プロジェクト: facelessuser/HexViewer
    def run(self, edit):
        """Run command."""

        viewer = common.hv_settings("external_viewer", {}).get("viewer", "")
        if not exists(viewer):
            error("Can't find the external hex viewer!")
            return

        file_name = self.window.extract_variables().get('file')

        if file_name is not None and exists(file_name):
            cmd = [viewer] + common.hv_settings("external_viewer", {}).get("args", [])

            for x in range(0, len(cmd)):
                cmd[x] = cmd[x].replace("${FILE}", file_name)

            subprocess.Popen(cmd)
コード例 #12
0
    def go_to_address(self, address):
        """Go to the specified address."""

        view = self.window.active_view()

        if self.handshake != -1 and self.handshake == view.id():
            # Adress offset for line
            address_offset = view.settings().get('hex_viewer_starting_address',
                                                 0)
            group_size = view.settings().get("hex_viewer_bits", None)
            bytes_wide = view.settings().get("hex_viewer_actual_bytes", None)
            if group_size is None and bytes_wide is None:
                return
            group_size = group_size / common.BITS_PER_BYTE

            # Go to address
            try:
                # Address wanted
                wanted = int(address, 16) - address_offset
                assert wanted >= 0, "Address does not exist!"
                # Calculate row
                row = int(wanted / (bytes_wide))
                # Byte offset into final row
                byte = wanted % (bytes_wide)
                #   Calculate byte number              Offset Char
                #
                #  wanted_char      byte
                # ------------ = -----------  => wanted_char + 11 = column
                #  total_chars   total_bytes
                #
                column = int((float(byte) / group_size) *
                             ((group_size) * 2 + 1)) + common.ADDRESS_OFFSET

                # Go to address and focus
                pt = view.text_point(row, column)
                view.sel().clear()
                view.sel().add(pt)
                view.show_at_center(pt)
                # Highlight
                self.window.run_command('hex_highlighter')
            except Exception:
                pass
        else:
            error("Hex view is no longer in focus! Find address canceled.")
        self.reset()
コード例 #13
0
ファイル: hex_viewer.py プロジェクト: JPuge/HexViewer
 def read_bin(self, file_name):
     global active_thread
     self.abort = False
     self.current_view = self.view
     self.thread = ReadBin(file_name, self.bytes_wide, self.group_size)
     file_size = float(self.thread.file_size) * 0.001
     max_file_size = float(hv_settings("max_file_size_kb", DEFAULT_MAX_FILE_SIZE))
     if file_size > max_file_size:
         viewer = hv_settings("external_viewer", {}).get("viewer", "")
         if exists(viewer):
             self.view.run_command("hex_external_viewer")
         else:
             error("File size exceeded HexViewers configured max limit of %s KB" % str(max_file_size))
         self.reset_thread()
     else:
         self.thread.start()
         self.handle_thread()
         active_thread = self.thread
コード例 #14
0
ファイル: hex_viewer.py プロジェクト: skeptycal/HexViewer
    def run(self, edit):
        """Run command."""

        viewer = common.hv_settings("external_viewer", {}).get("viewer", "")
        if not exists(viewer):
            error("Can't find the external hex viewer!")
            return

        file_name = self.window.extract_variables().get('file')

        if file_name is not None and exists(file_name):
            cmd = [viewer] + common.hv_settings("external_viewer", {}).get(
                "args", [])

            for x in range(0, len(cmd)):
                cmd[x] = cmd[x].replace("${FILE}", file_name)

            subprocess.Popen(cmd)
コード例 #15
0
ファイル: hex_writer.py プロジェクト: kwembel/HexViewer
    def prepare_export(self, file_path):
        """Prepare to export."""

        self.export_path = file_path
        if exists(dirname(file_path)):
            if exists(file_path):
                self.window.show_input_panel(
                    "Overwrite File? (yes | no):",
                    "no",
                    self.overwrite,
                    None,
                    self.reset
                )
            else:
                self.export()
        else:
            error("Directory does not exist!")
            self.export_path = self.view.settings().get("hex_viewer_file_name")
            self.export_panel()
コード例 #16
0
ファイル: hex_finder.py プロジェクト: kwembel/HexViewer
    def go_to_address(self, address):
        """Go to the specified address."""

        view = self.window.active_view()

        if self.handshake != -1 and self.handshake == view.id():
            # Adress offset for line
            address_offset = view.settings().get('hex_viewer_starting_address', 0)
            group_size = view.settings().get("hex_viewer_bits", None)
            bytes_wide = view.settings().get("hex_viewer_actual_bytes", None)
            if group_size is None and bytes_wide is None:
                return
            group_size = group_size / common.BITS_PER_BYTE

            # Go to address
            try:
                # Address wanted
                wanted = int(address, 16) - address_offset
                assert wanted >= 0, "Address does not exist!"
                # Calculate row
                row = int(wanted / (bytes_wide))
                # Byte offset into final row
                byte = wanted % (bytes_wide)
                #   Calculate byte number              Offset Char
                #
                #  wanted_char      byte
                # ------------ = -----------  => wanted_char + 11 = column
                #  total_chars   total_bytes
                #
                column = int((float(byte) / group_size) * ((group_size) * 2 + 1)) + common.ADDRESS_OFFSET

                # Go to address and focus
                pt = view.text_point(row, column)
                view.sel().clear()
                view.sel().add(pt)
                view.show_at_center(pt)
                # Highlight
                self.window.run_command('hex_highlighter')
            except Exception:
                pass
        else:
            error("Hex view is no longer in focus! Find address canceled.")
        self.reset()
コード例 #17
0
 def export_thread(self):
     ratio = float(self.thread.chunk) / float(self.thread.chunks)
     percent = int(ratio * 10)
     leftover = 10 - percent
     message = "[" + "-" * percent + ">" + "-" * leftover + (
         "] %3d%%" % int(ratio * 100)) + " chunks written"
     sublime.status_message(message)
     if not self.thread.is_alive():
         if self.thread.abort is True:
             notify("Write aborted!")
             sublime.set_timeout(lambda: self.reset_thread(), 500)
         else:
             status = self.thread.status
             self.reset_thread()
             if status == WRITE_GOOD:
                 sublime.set_timeout(lambda: self.finish_export(), 500)
             else:
                 error("Failed to export to " + self.export_path)
     else:
         sublime.set_timeout(lambda: self.export_thread(), 500)
コード例 #18
0
ファイル: hex_viewer.py プロジェクト: justintung/HexViewer
    def read_bin(self, file_name):
        """Read the binary file."""

        global active_thread
        self.abort = False
        self.current_view = self.view
        self.thread = ReadBin(file_name, self.bytes_wide, self.group_size, self.starting_address)
        file_size = float(self.thread.file_size) * 0.001
        max_file_size = float(common.hv_settings("max_file_size_kb", DEFAULT_MAX_FILE_SIZE))
        if file_size > max_file_size:
            viewer = common.hv_settings("external_viewer", {}).get("viewer", "")
            if exists(viewer):
                self.view.run_command("hex_external_viewer")
            else:
                error("File size exceeded HexViewers configured max limit of %s KB" % str(max_file_size))
            self.reset_thread()
        else:
            self.thread.start()
            self.handle_thread()
            active_thread = self.thread
コード例 #19
0
ファイル: hex_viewer.py プロジェクト: facelessuser/HexViewer
    def read_bin(self, file_name):
        """Read the binary file."""

        global active_thread
        self.abort = False
        self.thread = ReadBin(file_name, self.bytes_wide, self.group_size, self.starting_address)
        if self.is_file_too_big():
            viewer = common.hv_settings("external_viewer", {}).get("viewer", "")
            if exists(viewer):
                self.window.run_command("hex_external_viewer")
            else:
                error(
                    "File size exceeded HexViewers configured max limit of %s KB" % str(
                        common.hv_settings("max_file_size_kb", DEFAULT_MAX_FILE_SIZE)
                    )
                )
            self.reset_thread()
        else:
            self.thread.start()
            self.handle_thread()
            active_thread = self.thread
コード例 #20
0
ファイル: hex_writer.py プロジェクト: kwembel/HexViewer
    def export_thread(self):
        """Thread the export."""

        ratio = float(self.thread.chunk) / float(self.thread.chunks)
        percent = int(ratio * 10)
        leftover = 10 - percent
        message = "[" + "-" * percent + ">" + "-" * leftover + ("] %3d%%" % int(ratio * 100)) + " chunks written"
        sublime.status_message(message)
        if not self.thread.is_alive():
            if self.thread.abort is True:
                notify("Write aborted!")
                sublime.set_timeout(self.reset_thread, 500)
            else:
                status = self.thread.status
                self.reset_thread()
                if status == WRITE_GOOD:
                    sublime.set_timeout(self.finish_export, 500)
                else:
                    error("Failed to export to " + self.export_path)
        else:
            sublime.set_timeout(self.export_thread, 500)
コード例 #21
0
ファイル: hex_writer.py プロジェクト: kwembel/HexViewer
    def export(self):
        """Export the data."""

        global active_thread
        self.view = self.window.active_view()
        if self.handshake != -1 and self.handshake == self.view.id():
            try:
                sublime.set_timeout(lambda: sublime.status_message("Writing..."), 0)
                self.row = self.view.rowcol(self.view.size())[0] + 1
                self.hex_buffer = StringIO(self.view.substr(sublime.Region(0, self.view.size())))
                self.thread = ThreadedWrite(self.hex_buffer, self.export_path, parse_view_data, self.row)
                self.thread.start()
                self.export_thread()
                active_thread = self.thread
            except Exception:
                print(str(traceback.format_exc()))
                error("Failed to export to " + self.export_path)
                self.reset()
                return

        else:
            error("Hex view is no longer in focus! File not saved.")
            self.reset()
コード例 #22
0
ファイル: hex_viewer.py プロジェクト: justintung/HexViewer
    def run(self, bits=None, byte_array=None, starting_address=0):
        """Run the command."""

        self.starting_address = starting_address
        if active_thread is not None and active_thread.is_alive():
            error(
                "HexViewer is already converting a file!\n"
                "Please run the abort command to stop the current conversion."
            )
            return
        # If thread is active cancel thread
        if self.thread is not None and self.thread.is_alive():
            self.abort_hex_load()
            return

        # Init Buffer
        file_name = self.buffer_init(bits, byte_array)

        # Identify view
        if self.handshake != -1 and self.handshake == self.view.id():
            self.reset()
        self.handshake = self.view.id()

        if file_name is not None and exists(file_name):
            # Decide whether to read in as a binary file or a traditional file
            if self.view.settings().has("hex_viewer_file_name"):
                self.view_type = "hex"
                if common.is_hex_dirty(self.view):
                    self.file_name = file_name
                    if bits is None and byte_array is None:
                        self.switch_type = "file"
                    else:
                        self.switch_type = "hex"
                    self.discard_panel()
                else:
                    if bits is None and byte_array is None:
                        # Switch back to traditional output
                        self.read_file(file_name)
                    else:
                        # Reload hex with new settings
                        self.read_bin(file_name)
            else:
                # We are going to swap out the current file for hex output
                # So as not to clutter the screen.  Changes need to be saved
                # Or they will be lost
                if self.view.is_dirty():
                    self.file_name = file_name
                    self.switch_type = "hex"
                    self.discard_panel()
                else:
                    # Switch to hex output
                    self.read_bin(file_name)
        else:
            if file_name is None:
                error("View does not exist on disk!")
            else:
                error("%s does not exist on disk!" % basename(file_name))
コード例 #23
0
ファイル: hex_editor.py プロジェクト: niedfelj/HexViewer
    def apply_edit(self, value):
        """Apply edits."""

        edits = ""
        self.view = self.window.active_view()
        # Is this the same view as earlier?
        if self.handshake != -1 and self.handshake == self.view.id():
            total_chars = self.total_bytes * 2
            selection = self.line["selection"].replace(" ", "")

            # Transform string if provided
            if re.match("^s\:", value) is not None:
                edits = hexlify(value[2:len(value)].encode("ascii")).decode("ascii")
            else:
                edits = value.replace(" ", "").lower()

            # See if change occured and if changes are valid
            if len(edits) != total_chars:
                self.edit_panel(value, "Unexpected # of bytes!")
                return
            elif re.match("[\da-f]{" + str(total_chars) + "}", edits) is None:
                self.edit_panel(value, "Invalid data!")
                return
            elif selection != edits:
                # Get previous dirty markers before modifying buffer
                regions = self.view.get_regions("hex_edit")

                # Construct old and new data for diffs
                edits = self.line["data1"] + edits + self.line["data2"]
                original = self.line["data1"] + selection + self.line["data2"]

                # Initialize
                ascii_str = " :"
                start = 0
                ascii_start_pos = self.ascii_pos
                hex_start_pos = self.line["range"].begin() + common.ADDRESS_OFFSET
                end = len(edits)
                count = 1
                change_start = None

                # Reconstruct line
                l_buffer = self.line["address"]
                while start < end:
                    byte_end = start + 2
                    value = edits[start:byte_end]

                    # Diff data and mark changed bytes
                    if value != original[start:byte_end]:
                        if change_start is None:
                            change_start = [hex_start_pos, ascii_start_pos]
                            # Check if group end
                            if count == self.group_size:
                                regions.append(sublime.Region(change_start[0], hex_start_pos + 2))
                                change_start[0] = None
                        else:
                            # Check if after group end
                            if change_start[0] is None:
                                change_start[0] = hex_start_pos
                            # Check if group end
                            if count == self.group_size:
                                regions.append(sublime.Region(change_start[0], hex_start_pos + 2))
                                change_start[0] = None
                    elif change_start is not None:
                        if self.view.score_selector(hex_start_pos - 1, 'raw.nibble.lower'):
                            if change_start[0] is not None:
                                regions.append(sublime.Region(change_start[0], hex_start_pos))
                        else:
                            if change_start[0] is not None:
                                regions.append(sublime.Region(change_start[0], hex_start_pos - 1))
                        regions.append(sublime.Region(change_start[1], ascii_start_pos))
                        change_start = None

                    # Write bytes and add space and at group region end
                    l_buffer += value
                    if count == self.group_size:
                        l_buffer += " "
                        hex_start_pos += 1
                        count = 0

                    # Copy valid printible ascii chars over or substitute with "."
                    dec = unpack("=B", unhexlify(value))[0]
                    ascii_str += chr(dec) if dec in range(32, 127) else "."
                    start += 2
                    count += 1
                    hex_start_pos += 2
                    ascii_start_pos += 1

                # Check for end of line case for highlight
                if change_start is not None:
                    if change_start[0] is not None:
                        regions.append(sublime.Region(change_start[0], hex_start_pos))
                    regions.append(sublime.Region(change_start[1], ascii_start_pos))
                    change_start = None

                # Append ascii chars to line accounting for missing bytes in line
                delta = int(self.bytes_wide) - len(edits) / 2
                group_space = int(delta / self.group_size) + (1 if delta % self.group_size else 0)
                l_buffer += " " * int(group_space + delta * 2) + ascii_str

                # Apply buffer edit
                self.view.sel().clear()
                self.view.set_read_only(False)
                HexEditGlobal.bfr = l_buffer
                HexEditGlobal.region = self.line["range"]
                self.view.run_command("hex_edit_apply")
                HexEditGlobal.clear()
                self.view.set_read_only(True)
                self.view.sel().add(sublime.Region(self.start_pos, self.end_pos))

                # Underline if required
                if self.highlight_style == sublime.DRAW_EMPTY_AS_OVERWRITE:
                    regions = common.underline(regions)

                # Highlight changed bytes
                self.view.add_regions(
                    "hex_edit",
                    regions,
                    self.highlight_scope,
                    self.highlight_icon,
                    self.highlight_style
                )

                # Update selection
                self.window.run_command('hex_highlighter')
        else:
            error("Hex view is no longer in focus! Edit Failed.")
        # Clean up
        self.reset()
コード例 #24
0
    def apply_edit(self, value):
        """Apply edits."""

        edits = ""
        self.view = self.window.active_view()
        # Is this the same view as earlier?
        if self.handshake != -1 and self.handshake == self.view.id():
            total_chars = self.total_bytes * 2
            selection = self.line["selection"].replace(" ", "")

            # Transform string if provided
            if re.match("^s\:", value) is not None:
                edits = hexlify(
                    value[2:len(value)].encode("ascii")).decode("ascii")
            else:
                edits = value.replace(" ", "").lower()

            # See if change occured and if changes are valid
            if len(edits) != total_chars:
                self.edit_panel(value, "Unexpected # of bytes!")
                return
            elif re.match("[\da-f]{" + str(total_chars) + "}", edits) is None:
                self.edit_panel(value, "Invalid data!")
                return
            elif selection != edits:
                # Get previous dirty markers before modifying buffer
                regions = self.view.get_regions("hex_edit")

                # Construct old and new data for diffs
                edits = self.line["data1"] + edits + self.line["data2"]
                original = self.line["data1"] + selection + self.line["data2"]

                # Initialize
                ascii_str = " :"
                start = 0
                ascii_start_pos = self.ascii_pos
                hex_start_pos = self.line["range"].begin(
                ) + common.ADDRESS_OFFSET
                end = len(edits)
                count = 1
                change_start = None

                # Reconstruct line
                l_buffer = self.line["address"]
                while start < end:
                    byte_end = start + 2
                    value = edits[start:byte_end]

                    # Diff data and mark changed bytes
                    if value != original[start:byte_end]:
                        if change_start is None:
                            change_start = [hex_start_pos, ascii_start_pos]
                            # Check if group end
                            if count == self.group_size:
                                regions.append(
                                    sublime.Region(change_start[0],
                                                   hex_start_pos + 2))
                                change_start[0] = None
                        else:
                            # Check if after group end
                            if change_start[0] is None:
                                change_start[0] = hex_start_pos
                            # Check if group end
                            if count == self.group_size:
                                regions.append(
                                    sublime.Region(change_start[0],
                                                   hex_start_pos + 2))
                                change_start[0] = None
                    elif change_start is not None:
                        if self.view.score_selector(hex_start_pos - 1,
                                                    'raw.nibble.lower'):
                            if change_start[0] is not None:
                                regions.append(
                                    sublime.Region(change_start[0],
                                                   hex_start_pos))
                        else:
                            if change_start[0] is not None:
                                regions.append(
                                    sublime.Region(change_start[0],
                                                   hex_start_pos - 1))
                        regions.append(
                            sublime.Region(change_start[1], ascii_start_pos))
                        change_start = None

                    # Write bytes and add space and at group region end
                    l_buffer += value
                    if count == self.group_size:
                        l_buffer += " "
                        hex_start_pos += 1
                        count = 0

                    # Copy valid printible ascii chars over or substitute with "."
                    dec = unpack("=B", unhexlify(value))[0]
                    ascii_str += chr(dec) if dec in range(32, 127) else "."
                    start += 2
                    count += 1
                    hex_start_pos += 2
                    ascii_start_pos += 1

                # Check for end of line case for highlight
                if change_start is not None:
                    if change_start[0] is not None:
                        regions.append(
                            sublime.Region(change_start[0], hex_start_pos))
                    regions.append(
                        sublime.Region(change_start[1], ascii_start_pos))
                    change_start = None

                # Append ascii chars to line accounting for missing bytes in line
                delta = int(self.bytes_wide) - len(edits) / 2
                group_space = int(delta / self.group_size) + (
                    1 if delta % self.group_size else 0)
                l_buffer += " " * int(group_space + delta * 2) + ascii_str

                # Apply buffer edit
                self.view.sel().clear()
                self.view.set_read_only(False)
                HexEditGlobal.bfr = l_buffer
                HexEditGlobal.region = self.line["range"]
                self.view.run_command("hex_edit_apply")
                HexEditGlobal.clear()
                self.view.set_read_only(True)
                self.view.sel().add(
                    sublime.Region(self.start_pos, self.end_pos))

                # Underline if required
                if self.highlight_style == sublime.DRAW_EMPTY_AS_OVERWRITE:
                    regions = common.underline(regions)

                # Highlight changed bytes
                self.view.add_regions("hex_edit", regions,
                                      self.highlight_scope,
                                      self.highlight_icon,
                                      self.highlight_style)

                # Update selection
                self.window.run_command('hex_highlighter')
        else:
            error("Hex view is no longer in focus! Edit Failed.")
        # Clean up
        self.reset()