def switch_to_new_op_marks(cls, b: GtkSource.Buffer, ssb_filename: str):
     textiter: Gtk.TextIter = b.get_start_iter().copy()
     # TODO: This is probably pretty slow
     while textiter.forward_char():
         old_marks_at_pos = [
             m for m in textiter.get_marks() if m.get_name()
             and m.get_name().startswith(f'opcode_<<<{ssb_filename}>>>_')
         ]
         new_marks_at_pos = [
             m for m in textiter.get_marks() if m.get_name() and
             m.get_name().startswith(f'TMP_opcode_<<<{ssb_filename}>>>_')
         ]
         for m in old_marks_at_pos:
             b.delete_mark(m)
         for m in new_marks_at_pos:
             name = m.get_name()
             # Maybe by chance an old mark with this name still exists elsewhere, remove it.
             om = b.get_mark(name[4:])
             if om is not None:
                 b.delete_mark(om)
             # Move by deleting and re-creating.
             match = MARK_PATTERN_TMP.match(m.get_name())
             if match.group(3):
                 b.create_mark(
                     f'opcode_<<<{str(match.group(1))}>>>_{int(match.group(2))}_{match.group(3)}',
                     textiter)
             else:
                 b.create_mark(
                     f'opcode_<<<{str(match.group(1))}>>>_{int(match.group(2))}',
                     textiter)
             b.delete_mark(m)
 def create_opcode_mark(cls, b: GtkSource.Buffer, ssb_filename: str,
                        offset: int, line: int, col: int, is_tmp: bool,
                        is_for_macro_call: bool):
     textiter = b.get_iter_at_line_offset(line, col)
     tmp_prefix = 'TMP_' if is_tmp else ''
     macro_call_suffix = '_call' if is_for_macro_call else ''
     b.create_mark(
         f'{tmp_prefix}opcode_<<<{ssb_filename}>>>_{offset}{macro_call_suffix}',
         textiter)