void Navigator::Search() { sortitems.Check(sorting); int sc = scope.GetScroll(); String key = scope.GetKey(); String s = TrimBoth(~search); String search_name, search_nest; bool wholeclass = false; bool both = false; navigator_global = false; if(s.Find('.') >= 0) { Vector<String> h = Split((String)~search, '.'); if(*s.Last() == '.') search_nest = Join(h, "::"); else { search_name = h.Pop(); if(h.GetCount()) search_nest = Join(h, "::"); } wholeclass = *s == '.' && search_nest.GetCount(); } else { search_name = search_nest = ~search; both = true; } s = Join(Split(s, '.'), "::") + (s.EndsWith(".") ? "::" : ""); int lineno = StrInt(s); gitem.Clear(); nitem.Clear(); if(IsNull(theide->editfile)) return; int fileii = GetSourceFileIndex(theide->editfile); if(!IsNull(lineno)) { NavItem& m = nitem.Add(); m.type = "Go to line " + AsString(lineno); m.kind = KIND_LINE; m.line = lineno; gitem.Add(Null).Add(&m); } else if(IsNull(s) && !sorting) { const CppBase& b = CodeBase(); for(int i = 0; i < b.GetCount(); i++) { String nest = b.GetKey(i); const Array<CppItem>& ci = b[i]; for(int j = 0; j < ci.GetCount(); j++) { const CppItem& m = ci[j]; if(m.file == fileii) { NavItem& n = nitem.Add(); n.Set(m); n.nest = nest; n.decl_line = m.line; n.decl_file = m.file; n.decl = !m.impl; NavLine& l = n.linefo.Add(); l.impl = m.impl; l.file = m.file; l.line = m.line; } } } Sort(nitem, FieldRelation(&NavItem::line, StdLess<int>())); NavGroup(true); } else { navigator_global = true; const CppBase& b = CodeBase(); String usearch_nest = ToUpper(search_nest); String usearch_name = ToUpper(search_name); ArrayMap<String, NavItem> imap; bool local = sorting && IsNull(s); VectorMap<String, int> nest_pass; for(int pass = -1; pass < 2; pass++) { for(int i = 0; i < b.GetCount(); i++) { String nest = b.GetKey(i); bool foundnest = (wholeclass ? pass < 0 ? false : pass ? ToUpper(nest) == usearch_nest : nest == search_nest : pass < 0 ? nest == search_nest : (pass ? ToUpper(nest).Find(usearch_nest) >= 0 : nest.StartsWith(search_nest))) && nest.Find('@') < 0; if(local || foundnest || both) { const Array<CppItem>& ci = b[i]; for(int j = 0; j < ci.GetCount(); j++) { const CppItem& m = ci[j]; if(local ? m.file == fileii : m.uname.Find('@') < 0 && (pass < 0 ? m.name == search_name : pass ? m.uname.Find(usearch_name) >= 0 : m.name.StartsWith(search_name)) || both && foundnest) { String key = nest + '\1' + m.qitem; int q = nest_pass.Find(nest); int p = pass; if(q < 0) // We do not want classes to be split based on pass nest_pass.Add(nest, pass); else p = nest_pass[q]; q = imap.Find(key); if(q < 0) { NavItem& ni = imap.Add(key); ni.Set(m); ni.nest = nest; ni.decl_line = ni.line; ni.decl_file = ni.file; ni.decl = !ni.impl; ni.pass = p; NavLine& l = ni.linefo.Add(); l.impl = m.impl; l.file = m.file; l.line = m.line; } else { NavItem& mm = imap[q]; if(!m.impl && (!mm.decl || CombineCompare(mm.decl_file, m.file)(mm.decl_line, m.line) < 0)) { mm.decl = true; mm.decl_line = m.line; mm.decl_file = m.file; mm.natural = m.natural; } NavLine& l = mm.linefo.Add(); l.impl = m.impl; l.file = m.file; l.line = m.line; } } } } } } nitem = imap.PickValues(); NavGroup(false); SortByKey(gitem); Vector<String> keys = gitem.PickKeys(); Vector<Vector<NavItem *> > values = gitem.PickValues(); IndexSort(keys, values); for(int i = 0; i < keys.GetCount(); i++) keys[i].Remove(0); VectorMap<String, Vector<NavItem *> > h(pick(keys), pick(values)); gitem = pick(h); for(int i = 0; i < gitem.GetCount(); i++) Sort(gitem[i], sorting ? SortByNames : SortByLines); } scope.Clear(); scope.Add(Null); Index<String> done; for(int i = 0; i < gitem.GetCount(); i++) { String s = gitem.GetKey(i); if(done.Find(s) < 0) { done.Add(s); scope.Add(s); } } scope.ScrollTo(sc); if(!navigator_global || !scope.FindSetCursor(key)) scope.GoBegin(); }