node/lib/metasm/metasm/gui/dasm_graph.rb
def pattern_layout_complex(groups)
		order = order_graph(groups)
		uniq = nil
		if groups.sort_by { |g| order[g] }.find { |g|
			next if g.to.length <= 1
			# list all nodes reachable for every 'to'
			reach = g.to.map { |t| list_reachable(t) }
			# list all nodes reachable only from a single 'to'
			uniq = []
			reach.each_with_index { |r, i|
				# take all nodes reachable from there ...
				u = uniq[i] = r.dup
				u.delete_if { |k, v| k.content.empty? }	# ignore previous layout_complex artifacts
				reach.each_with_index { |rr, ii|
					next if i == ii
					# ... and delete nodes reachable from anywhere else
					rr.each_key { |k| u.delete k }
				}
			}
			uniq.delete_if { |u| u.length <= 1 }
			!uniq.empty?
		}
			# now layout every uniq subgroup independently
			uniq.each { |u|
				subgroups = groups.find_all { |g| u[g] }

				# isolate subgroup from external links
				# change all external links into a single empty box
				newtop = Box.new(nil, [])
				newtop.x = -8 ; newtop.y = -9
				newtop.w = 16 ; newtop.h = 18
				newbot = Box.new(nil, [])
				newbot.x = -8 ; newbot.y = -9
				newbot.w = 16 ; newbot.h = 18
				hadfrom = [] ; hadto = []
				subgroups.each { |g|
					g.to.dup.each { |t|
						next if u[t]
						newbot.from |= [g]
						g.to.delete t
						hadto << t
						g.to |= [newbot]
					}
					g.from.dup.each { |f|
						next if u[f]
						newtop.to |= [g]
						g.from.delete f
						hadfrom << f
						g.from |= [newtop]
					}
				}
				subgroups << newtop << newbot

				# subgroup layout
				auto_arrange_step(subgroups) while subgroups.length > 1
				newg = subgroups[0]

				# patch 'groups'
				idx = groups.index { |g| u[g] }
				groups.delete_if { |g| u[g] }
				groups[idx, 0] = [newg]

				# restore external links & fix xrefs
				hadfrom.uniq.each { |f|
					f.to.delete_if { |t| u[t] }
					f.to |= [newg]
					newg.from |= [f]
				}
				hadto.uniq.each { |t|
					t.from.delete_if { |f| u[f] }
					t.from |= [newg]
					newg.to |= [t]
				}
			}

			true
		end
	end
# one box, has a text, an id, and a list of other boxes to/from
one box, has a text, an id, and a list of other boxes to/from
one box has a text an id and a list of other boxes to / from
def pattern_layout_complex(groups)
		order = order_graph(groups)
		uniq = nil
		if groups.sort_by { |g| order[g] }.find { |g|
			next if g.to.length <= 1
			reach = g.to.map { |t| list_reachable(t) }
			uniq = []
			reach.each_with_index { |r, i|
				u = uniq[i] = r.dup
				u.delete_if { |k, v| k.content.empty? }	
				reach.each_with_index { |rr, ii|
					next if i == ii
					rr.each_key { |k| u.delete k }
				}
			}
			uniq.delete_if { |u| u.length <= 1 }
			!uniq.empty?
		}
			uniq.each { |u|
				subgroups = groups.find_all { |g| u[g] }
				newtop = Box.new(nil, [])
				newtop.x = -8 ; newtop.y = -9
				newtop.w = 16 ; newtop.h = 18
				newbot = Box.new(nil, [])
				newbot.x = -8 ; newbot.y = -9
				newbot.w = 16 ; newbot.h = 18
				hadfrom = [] ; hadto = []
				subgroups.each { |g|
					g.to.dup.each { |t|
						next if u[t]
						newbot.from |= [g]
						g.to.delete t
						hadto << t
						g.to |= [newbot]
					}
					g.from.dup.each { |f|
						next if u[f]
						newtop.to |= [g]
						g.from.delete f
						hadfrom << f
						g.from |= [newtop]
					}
				}
				subgroups << newtop << newbot
				auto_arrange_step(subgroups) while subgroups.length > 1
				newg = subgroups[0]
				idx = groups.index { |g| u[g] }
				groups.delete_if { |g| u[g] }
				groups[idx, 0] = [newg]
				hadfrom.uniq.each { |f|
					f.to.delete_if { |t| u[t] }
					f.to |= [newg]
					newg.from |= [f]
				}
				hadto.uniq.each { |t|
					t.from.delete_if { |f| u[f] }
					t.from |= [newg]
					newg.to |= [t]
				}
			}
			true
		end
	end
def pattern_layout_complex ( groups ) order = order_graph ( groups ) uniq = nil if groups . sort_by { | g | order [ g ] } . find { | g | next if g . to . length <= 1 reach = g . to . map { | t | list_reachable ( t ) } uniq = [ ] reach . each_with_index { | r , i | u = uniq [ i ] = r . dup u . delete_if { | k , v | k . content . empty? } reach . each_with_index { | rr , ii | next if i == ii rr . each_key { | k | u . delete k } } } uniq . delete_if { | u | u . length <= 1 } ! uniq . empty? } uniq . each { | u | subgroups = groups . find_all { | g | u [ g ] } newtop = Box . new ( nil , [ ] ) newtop . x = - 8 ; newtop . y = - 9 newtop . w = 16 ; newtop . h = 18 newbot = Box . new ( nil , [ ] ) newbot . x = - 8 ; newbot . y = - 9 newbot . w = 16 ; newbot . h = 18 hadfrom = [ ] ; hadto = [ ] subgroups . each { | g | g . to . dup . each { | t | next if u [ t ] newbot . from |= [ g ] g . to . delete t hadto << t g . to |= [ newbot ] } g . from . dup . each { | f | next if u [ f ] newtop . to |= [ g ] g . from . delete f hadfrom << f g . from |= [ newtop ] } } subgroups << newtop << newbot auto_arrange_step ( subgroups ) while subgroups . length > 1 newg = subgroups [ 0 ] idx = groups . index { | g | u [ g ] } groups . delete_if { | g | u [ g ] } groups [ idx , 0 ] = [ newg ] hadfrom . uniq . each { | f | f . to . delete_if { | t | u [ t ] } f . to |= [ newg ] newg . from |= [ f ] } hadto . uniq . each { | t | t . from . delete_if { | f | u [ f ] } t . from |= [ newg ] newg . to |= [ t ] } } true end end
one box, has a text, an id, and a list of other boxes to/from
one box has a text an id and a list of other boxes to / from
# list all nodes reachable for every 'to' # list all nodes reachable only from a single 'to' # take all nodes reachable from there ... # ignore previous layout_complex artifacts # ... and delete nodes reachable from anywhere else # now layout every uniq subgroup independently # isolate subgroup from external links # change all external links into a single empty box # subgroup layout # patch 'groups' # restore external links & fix xrefs
groups