mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
269 lines
5.9 KiB
C++
269 lines
5.9 KiB
C++
#include "ide.h"
|
|
|
|
#define LLOG(x) // DLOG(x)
|
|
|
|
struct GotoDlg : public WithGotoLayout<TopWindow> {
|
|
bool global;
|
|
Array<CppItemInfo> item;
|
|
Index<String> type;
|
|
CppBase lbase;
|
|
CppBase *gbase;
|
|
|
|
void SyncList();
|
|
int GetLine();
|
|
void SyncOk();
|
|
|
|
void Serialize(Stream& s);
|
|
|
|
typedef GotoDlg CLASSNAME;
|
|
|
|
GotoDlg(const String& s);
|
|
};
|
|
|
|
void GotoDlg::SyncList()
|
|
{
|
|
list.Clear();
|
|
String n = ~target;
|
|
int typei = Null;
|
|
String scope = Null;
|
|
Vector<String> h = Split(n, ':');
|
|
if(n[0] == ':') {
|
|
if(h.GetCount() > 1 && *n.Last() != ':') {
|
|
n = h.Top();
|
|
h.Drop();
|
|
}
|
|
else
|
|
n.Clear();
|
|
scope = Join(h, "::");
|
|
}
|
|
else
|
|
if(h.GetCount() > 1 || h.GetCount() == 1 && *n.Last() == ':') {
|
|
if(h.GetCount() > 1 && *n.Last() != ':') {
|
|
n = h.Top();
|
|
h.Drop();
|
|
}
|
|
else
|
|
n.Clear();
|
|
typei = type.Find(Join(h, "::"));
|
|
if(typei < 0)
|
|
typei = -1;
|
|
}
|
|
if(IsDigit(*n))
|
|
n.Clear();
|
|
Index<String> nc;
|
|
for(int ci = 0; ci < (n.GetCount() ? 2 : 1); ci++)
|
|
for(int i = 0; i < item.GetCount(); i++) {
|
|
const CppItemInfo& f = item[i];
|
|
int q = memcmp(n, f.name, n.GetLength());
|
|
if((n.GetLength() == 0 ||
|
|
(ci ? q && memcmp_i(n, f.name, n.GetLength()) == 0 : q == 0)) &&
|
|
(IsNull(typei) || typei == f.typei) &&
|
|
(IsNull(scope) || scope == f.scope)) {
|
|
list.Add(f.scope, RawToValue(f), f.item, f.line, GetCppFile(f.file), f.scope);
|
|
nc.FindAdd(f.scope);
|
|
}
|
|
}
|
|
list.HeaderTab(0).SetText(Format("Scope (%d)", nc.GetCount()));
|
|
list.HeaderTab(1).SetText(Format("Symbol (%d)", list.GetCount()));
|
|
SyncOk();
|
|
}
|
|
|
|
int GotoDlg::GetLine()
|
|
{
|
|
if(list.IsCursor() && list.HasFocus())
|
|
return list.Get(3);
|
|
String s = ~target;
|
|
if(IsDigit(s[0]))
|
|
return atoi(s);
|
|
if(list.IsCursor())
|
|
return list.Get(3);
|
|
if(list.GetCount())
|
|
return list.Get(0, 3);
|
|
return -1;
|
|
}
|
|
|
|
void GotoDlg::SyncOk()
|
|
{
|
|
ok.Enable(GetLine() >= 0);
|
|
}
|
|
|
|
int GotoFilter(int c)
|
|
{
|
|
return IsDigit(c) || IsAlpha(c) || c == '_' || c == ':' ? c : c == '.' ? ':' : 0;
|
|
}
|
|
|
|
void GotoDlg::Serialize(Stream& s)
|
|
{
|
|
SerializePlacement(s);
|
|
list.SerializeHeader(s);
|
|
}
|
|
|
|
struct CppItemInfoSortLine {
|
|
bool operator()(const CppItemInfo& a, const CppItemInfo& b) const {
|
|
return a.line < b.line;
|
|
}
|
|
};
|
|
|
|
struct CppItemInfoSortGlobal {
|
|
bool operator()(const CppItemInfo& a, const CppItemInfo& b) const {
|
|
return CombineCompare(a.scope, b.scope)
|
|
(GetCppFile(a.file), GetCppFile(b.file))
|
|
(a.line, b.line) < 0;
|
|
}
|
|
};
|
|
|
|
GotoDlg::GotoDlg(const String& s)
|
|
{
|
|
global = IsNull(s);
|
|
if(!global) {
|
|
StringStream ss(s);
|
|
Parser parser;
|
|
parser.Do(ss, IgnoreList(), lbase, Null, CNULL);
|
|
}
|
|
CtrlLayoutOKCancel(*this, IsNull(s) ? "Go to global" : "Go to line or symbol");
|
|
CppBase& base = IsNull(s) ? CodeBase() : lbase;
|
|
gbase = &base;
|
|
for(int i = 0; i < base.GetCount(); i++) {
|
|
Array<CppItem>& n = base[i];
|
|
for(int j = 0; j < n.GetCount(); j++) {
|
|
const CppItem& m = n[j];
|
|
CppItemInfo mf;
|
|
(CppItem&)mf = n[j];
|
|
mf.scope = base.GetKey(i);
|
|
mf.virt = false;
|
|
mf.access = m.impl ? (int)WITHBODY : (int)PUBLIC;
|
|
mf.item = global ? String().Cat() << GetFileName(GetCppFile(m.file)) << " (" << m.line << ')'
|
|
: AsString(m.line);
|
|
mf.typei = 0;
|
|
item.Add(mf);
|
|
}
|
|
}
|
|
if(global)
|
|
Sort(item, CppItemInfoSortGlobal());
|
|
else
|
|
Sort(item, CppItemInfoSortLine());
|
|
target.SetFilter(GotoFilter);
|
|
target <<= THISBACK(SyncList);
|
|
list.AddColumn("Nesting");
|
|
list.AddColumn().SetDisplay(Single<CppItemInfoDisplay>());
|
|
list.AddColumn(global ? "Position" : "Line");
|
|
list.SetLineCy(BrowserFont().Info().GetHeight() + 3);
|
|
if(global)
|
|
list.ColumnWidths("181 466 112");
|
|
else
|
|
list.ColumnWidths("174 516 37");
|
|
list.WhenCursor = THISBACK(SyncOk);
|
|
list.WhenLeftDouble = Breaker(IDOK);
|
|
list.EvenRowColor();
|
|
SyncList();
|
|
ActiveFocus(target);
|
|
Sizeable().Zoomable();
|
|
Icon(IdeImg::Navigator());
|
|
}
|
|
|
|
INITBLOCK
|
|
{
|
|
RegisterGlobalConfig("IdeGoto");
|
|
RegisterGlobalConfig("IdeGotoGlobal");
|
|
}
|
|
|
|
void Ide::Goto()
|
|
{
|
|
if(designer || editor.GetLength() == 0)
|
|
return;
|
|
GotoDlg dlg(~editor);
|
|
LoadFromGlobal(dlg, "IdeGoto");
|
|
int c = dlg.Run();
|
|
StoreToGlobal(dlg, "IdeGoto");
|
|
if(c != IDOK)
|
|
return;
|
|
int l = dlg.GetLine();
|
|
if(l > 0) {
|
|
editor.SetCursor(editor.GetPos(l - 1));
|
|
editor.TopCursor();
|
|
}
|
|
}
|
|
|
|
void Ide::GotoGlobal()
|
|
{
|
|
SaveFile();
|
|
GotoDlg dlg(Null);
|
|
LoadFromGlobal(dlg, "IdeGotoGlobal");
|
|
int c = dlg.Run();
|
|
StoreToGlobal(dlg, "IdeGotoGlobal");
|
|
if(c != IDOK)
|
|
return;
|
|
int l = dlg.GetLine();
|
|
if(l > 0 && dlg.list.GetCount()) {
|
|
String file = dlg.list.IsCursor() ? dlg.list.Get(4) : dlg.list.Get(0, 4);
|
|
GotoPos(file, l);
|
|
}
|
|
}
|
|
|
|
void AssistEditor::SwapSContext(Parser& p)
|
|
{
|
|
int i = GetCursor();
|
|
if(Ch(i - 1) == ';')
|
|
i--;
|
|
else
|
|
for(;;) {
|
|
int c = Ch(i);
|
|
if(c == '{') {
|
|
i++;
|
|
break;
|
|
}
|
|
if(c == 0 || c == ';' || c == '}')
|
|
break;
|
|
i++;
|
|
}
|
|
Context(p, i);
|
|
}
|
|
|
|
bool Ide::SwapSIf(const char *cref)
|
|
{
|
|
if(designer || !editor.assist_active)
|
|
return false;
|
|
Parser p;
|
|
editor.SwapSContext(p);
|
|
int q = CodeBase().Find(p.current_scope);
|
|
LLOG("SwapS scope: " << p.current_scope);
|
|
if(q < 0)
|
|
return false;
|
|
const Array<CppItem>& n = CodeBase()[q];
|
|
String qitem = QualifyKey(CodeBase(), p.current_scope, p.current_key);
|
|
if(cref && MakeCodeRef(p.current_scope, p.current_key) != cref)
|
|
return false;
|
|
q = FindItem(n, qitem);
|
|
int count = q >= 0 ? GetCount(n, q) : 0;
|
|
if(!cref && count < 2) {
|
|
for(int i = 0; i < n.GetCount(); i++) {
|
|
if(i >= n.GetCount())
|
|
return false;
|
|
if(i != q && n[i].name == p.current_name) {
|
|
GotoCpp(n[i]);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
if(count < 1)
|
|
return false;
|
|
int file = GetCppFileIndex(editfile);
|
|
int line = p.current.line;
|
|
LLOG("SwapS line: " << line);
|
|
int i;
|
|
for(i = 0; i < count; i++) {
|
|
LLOG("file: " << GetCppFile(n[q + i].file) << ", line: " << n[q + i].line);
|
|
if(n[q + i].file == file && n[q + i].line == line) {
|
|
i++;
|
|
break;
|
|
}
|
|
}
|
|
GotoCpp(n[q + i % count]);
|
|
return true;
|
|
}
|
|
|
|
void Ide::SwapS()
|
|
{
|
|
SwapSIf(NULL);
|
|
}
|