1 #include "ide.h"
2
3 #define LTIMING(x) // RTIMING(x)
4
FormatNest(String nest)5 String FormatNest(String nest)
6 {
7 int q = nest.Find("@");
8 if(q >= 0) {
9 nest.Trim(q);
10 nest << "[anonymous]";
11 }
12 return nest;
13 }
14
CharFilterNavigator(int c)15 int CharFilterNavigator(int c)
16 {
17 return c == ':' ? '.' : IsAlNum(c) || c == '_' || c == '.' ? c : 0;
18 }
19
PaintTeXt(Draw & w,int & x,int y,const String & text,Font font,Color ink)20 void PaintTeXt(Draw& w, int& x, int y, const String& text, Font font, Color ink)
21 {
22 static int maxascent = MaxAscent(StdFont());
23 Size sz = GetTextSize(text, font);
24 w.DrawText(x, y + maxascent - font.GetAscent(), text, font, ink);
25 x += sz.cx;
26 }
27
DrawFileName0(Draw & w,const Rect & r,const String & h,Color ink,int x)28 int DrawFileName0(Draw& w, const Rect& r, const String& h, Color ink, int x)
29 {
30 if(h.GetCount() == 0)
31 return 0;
32 int q = h.Find("\xff");
33 String ns;
34 String fn = h;
35 if(q >= 0) {
36 ns = h.Mid(0, q) + ' ';
37 fn = h.Mid(q + 1);
38 }
39 String s = GetFileName(GetFileFolder(h)) + "/";
40 x += r.left;
41 if(ns.GetCount()) {
42 PaintTeXt(w, x, r.top, ns, StdFont().Bold(), ink);
43 PaintTeXt(w, x, r.top, "(", StdFont(), ink);
44 }
45 PaintTeXt(w, x, r.top, s, StdFont(), ink);
46 s = GetFileName(h);
47 PaintTeXt(w, x, r.top, s, StdFont().Bold(), ink);
48 if(ns.GetCount())
49 PaintTeXt(w, x, r.top, ")", StdFont(), ink);
50 return x - r.left;
51 }
52
GetDrawFileNameSize(const String & h)53 Size GetDrawFileNameSize(const String& h)
54 {
55 NilDraw w;
56 return Size(DrawFileName0(w, Size(999999, 999999), h, Null, 0), StdFont().Bold().GetCy());
57 }
58
DrawFileName(Draw & w,const Rect & r,const String & h,Color ink)59 void DrawFileName(Draw& w, const Rect& r, const String& h, Color ink)
60 {
61 DrawFileName0(w, r, h, ink, min(r.GetWidth() - GetDrawFileNameSize(h).cx, 0));
62 }
63
PaintFileName(Draw & w,const Rect & r,String h,Color ink)64 int PaintFileName(Draw& w, const Rect& r, String h, Color ink)
65 {
66 if(*h == '\xff')
67 h.Remove(0, 1);
68 return DrawFileName0(w, r, h, ink, 0);
69 }
70
Navigator()71 Navigator::Navigator()
72 : navidisplay(litem)
73 {
74 scope_display.navigator = this;
75 scope.NoHeader();
76 scope.AddColumn().SetDisplay(scope_display);
77 scope.NoWantFocus();
78 scope.WhenSel = THISBACK(Scope);
79 scope.WhenLeftDouble = THISBACK(ScopeDblClk);
80
81 list.NoHeader();
82 list.AddRowNumColumn().SetDisplay(navidisplay);
83 list.SetLineCy(max(16, GetStdFontCy()));
84 list.NoWantFocus();
85 list.WhenLeftClick = THISBACK(NavigatorClick);
86 list.WhenSel = THISBACK(SyncNavLines);
87 list.WhenLineEnabled = THISBACK(ListLineEnabled);
88
89 navlines.NoHeader().NoWantFocus();
90 navlines.WhenLeftClick = THISBACK(GoToNavLine);
91 navlines.AddColumn().SetDisplay(Single<LineDisplay>());
92
93 search <<= THISBACK(TriggerSearch);
94 search.SetFilter(CharFilterNavigator);
95 search.WhenEnter = THISBACK(NavigatorEnter);
96
97 sortitems.Image(BrowserImg::Sort());
98 sortitems <<= THISBACK(NaviSort);
99 sorting = false;
100
101 dlgmode = false;
102 }
103
SyncCursor()104 void Navigator::SyncCursor()
105 {
106 String k = "(" + GetKeyDesc(IdeKeys::AK_GOTO().key[0]) + ") ";
107 search.NullText("Symbol/lineno " + k);
108 search.Tip(IsNull(search) ? String() : "Clear " + k);
109
110 if(!navigating && theide->editfile.GetCount()) {
111 navlines.KillCursor();
112 int q = linefo.Find(GetSourceFileIndex(theide->editfile));
113 if(q < 0)
114 return;
115 navigating = true;
116 SortedVectorMap<int, int>& m = linefo[q];
117 q = m.FindUpperBound(GetCurrentLine() + 1) - 1;
118 if(q >= 0 && q < m.GetCount())
119 list.SetCursor(m[q]);
120 navigating = false;
121 }
122 SyncLines();
123 if(scope.IsCursor())
124 scope.RefreshRow(scope.GetCursor());
125 }
126
SyncLines()127 void Navigator::SyncLines()
128 {
129 if(IsNull(theide->editfile) || navigating)
130 return;
131 int ln = GetCurrentLine() + 1;
132 int fi = GetSourceFileIndex(theide->editfile);
133 int q = -1;
134 for(int i = 0; i < navlines.GetCount(); i++) {
135 const NavLine& l = navlines.Get(i, 0).To<NavLine>();
136 if(l.file == fi && l.line <= ln && i < navlines.GetCount())
137 q = i;
138 }
139 if(dlgmode)
140 navlines.GoBegin();
141 else
142 if(q >= 0)
143 navlines.SetCursor(q);
144 }
145
SyncNavLines()146 void Navigator::SyncNavLines()
147 {
148 int sc = navlines.GetScroll();
149 navlines.Clear();
150 int ii = list.GetCursor();
151 if(ii >= 0 && ii < litem.GetCount()) {
152 Vector<NavLine> l = GetNavLines(*litem[ii]);
153 for(int i = 0; i < l.GetCount(); i++) {
154 String p = GetSourceFilePath(l[i].file);
155 navlines.Add(RawToValue(l[i]));
156 }
157 navlines.ScrollTo(sc);
158 SyncLines();
159 }
160 }
161
DoPaint(Draw & w,const Rect & r,const Value & q,Color ink,Color paper,dword style,int x) const162 int Navigator::LineDisplay::DoPaint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style, int x) const
163 {
164 w.DrawRect(r, paper);
165 const NavLine& l = q.To<NavLine>();
166 x += r.left;
167 String p = GetSourceFilePath(l.file);
168 int y = r.top + (r.GetHeight() - StdFont().GetCy()) / 2;
169 PaintTeXt(w, x, y, GetFileName(GetFileFolder(p)) + "/", StdFont(), ink);
170 PaintTeXt(w, x, y, GetFileName(p), StdFont().Bold(), ink);
171 PaintTeXt(w, x, y, " (", StdFont(), ink);
172 PaintTeXt(w, x, y, AsString(l.line), StdFont().Bold(), ink);
173 PaintTeXt(w, x, y, ")", StdFont(), ink);
174 return x - r.left;
175 }
176
Paint(Draw & w,const Rect & r,const Value & q,Color ink,Color paper,dword style) const177 void Navigator::LineDisplay::Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
178 {
179 DoPaint(w, r, q, ink, paper, style, min(r.GetWidth() - GetStdSize(q).cx, 0));
180 }
181
GetStdSize(const Value & q) const182 Size Navigator::LineDisplay::GetStdSize(const Value& q) const
183 {
184 NilDraw w;
185 return Size(DoPaint(w, Size(999999, 999999), q, White(), White(), 0, 0), StdFont().Bold().GetCy());
186 }
187
GoToNavLine()188 void Navigator::GoToNavLine()
189 {
190 if(dlgmode)
191 return;
192 int ii = navlines.GetClickPos().y;
193 if(ii >= 0 && ii < navlines.GetCount() && theide) {
194 const NavLine& l = navlines.Get(ii, 0).To<NavLine>();
195 theide->GotoPos(GetSourceFilePath(l.file), l.line);
196 }
197 }
198
operator <(const NavLine & b) const199 bool Navigator::NavLine::operator<(const NavLine& b) const
200 {
201 String p1 = GetSourceFilePath(file);
202 String p2 = GetSourceFilePath(b.file);
203 return CombineCompare/*(!impl, !b.impl)*/
204 (GetFileExt(p2), GetFileExt(p1)) // .h > .c
205 (GetFileName(p1), GetFileName(p2))
206 (p1, p2)
207 (line, b.line) < 0;
208 }
209
GetNavLines(const NavItem & m)210 Vector<Navigator::NavLine> Navigator::GetNavLines(const NavItem& m)
211 {
212 CodeBaseLock __;
213 Vector<NavLine> l;
214 int q = CodeBase().Find(m.nest);
215 if(q < 0 || IsNull(m.qitem))
216 return l;
217 const Array<CppItem>& a = CodeBase()[q];
218 for(int i = 0; i < a.GetCount(); i++) {
219 const CppItem& mm = a[i];
220 if(mm.qitem == m.qitem) {
221 NavLine& nl = l.Add();
222 nl.impl = mm.impl;
223 nl.file = mm.file;
224 nl.line = mm.line;
225 }
226 }
227 Sort(l);
228 return l;
229 }
230
Navigate()231 void Navigator::Navigate()
232 {
233 if(navigating)
234 return;
235 navigating = true;
236 int ii = list.GetCursor();
237 if(theide && ii >= 0 && ii < litem.GetCount()) {
238 int ln = GetCurrentLine() + 1;
239 const NavItem& m = *litem[ii];
240 if(m.kind == KIND_LINE || IsNull(search)) {
241 theide->GotoPos(Null, m.line);
242 if(m.kind == KIND_LINE) { // Go to line - restore file view
243 search.Clear();
244 Search();
245 navigating = false;
246 }
247 SyncCursor();
248 }
249 else
250 if(m.kind == KIND_SRCFILE) {
251 theide->AddHistory();
252 theide->EditFile(m.ptype);
253 theide->AddHistory();
254 }
255 else {
256 Vector<NavLine> l = GetNavLines(m);
257 int q = l.GetCount() - 1;
258 for(int i = 0; i < l.GetCount(); i++)
259 if(GetSourceFilePath(l[i].file) == NormalizeSourcePath(theide->editfile) && l[i].line == ln) {
260 q = (i + l.GetCount() + 1) % l.GetCount();
261 break;
262 }
263 if(q >= 0 && q < l.GetCount()) {
264 String path = GetSourceFilePath(l[q].file);
265 if(!theide->GotoDesignerFile(path, m.nest, m.name, l[q].line))
266 theide->GotoPos(path, l[q].line);
267 }
268 }
269 }
270 navigating = false;
271 }
272
ScopeDblClk()273 void Navigator::ScopeDblClk()
274 {
275 if(!scope.IsCursor())
276 return;
277 String h = scope.GetKey();
278 if((byte)*h == 0xff)
279 theide->GotoPos(h.Mid(1), 1);
280 else {
281 list.GoBegin();
282 Navigate();
283 }
284 }
285
NavigatorClick()286 void Navigator::NavigatorClick()
287 {
288 if(dlgmode)
289 return;
290 int q = list.GetClickPos().y;
291 if(q >= 0 && q < list.GetCount())
292 Navigate();
293 }
294
NavigatorEnter()295 void Navigator::NavigatorEnter()
296 {
297 if(list.GetCount()) {
298 list.GoBegin();
299 Navigate();
300 }
301 }
302
ToggleNavigator()303 void Ide::ToggleNavigator()
304 {
305 editor.Navigator(!editor.navigator);
306 }
307
SearchCode()308 void Ide::SearchCode()
309 {
310 if(!editor.navigator)
311 editor.Navigator(true);
312 if(!IsNull(~editor.search)) {
313 editor.search.Clear();
314 editor.Search();
315 editor.SetFocus();
316 }
317 else {
318 String h = editor.GetWord();
319 if(h.GetCount()) {
320 editor.search <<= h;
321 editor.search.SelectAll();
322 editor.Search();
323 }
324 editor.search.SetFocus();
325 }
326 }
327
SwitchHeader()328 void Ide::SwitchHeader() {
329 int c = filelist.GetCursor();
330 if(c < 0) return;
331 String currfile = filelist[c];
332 const char *ext = GetFileExtPos(currfile);
333 if(!stricmp(ext, ".h") || !stricmp(ext, ".hpp")
334 || !stricmp(ext, ".lay") || !stricmp(ext, ".iml")) {
335 int f = filelist.Find(ForceExt(currfile, ".cpp"));
336 if(f < 0) f = filelist.Find(ForceExt(currfile, ".c"));
337 if(f < 0) f = filelist.Find(ForceExt(currfile, ".cc"));
338 if(f >= 0) filelist.SetCursor(f);
339 }
340 }
341
Set(const CppItem & m)342 void Navigator::NavItem::Set(const CppItem& m)
343 {
344 qitem = m.qitem;
345 name = m.name;
346 uname = m.uname;
347 natural = m.natural;
348 type = m.type;
349 pname = m.pname;
350 ptype = m.ptype;
351 tname = m.tname;
352 ctname = m.ctname;
353 access = m.access;
354 kind = m.kind;
355 at = m.at;
356 line = m.line;
357 file = m.file;
358 impl = m.impl;
359 pass = false;
360 }
361
PaintBackground(Draw & w,const Rect & r,const Value & q,Color ink,Color paper,dword style) const362 void Navigator::NavigatorDisplay::PaintBackground(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
363 {
364 int ii = q;
365 if(ii < 0 || ii >= item.GetCount())
366 return;
367 const NavItem& m = *item[ii];
368 bool focuscursor = (style & (FOCUS|CURSOR)) == (FOCUS|CURSOR) || (style & SELECT);
369 if(findarg(m.kind, KIND_FILE, KIND_NEST) >= 0)
370 w.DrawRect(r, focuscursor ? paper : m.kind == KIND_NEST ? Blend(SColorMark, SColorPaper, 220)
371 : SColorFace);
372 else
373 w.DrawRect(r, paper);
374 }
375
376
DoPaint(Draw & w,const Rect & r,const Value & q,Color ink,Color paper,dword style) const377 int Navigator::NavigatorDisplay::DoPaint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
378 {
379 int ii = q;
380 if(ii < 0 || ii >= item.GetCount())
381 return 0;
382 const NavItem& m = *item[ii];
383 bool focuscursor = (style & (FOCUS|CURSOR)) == (FOCUS|CURSOR) || (style & SELECT);
384
385 int x = r.left;
386 int ry = r.top + r.GetHeight() / 2;
387 int y = ry - Draw::GetStdFontCy() / 2;
388
389 if(findarg(m.kind, KIND_FILE, KIND_NEST) >= 0) {
390 w.DrawRect(r, focuscursor ? paper : m.kind == KIND_NEST ? Blend(SColorMark, SColorPaper, 220)
391 : SColorFace);
392 if(findarg(m.kind, KIND_FILE) >= 0)
393 return PaintFileName(w, r, m.type, ink);
394 String h = FormatNest(m.type);
395 w.DrawText(x, y, h, StdFont().Bold(), ink);
396 return GetTextSize(h, StdFont().Bold()).cx;
397 }
398
399 w.DrawRect(r, paper);
400
401 if(m.kind == KIND_SRCFILE)
402 return PaintFileName(w, r, m.type, ink);
403
404 if(m.kind == KIND_LINE) {
405 w.DrawText(x, y, m.type, StdFont().Bold(), ink);
406 return GetTextSize(m.type, StdFont().Bold()).cx;
407 }
408
409 PaintCppItemImage(w, x, ry, m.access, m.kind, focuscursor);
410
411 x += Zx(15);
412 Vector<ItemTextPart> n = ParseItemNatural(m.name, m.natural, m.ptype, m.pname, m.type,
413 m.tname, m.ctname, ~m.natural + m.at);
414 int starti = 0;
415 for(int i = 0; i < n.GetCount(); i++)
416 if(n[i].type == ITEM_NAME) {
417 starti = i;
418 break;
419 }
420 PaintText(w, x, y, m.natural, n, starti, n.GetCount(), focuscursor, ink, false);
421 if(starti) {
422 const char *h = " : ";
423 w.DrawText(x, y, h, BrowserFont(), SColorText);
424 x += GetTextSize(h, BrowserFont()).cx;
425 }
426 PaintText(w, x, y, m.natural, n, 0, starti, focuscursor, ink, false);
427 return x;
428 }
429
Paint(Draw & w,const Rect & r,const Value & q,Color ink,Color paper,dword style) const430 void Navigator::NavigatorDisplay::Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
431 {
432 DoPaint(w, r, q, ink, paper, style);
433 }
434
GetStdSize(const Value & q) const435 Size Navigator::NavigatorDisplay::GetStdSize(const Value& q) const
436 {
437 NilDraw w;
438 return Size(DoPaint(w, Size(999999, 999999), q, White(), White(), 0), Draw::GetStdFontCy());
439 }
440
TriggerSearch()441 void Navigator::TriggerSearch()
442 {
443 search_trigger.KillSet(100, THISBACK(Search));
444 }
445
NavGroup(bool local)446 void Navigator::NavGroup(bool local)
447 {
448 CodeBaseLock __;
449 for(int i = 0; i < nitem.GetCount(); i++) {
450 NavItem& m = nitem[i];
451 String g = m.nest;
452 if(m.kind == TYPEDEF)
453 g.Trim(max(g.ReverseFind("::"), 0));
454 if(IsNull(g) || CodeBase().namespaces.Find(m.nest) >= 0) {
455 if(g.GetCount()) // We want to show the namespace
456 g << '\xff';
457 else
458 g.Clear();
459 g << GetSourceFilePath(m.decl_file);
460 g = '\xff' + g;
461 }
462 if(!local)
463 g = (char)(m.pass + 10) + g;
464 if(local)
465 if(gitem.GetCount() && gitem.TopKey() == g)
466 gitem.Top().Add(&m);
467 else
468 gitem.Add(g).Add(&m);
469 else
470 gitem.GetAdd(g).Add(&m);
471 }
472 }
473
474 force_inline
SortByLines(const NavItem * a,const NavItem * b)475 bool Navigator::SortByLines(const NavItem *a, const NavItem *b)
476 {
477 return CombineCompare(a->decl_file, b->decl_file)(a->decl_line, b->decl_line) < 0;
478 }
479
480 force_inline
SortByNames(const NavItem * a,const NavItem * b)481 bool Navigator::SortByNames(const NavItem *a, const NavItem *b)
482 {
483 return CombineCompare(a->name, b->name)(a->qitem, b->qitem) < 0;
484 }
485
Search()486 void Navigator::Search()
487 {
488 CodeBaseLock __;
489 sortitems.Check(sorting);
490 int sc = scope.GetScroll();
491 String key = scope.GetKey();
492 String s = TrimBoth(~search);
493 String search_name, search_nest;
494 bool wholeclass = false;
495 bool both = false;
496 navigator_global = false;
497 if(s.Find('.') >= 0) {
498 Vector<String> h = Split((String)~search, '.');
499 if(*s.Last() == '.')
500 search_nest = Join(h, "::");
501 else {
502 search_name = h.Pop();
503 if(h.GetCount())
504 search_nest = Join(h, "::");
505 }
506 wholeclass = *s == '.' && search_nest.GetCount();
507 }
508 else {
509 search_name = search_nest = ~search;
510 both = true;
511 }
512 s = Join(Split(s, '.'), "::") + (s.EndsWith(".") ? "::" : "");
513 int lineno = StrInt(s);
514 gitem.Clear();
515 nitem.Clear();
516 if(IsNull(theide->editfile))
517 return;
518 int fileii = GetSourceFileIndex(theide->editfile);
519 if(!IsNull(lineno)) {
520 NavItem& m = nitem.Add();
521 m.type = "Go to line " + AsString(lineno);
522 m.kind = KIND_LINE;
523 m.line = lineno;
524 gitem.Add(Null).Add(&m);
525 }
526 else
527 if(IsNull(s) && !sorting) {
528 const CppBase& b = CodeBase();
529 bool sch = GetFileExt(theide->editfile) == ".sch";
530 for(int i = 0; i < b.GetCount(); i++) {
531 String nest = b.GetKey(i);
532 const Array<CppItem>& ci = b[i];
533 for(int j = 0; j < ci.GetCount(); j++) {
534 const CppItem& m = ci[j];
535 if(m.file == fileii && (!sch || !m.IsData() || m.type != "SqlId")) {
536 NavItem& n = nitem.Add();
537 n.Set(m);
538 n.nest = nest;
539 n.decl_line = m.line;
540 n.decl_file = m.file;
541 n.decl = !m.impl;
542 NavLine& l = n.linefo.Add();
543 l.impl = m.impl;
544 l.file = m.file;
545 l.line = m.line;
546 }
547 }
548 }
549 Sort(nitem, FieldRelation(&NavItem::line, StdLess<int>()));
550 NavGroup(true);
551 }
552 else {
553 navigator_global = true;
554 const CppBase& b = CodeBase();
555 String usearch_nest = ToUpper(search_nest);
556 String usearch_name = ToUpper(search_name);
557 ArrayMap<String, NavItem> imap;
558 bool local = sorting && IsNull(s);
559 VectorMap<String, int> nest_pass;
560 for(int pass = -1; pass < 2; pass++) {
561 for(int i = 0; i < b.GetCount(); i++) {
562 String nest = b.GetKey(i);
563 bool foundnest = (wholeclass ? pass < 0 ? false :
564 pass ? ToUpper(nest) == usearch_nest
565 : nest == search_nest
566 : pass < 0 ? nest == search_nest :
567 (pass ? ToUpper(nest).Find(usearch_nest) >= 0
568 : nest.StartsWith(search_nest)))
569 && nest.Find('@') < 0;
570 if(local || foundnest || both) {
571 const Array<CppItem>& ci = b[i];
572 for(int j = 0; j < ci.GetCount(); j++) {
573 const CppItem& m = ci[j];
574 if(local ? m.file == fileii
575 : m.uname.Find('@') < 0 && (pass < 0 ? m.name == search_name :
576 pass ? m.uname.Find(usearch_name) >= 0
577 : m.name.StartsWith(search_name))
578 || both && foundnest) {
579 String key = nest + '\1' + m.qitem;
580 int q = nest_pass.Find(nest);
581 int p = pass;
582 if(q < 0) // We do not want classes to be split based on pass
583 nest_pass.Add(nest, pass);
584 else
585 p = nest_pass[q];
586 q = imap.Find(key);
587 if(q < 0) {
588 NavItem& ni = imap.Add(key);
589 ni.Set(m);
590 ni.nest = nest;
591 ni.decl_line = ni.line;
592 ni.decl_file = ni.file;
593 ni.decl = !ni.impl;
594 ni.pass = p;
595 NavLine& l = ni.linefo.Add();
596 l.impl = m.impl;
597 l.file = m.file;
598 l.line = m.line;
599 }
600 else {
601 NavItem& mm = imap[q];
602 if(!m.impl &&
603 (!mm.decl
604 || CombineCompare(mm.decl_file, m.file)(mm.decl_line, m.line) < 0)) {
605 mm.decl = true;
606 mm.decl_line = m.line;
607 mm.decl_file = m.file;
608 mm.natural = m.natural;
609 }
610 NavLine& l = mm.linefo.Add();
611 l.impl = m.impl;
612 l.file = m.file;
613 l.line = m.line;
614 }
615 }
616 }
617 }
618 }
619 }
620 nitem = imap.PickValues();
621 NavGroup(false);
622 SortByKey(gitem);
623 Vector<String> keys = gitem.PickKeys();
624 Vector<Vector<NavItem *> > values = gitem.PickValues();
625 IndexSort(keys, values);
626 for(int i = 0; i < keys.GetCount(); i++)
627 keys[i].Remove(0);
628 VectorMap<String, Vector<NavItem *> > h(pick(keys), pick(values));
629 gitem = pick(h);
630 for(int i = 0; i < gitem.GetCount(); i++)
631 Sort(gitem[i], sorting ? SortByNames : SortByLines);
632 const Workspace& wspc = GetIdeWorkspace();
633 String s = ToUpper(TrimBoth(~search));
634 for(int i = 0; i < wspc.GetCount(); i++) {
635 const Package& p = wspc.GetPackage(i);
636 for(int j = 0; j < p.GetCount(); j++) {
637 if(!p[j].separator && ToUpper(p[j]).Find(s) >= 0) {
638 NavItem& m = nitem.Add();
639 m.kind = KIND_SRCFILE;
640 m.type = wspc[i] + "/" + p[j];
641 m.ptype = SourcePath(wspc[i], p[j]);
642 m.line = 0;
643 gitem.GetAdd("<files>").Add(&m);
644 }
645 }
646 }
647 }
648 scope.Clear();
649 scope.Add(Null);
650 Index<String> done;
651 for(int i = 0; i < gitem.GetCount(); i++) {
652 String s = gitem.GetKey(i);
653 if(done.Find(s) < 0) {
654 done.Add(s);
655 scope.Add(s);
656 }
657 }
658 scope.ScrollTo(sc);
659 if(!navigator_global || !scope.FindSetCursor(key))
660 scope.GoBegin();
661 }
662
DoPaint(Draw & w,const Rect & r,const Value & q,Color ink,Color paper,dword style) const663 int Navigator::ScopeDisplay::DoPaint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
664 {
665 w.DrawRect(r, paper);
666 if(IsNull(q)) {
667 const char *txt = "* ";
668 int x = 0;
669 w.DrawText(r.left, r.top, txt, StdFont().Bold().Italic(),
670 style & CURSOR ? ink : HighlightSetup::GetHlStyle(HighlightSetup::INK_KEYWORD).color);
671 x += GetTextSize(txt, StdFont().Bold().Italic()).cx;
672 int ii = navigator->list.GetCursor();
673 if(ii >= 0 && ii < navigator->litem.GetCount()) {
674 const NavItem& m = *navigator->litem[ii];
675 String txt = m.nest;
676 if(IsCppCode(m.kind))
677 txt << "::" << m.name;
678 w.DrawText(r.left + x, r.top, txt, StdFont().Bold(), ink);
679 x += GetTextSize(txt, StdFont().Bold()).cx;
680 }
681 return x;
682 }
683 String h = q;
684 if(*h == '\xff')
685 return PaintFileName(w, r, h, ink);
686 else
687 h = FormatNest(h);
688 w.DrawText(r.left, r.top, h, StdFont(), ink);
689 return GetTextSize(h, StdFont()).cx;
690 }
691
Paint(Draw & w,const Rect & r,const Value & q,Color ink,Color paper,dword style) const692 void Navigator::ScopeDisplay::Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
693 {
694 DoPaint(w, r, q, ink, paper, style);
695 }
696
GetStdSize(const Value & q) const697 Size Navigator::ScopeDisplay::GetStdSize(const Value& q) const
698 {
699 NilDraw w;
700 return Size(DoPaint(w, Size(999999, 999999), q, White(), White(), 0), StdFont().Bold().GetCy());
701 }
702
Scope()703 void Navigator::Scope()
704 {
705 LTIMING("FINALIZE");
706 litem.Clear();
707 nest_item.Clear();
708 linefo.Clear();
709 bool all = scope.GetCursor() <= 0;
710 String sc = scope.GetKey();
711 for(int i = 0; i < gitem.GetCount(); i++) {
712 String grp = gitem.GetKey(i);
713 int kind = KIND_NEST;
714 if(*grp == '\xff')
715 kind = KIND_FILE;
716 if(all) {
717 NavItem& m = nest_item.Add();
718 m.kind = kind;
719 m.type = FormatNest(grp);
720 litem.Add(&m);
721 }
722 else
723 if(grp != sc)
724 continue;
725 const Vector<NavItem *>& ia = gitem[i];
726 for(int i = 0; i < ia.GetCount(); i++) {
727 NavItem *m = ia[i];
728 for(int j = 0; j < m->linefo.GetCount(); j++)
729 linefo.GetAdd(m->linefo[j].file).Add(m->linefo[j].line, litem.GetCount());
730 litem.Add(m);
731 }
732 }
733 list.Clear();
734 list.SetVirtualCount(litem.GetCount());
735 }
736
ListLineEnabled(int i,bool & b)737 void Navigator::ListLineEnabled(int i, bool& b)
738 {
739 if(i >= 0 && i < litem.GetCount()) {
740 int kind = litem[i]->kind;
741 if(findarg(kind, KIND_FILE, KIND_NEST) >= 0)
742 b = false;
743 }
744 }
745
NaviSort()746 void Navigator::NaviSort()
747 {
748 sorting = !sorting;
749 Search();
750 }
751