@@ -659,6 +659,45 @@ def add_dialog_proc(name, p, context = nil)
659659 render_dialog_changes ( changes , cursor_column )
660660 end
661661
662+ private def range_subtract ( base_ranges , subtract_ranges )
663+ points = [ ]
664+ base_ranges . each do |range |
665+ points << [ range . begin , 1 , 1 ]
666+ points << [ range . end , -1 , 1 ]
667+ end
668+ subtract_ranges . each do |range |
669+ points << [ range . begin , 1 , -1 ]
670+ points << [ range . end , -1 , -1 ]
671+ end
672+ ranges = [ ]
673+ base_count = 0
674+ subtract_count = 0
675+ open = false
676+ points . sort . each do |point , diff , mode |
677+ if mode == 1
678+ base_count += diff
679+ else
680+ subtract_count += diff
681+ end
682+ next if open == ( base_count > 0 && subtract_count == 0 )
683+ open = !open
684+ if open
685+ if ranges . last &.end === point
686+ ranges [ -1 ] = ( ranges . last . begin ...)
687+ else
688+ ranges << ( point ...)
689+ end
690+ else
691+ if ranges . last . begin === point
692+ ranges . pop
693+ else
694+ ranges [ -1 ] = ranges . last . begin ...point
695+ end
696+ end
697+ end
698+ ranges
699+ end
700+
662701 private def dialog_range ( dialog , dialog_y )
663702 x_range = dialog . column ...dialog . column + dialog . width
664703 y_range = dialog_y + dialog . vertical_offset ...dialog_y + dialog . vertical_offset + dialog . contents . size
@@ -687,24 +726,8 @@ def add_dialog_proc(name, p, context = nil)
687726 return if old_dialog_ranges . empty? && new_dialog_ranges . empty?
688727 ranges_to_restore = { }
689728 old_dialog_ranges . each do |y , old_x_ranges |
690- new_dialog_ranges [ y ] &.each do |new_x_range |
691- ranges = [ ]
692- old_x_ranges . each do |old_x_range |
693- next if new_x_range . cover? old_x_range
694- if new_x_range . end <= old_x_range . begin || old_x_range . end <= new_x_range . begin
695- ranges << old_x_range
696- elsif new_x_range . begin <= old_x_range . begin
697- ranges << ( new_x_range . end ...old_x_range . end )
698- elsif old_x_range . end <= new_x_range . end
699- ranges << ( old_x_range . begin ...new_x_range . begin )
700- else
701- ranges << ( old_x_range . begin ...new_x_range . begin )
702- ranges << ( new_x_range . end ...old_x_range . end )
703- end
704- end
705- old_x_ranges = ranges
706- end
707- ( ranges_to_restore [ y ] ||= [ ] ) . push ( *old_x_ranges ) unless old_x_ranges . empty?
729+ ranges = range_subtract ( old_x_ranges , new_dialog_ranges [ y ] || [ ] )
730+ ranges_to_restore [ y ] = ranges if ranges . any?
708731 end
709732
710733 if ranges_to_restore . any?
0 commit comments