ultimatepp/uppsrc/Docedit/Docedit.cpp
cxl f8c9a6bff9 .removed RDUMP
git-svn-id: svn://ultimatepp.org/upp/trunk@12598 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2018-12-04 13:04:37 +00:00

539 lines
12 KiB
C++

#include <DocEdit/DocEdit.h>
int PosOf(const String& str, const String& sub)
{
if(sub.GetLength() > str.GetLength()) return -1;
const char *s = str;
const char *e = s + str.GetLength() - sub.GetLength();
while(s <= e) {
if(memcmp(s, sub, sub.GetLength()) == 0)
return s - ~str;
s++;
}
return -1;
}
void DocBrowser::Nameing()
{
nesting.Clear();
if(IsNull(nameing)) {
Nesting();
return;
}
const VectorMap<String, ArrayMap<String, DocItem> >& ns = set.Get(~nameing);
nesting.Clear();
for(int i = 0; i < ns.GetCount(); i++)
nesting.Add(ns.GetKey(i));
nesting.Sort(0, CompareNests);
nesting.GoBegin();
Nesting();
}
void DocBrowser::Nesting()
{
item.Clear();
if(!nesting.IsCursor()) {
Item();
return;
}
LoadItems(set, ~nameing, nesting.GetKey(), item);
if(sort)
item.Sort(CompareItems);
item.GoBegin();
edit.Enable(item.IsCursor());
}
void DocBrowser::Item()
{
Flush();
EnterItem();
}
void DocBrowser::EnterItem()
{
String lbl;
target = current = DocKey(~nameing, nesting.GetKey(), item.GetKey(), (int)~lang);
if(doc_dir.GetStatus(current) == DocDir::LINK)
if(!ParseLink(doc_dir.GetLink(current), target, lbl)) {
View();
view.SetQTF("[R9&&&=@3* Invalid link");
return;
}
String txt = LoadFile(CommonPath("dppstyles.qtf")) + doc_dir.GetText(target);
package <<= doc_dir.GetPackage(target);
if(edit.IsShown()) {
edit.SetPage(Size(3968, INT_MAX));
edit.SetQTF(txt);
edit.SetFocus();
String p = doc_dir.GetFilePath(target);
if(!IsNull(p)) {
int q = editstate.Find(p);
if(q >= 0) {
FileInfo& fi = editstate[q];
if(fi.time == GetFileTime(p)) {
edit.SetPickUndoInfo(fi.info);
fi.time = Time(1, 1, 1);
}
}
}
int q = posinfo.Find(current);
if(q >= 0)
edit.SetPosInfo(posinfo[q]);
else
if(!lbl.IsEmpty())
edit.GotoLabel(lbl);
edit.ClearModify();
}
else {
view.SetQTF(txt);
if(!lbl.IsEmpty())
view.GotoLabel(lbl);
}
trect.Color(SLtBlue);
title.SetInk(SWhite);
String s = " dpp://" + current.nameing + "/" + current.nesting + "/" + current.item;
switch(GetCurrentStatus()) {
case DocDir::UNDOCUMENTED:
trect.Color(SGray);
break;
case DocDir::LINK:
s << " -> " << target.nameing + "/" + target.nesting + "/" + target.item;
trect.Color(SCyan);
break;
case DocDir::OBSOLETE:
trect.Color(SRed);
break;
case DocDir::EXTERNAL:
trect.Color(SGreen);
break;
}
title = s;
int status = item.Get(4);
int kind = item.Get(2);
String name = item.Get(1);
String text = item.Get(0);
String post;
if(status == DocDir::EXTERNAL)
post = " (external)";
if(!name.IsEmpty() && status != DocDir::EXTERNAL) {
int q = PosOf(text, name);
if(q >= 0) {
if(current.nesting.IsEmpty() || kind == STRUCT || kind == STRUCTTEMPLATE)
Title(text.Mid(0, q) + current.nameing + text.Mid(q) + post);
else
Title(text.Mid(0, q) + current.nameing + current.nesting + "::" + text.Mid(q)
+ post);
return;
}
}
Title(current.nameing + "::" + current.nesting + "::" + text + post);
}
void DocBrowser::Flush()
{
if(edit.IsShown() && target && item.IsCursor()) {
posinfo.GetAdd(current) = edit.GetPosInfo();
if(edit.IsModified()) {
DocItem& im = set.Get(target.nameing).Get(target.nesting).Get(target.item);
const RichText& txt = edit.Get();
SaveFile(CommonPath("dppstyles.qtf"), StylesAsQTF(txt));
if(edit.GetLength()) {
doc_dir.SaveText(GetItemPackage(), target, BodyAsQTF(txt),
doc_dir.GetStatus(target) == DocDir::EXTERNAL);
im.status = DocDir::NORMAL;
}
else {
doc_dir.Remove(target);
im.status = DocDir::UNDOCUMENTED;
}
String p = doc_dir.GetFilePath(target);
FileInfo& fi = editstate.GetAdd(p);
fi.time = GetFileTime(p);
fi.info = edit.PickUndoInfo();
}
target.Clear();
if(edit.IsModified())
ReloadItems();
edit.ClearModify();
}
}
void DocBrowser::Query()
{
DocQuery q;
q.lang = (int)~lang;
q.undocumented = q.normal = q.external = q.obsolete = q.ignored = false;
switch(query.status) {
case 4:
q.ignored = true;
case 0:
q.undocumented = q.normal = q.external = q.obsolete = true;
break;
case 1:
q.undocumented = true;
break;
case 2:
q.obsolete = true;
break;
case 3:
q.ignored = true;
break;
}
q.name = query.name;
q.text = query.text;
q.header = ~query.header;
set = doc_dir.Select(q);
nameing.ClearList();
for(int i = 0; i < set.GetCount(); i++)
nameing.Add(set.GetKey(i));
if(nameing.GetCount())
nameing.SetIndex(0);
Nameing();
}
void DocBrowser::Select()
{
int c;
query.header.ClearList();
Vector<String> h = doc_base.GetHeaders();
for(int i = 0; i < h.GetCount(); i++)
query.header.Add(h[i], GetFileName(h[i]));
query.header.Add(Null, "<any>");
for(;;) {
c = query.Run();
if(c == IDCANCEL)
break;;
if(c == IDYES) {
query.status = 0;
query.name <<= Null;
query.text <<= Null;
}
if(c == IDOK)
break;
}
query.Close();
query.name.AddHistory();
query.text.AddHistory();
if(c == IDOK)
Query();
}
bool DocBrowser::Key(dword key, int)
{
switch(key) {
case K_F6:
Select();
break;
default:
return false;
}
return true;
}
void DocBrowser::Edit()
{
Flush();
edit.Show();
view.Hide();
EnterItem();
}
void DocBrowser::View()
{
view.Show();
edit.Hide();
Item();
}
void DocBrowser::Sort()
{
sort = !sort;
Nesting();
}
int DocBrowser::GetCurrentStatus()
{
return item.IsCursor() ? doc_dir.GetStatus(current) : Null;
}
void DocBrowser::ReloadItems()
{
int c = item.GetCursor();
int a = item.GetCursorSc();
Nesting();
if(c >= 0)
item.SetCursor(c);
item.ScCursor(a);
}
void DocBrowser::SetCurrentStatus(int status)
{
set.GetAdd(current.nameing).GetAdd(current.nesting).GetAdd(current.item).status = status;
ReloadItems();
}
void DocBrowser::Link()
{
int q = GetCurrentStatus();
if(q != DocDir::UNDOCUMENTED && q != DocDir::LINK || !item.IsCursor())
return;
String pk = GetItemPackage();
String h;
if(GetCurrentStatus() == DocDir::LINK)
h = doc_dir.GetLink(current);
if(linkdlg.Perform(set, sort, h, (int)~lang, ~nameing, nesting.GetKey())) {
int c = item.GetCursor();
item.KillCursor();
doc_dir.SaveLink(pk, current, h);
item.SetCursor(c);
SetCurrentStatus(DocDir::LINK);
}
}
void DocBrowser::Ignore()
{
int q = GetCurrentStatus();
if(q != DocDir::UNDOCUMENTED || !item.IsCursor()) return;
int c = item.GetCursor();
String pk = GetItemPackage();
item.KillCursor();
doc_dir.Ignore(pk, current);
item.SetCursor(c);
SetCurrentStatus(DocDir::IGNORED);
}
void DocBrowser::Delete()
{
int q = GetCurrentStatus();
if(q == DocDir::UNDOCUMENTED || !item.IsCursor()) return;
int c = item.GetCursor();
item.KillCursor();
switch(q) {
case DocDir::OBSOLETE:
case DocDir::OBSOLETELINK:
break;
default:
if(!PromptYesNo("Remove current current ?")) return;
}
doc_dir.Remove(current);
item.SetCursor(c);
SetCurrentStatus(DocDir::UNDOCUMENTED);
}
void DocBrowser::New()
{
external.package.Add("Core"); //!!!
external.package <<= doc_dir.GetPackage(current);
external.nameing <<= ~nameing;
external.nesting <<= nesting.GetKey();
again:
if(external.Execute() != IDOK) return;
if(IsNull(external.nameing)) {
Exclamation("Missing namespace !");
goto again;
}
if(IsNull(external.item)) {
Exclamation("Missing item !");
goto again;
}
external.nameing.AddHistory();
external.nesting.AddHistory();
DocKey k = DocKey(~external.nameing, ~external.nesting, ~external.item, (int)~lang);
doc_dir.SaveText(~external.package, k, "", true);
Query();
nameing <<= k.nameing;
Nameing();
if(nesting.FindSetCursor(k.nesting))
item.FindSetCursor(k.item);
}
void DocBrowser::EditLink(String& s)
{
linkdlg.Perform(set, sort, s, (int)~lang, ~nameing, nesting.GetKey());
}
void DocBrowser::FollowLink(const String& s)
{
if(memcmp(s, "dpp://", 6)) {
Exclamation("Not a dpp link !");
return;
}
Vector<String> l = Split(~s + 6, '/', false);
if(l.GetCount() != 3) {
Exclamation("Invalid link !");
return;
}
if(nameing.HasKey(l[0])) {
nameing.SetData(l[0]);
Nameing();
if(nesting.FindSetCursor(l[1])) {
String n = l[2];
String l;
int q = n.Find('#');
if(q >= 0) {
l = n.Mid(q + 1);
n = n.Mid(0, q);
}
if(item.FindSetCursor(n))
return;
}
}
Exclamation("Link not found");
}
void DocBrowser::BrowseMenu(Bar& bar)
{
bar.Add("Select..", THISBACK(Select))
.Key(K_F6);
bar.Separator();
bar.Add("Edit", THISBACK(Edit))
.Radio(edit.IsShown())
.Key(K_CTRL_O);
bar.Add("View", THISBACK(View))
.Radio(view.IsShown())
.Key(edit.IsShown() ? K_ESCAPE : 0);
bar.Separator();
bar.Add("Sort by types and names", THISBACK(Sort))
.Check(sort);
bar.Separator();
}
void DocBrowser::ItemMenu(Bar& bar)
{
int q = GetCurrentStatus();
bar.Add(q == DocDir::UNDOCUMENTED || q == DocDir::LINK,
"Link..", THISBACK(Link))
.Key(K_CTRL_L);
bar.Add(q == DocDir::UNDOCUMENTED, "Ignore", THISBACK(Ignore))
.Key(K_CTRL_I);
bar.Add(q != DocDir::UNDOCUMENTED, "Delete", THISBACK(Delete))
.Key(K_CTRL_DELETE);
bar.Add("New..", THISBACK(New));
}
void DocBrowser::MainMenu(Bar& bar)
{
bar.Add("Browse", THISBACK(BrowseMenu));
bar.Add("Item", THISBACK(ItemMenu));
}
void DocBrowser::EditBar(Bar& bar)
{
edit.StyleTool(bar);
bar.Gap();
edit.FontTools(bar);
bar.Gap();
edit.InkTool(bar);
edit.PaperTool(bar);
bar.Gap();
edit.LanguageTool(bar);
edit.SpellCheckTool(bar);
bar.Break();
edit.HyperlinkTool(bar, 300);
bar.Gap();
edit.LabelTool(bar);
bar.Gap();
edit.IndexEntryTool(bar);
bar.Break();
edit.ParaTools(bar);
bar.Gap();
edit.EditTools(bar);
bar.Gap();
edit.PrintTool(bar);
}
void DocBrowser::SetEditBar()
{
editbar.Set(THISBACK(EditBar));
}
void DocBrowser::SetMainBar()
{
menu.Set(THISBACK(MainMenu));
}
void DocBrowser::Close()
{
Flush();
TopWindow::Close();
}
DocBrowser::DocBrowser()
{
Zoomable().Sizeable().Icon(DppImg::SmallIcon);
ni_split.Vert(nesting, item);
ni_split.SetPos(3000);
int q = nameing.GetMinSize().cy;
larea.Add(nameing.HSizePos().TopPos(0, q));
larea.Add(ni_split.HSizePos().VSizePos(q + 4, 0));
rarea.AddFrame(trect.Height(q + 4));
trect.SetFrame(ThinInsetFrame());
trect.Add(title.SizePos());
trect.Add(package.RightPos(0, 100).VSizePos());
rarea.Add(view.SizePos());
rarea.Add(edit.SizePos());
vi_split.Horz(larea, rarea);
vi_split.SetPos(3000);
Add(vi_split);
nesting.AddColumn().SetDisplay(Single<DocNestDisplay>());
nesting.NoHeader().NoGrid();
nameing <<= THISBACK(Nameing);
nesting.WhenEnterRow = THISBACK(Nesting);
InitItemArray(item);
item.WhenEnterRow = THISBACK(Item);
item.WhenKillCursor = THISBACK(Flush);
item.WhenBar = THISBACK(ItemMenu);
item.WhenLeftDouble = THISBACK(Edit);
view.Show();
edit.Hide();
edit.SetPage(Size(3968, INT_MAX));
CtrlLayoutOKCancel(query, "Select");
query.clear <<= query.Breaker(IDYES);
query.status = 0;
AddFrame(menu);
SetMainBar();
menu.Ctrl::Add(lang.RightPos(10, 70).TopPos(0, EditField::GetStdHeight()));
lang.Add((int)LNG_ENGLISH, "EN-US");
lang.Add((int)LNGFromText("EN-GB"), "EN-GB");
lang.Add((int)LNGFromText("DE-DE"), "DE-DE");
lang.Add((int)LNG_CZECH, "CS-CZ");
lang <<= (int)LNGFromText("EN-US");
lang <<= THISBACK(Query);
edit.InsertFrame(1, editbar);
edit.WhenRefreshBar = THISBACK(SetEditBar);
edit.WhenHyperlink = THISBACK(EditLink);
view.WhenLink = THISBACK(FollowLink);
sort = false;
CtrlLayoutOKCancel(external, "New external item");
external.ActiveFocus(external.item);
}
void AppMain()
{
doc_base.ignore.Add("pick_");
FindFile ff("f:/uppsrc/Core/*.h");
while(ff) {
String fn = String("f:/uppsrc/Core/") + ff.GetName();
try {
doc_base.ParseFile(fn, "Core");
}
catch(Parser::Error e) {
LOG(e);
}
ff.Next();
}
doc_dir.Refresh("Core");
DocBrowser d;
d.Query();
d.Run();
}