From 0f3b0f73760c91a33b1e0829b5367583b68fb070 Mon Sep 17 00:00:00 2001 From: cxl Date: Thu, 15 Oct 2020 13:14:48 +0000 Subject: [PATCH] uppsrc: docs & cosmetics git-svn-id: svn://ultimatepp.org/upp/trunk@15254 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- README.md | 28 +- {uppsrc/Docedit => archive/PaintGL}/Copying | 0 {uppsrc => archive}/PaintGL/PaintGL.cpp | 196 +- {uppsrc => archive}/PaintGL/PaintGL.h | 54 +- {uppsrc => archive}/PaintGL/PaintGL.upp | 12 +- {uppsrc => archive}/RichBook/RichBook.cpp | 1354 +++++++------- {uppsrc => archive}/RichBook/RichBook.h | 268 +-- {uppsrc => archive}/RichBook/RichBook.t | 76 +- {uppsrc => archive}/RichBook/RichBook.upp | 18 +- .../RichBook/RichBook_init.icpp | 16 +- .../uppsrc/Docedit}/Copying | 0 .../uppsrc}/Docedit/DocItem.cpp | 692 +++---- .../uppsrc}/Docedit/DocLink.cpp | 228 +-- .../uppsrc}/Docedit/Docbase.cpp | 132 +- {uppsrc => archive/uppsrc}/Docedit/Docdir.cpp | 1022 +++++----- .../uppsrc}/Docedit/Docedit.cpp | 1078 +++++------ {uppsrc => archive/uppsrc}/Docedit/Docedit.h | 482 ++--- .../uppsrc}/Docedit/Docedit.iml | 106 +- .../uppsrc}/Docedit/Docedit.lay | 96 +- .../uppsrc}/Docedit/Docedit.upp | 30 +- archive/uppsrc/TCore/Copying | 2 +- archive/uppsrc/TCtrlLib/Copying | 2 +- archive/uppsrc/TDraw/Copying | 2 +- archive/uppsrc/TSql/Copying | 2 +- archive/uppsrc/Web/Copying | 2 +- archive/uppsrc/Web/SSL/Copying | 2 +- archive/uppsrc/Web/ctrl/Copying | 2 +- archive/uppsrc/Web/wisapi/Copying | 2 +- {uppsrc => archive/uppsrc}/docpp/Copying | 0 {uppsrc => archive/uppsrc}/docpp/Parser.cpp | 1650 ++++++++--------- {uppsrc => archive/uppsrc}/docpp/Pre.cpp | 190 +- {uppsrc => archive/uppsrc}/docpp/cpplex.cpp | 648 +++---- {uppsrc => archive/uppsrc}/docpp/docpp.h | 500 ++--- {uppsrc => archive/uppsrc}/docpp/docpp.upp | 24 +- {uppsrc => archive/uppsrc}/docpp/keyword.i | 160 +- benchmarks/Sort/Sort.cpp | 29 +- configure_makefile | 18 +- uppbox/uppweb/Resources/Images/TheIDE.png | Bin 0 -> 177761 bytes uppsrc/DocTypes/DocTypes.upp | 2 + uppsrc/GLCtrl/GLCtrl.upp | 2 + uppsrc/GLDraw/GLDraw.upp | 2 + uppsrc/Geom/Coords/Coords.upp | 2 + uppsrc/Geom/Ctrl/Ctrl.upp | 2 + uppsrc/Geom/Draw/Draw.upp | 2 + uppsrc/Geom/Geom.upp | 2 + uppsrc/Ole/Ctrl/Ctrl.upp | 2 + uppsrc/Ole/Ole.upp | 2 + uppsrc/PostgreSQL/PostgreSQL.upp | 2 + uppsrc/Skylark/Iml/Iml.upp | 2 +- uppsrc/TextDiffCtrl/TextDiffCtrl.upp | 2 + uppsrc/VirtualGui/SDL2GL/SDL2GL.upp | 2 + uppsrc/VirtualGui/VirtualGui.upp | 2 +- uppsrc/plugin/astyle/astyle.upp | 2 +- uppsrc/plugin/lz4/lz4.upp | 2 +- uppsrc/plugin/lzma/lzma.upp | 2 +- uppsrc/plugin/zstd/zstd.upp | 2 +- uppsrc/plugin/zstd_legacy/zstd_legacy.upp | 2 +- 57 files changed, 4617 insertions(+), 4544 deletions(-) rename {uppsrc/Docedit => archive/PaintGL}/Copying (100%) rename {uppsrc => archive}/PaintGL/PaintGL.cpp (95%) rename {uppsrc => archive}/PaintGL/PaintGL.h (92%) rename {uppsrc => archive}/PaintGL/PaintGL.upp (91%) rename {uppsrc => archive}/RichBook/RichBook.cpp (96%) rename {uppsrc => archive}/RichBook/RichBook.h (96%) rename {uppsrc => archive}/RichBook/RichBook.t (94%) rename {uppsrc => archive}/RichBook/RichBook.upp (91%) rename {uppsrc => archive}/RichBook/RichBook_init.icpp (92%) rename {uppsrc/PaintGL => archive/uppsrc/Docedit}/Copying (100%) rename {uppsrc => archive/uppsrc}/Docedit/DocItem.cpp (95%) rename {uppsrc => archive/uppsrc}/Docedit/DocLink.cpp (95%) rename {uppsrc => archive/uppsrc}/Docedit/Docbase.cpp (95%) rename {uppsrc => archive/uppsrc}/Docedit/Docdir.cpp (95%) rename {uppsrc => archive/uppsrc}/Docedit/Docedit.cpp (95%) rename {uppsrc => archive/uppsrc}/Docedit/Docedit.h (96%) rename {uppsrc => archive/uppsrc}/Docedit/Docedit.iml (98%) rename {uppsrc => archive/uppsrc}/Docedit/Docedit.lay (98%) rename {uppsrc => archive/uppsrc}/Docedit/Docedit.upp (91%) rename {uppsrc => archive/uppsrc}/docpp/Copying (100%) rename {uppsrc => archive/uppsrc}/docpp/Parser.cpp (95%) rename {uppsrc => archive/uppsrc}/docpp/Pre.cpp (94%) rename {uppsrc => archive/uppsrc}/docpp/cpplex.cpp (95%) rename {uppsrc => archive/uppsrc}/docpp/docpp.h (95%) rename {uppsrc => archive/uppsrc}/docpp/docpp.upp (90%) rename {uppsrc => archive/uppsrc}/docpp/keyword.i (93%) create mode 100644 uppbox/uppweb/Resources/Images/TheIDE.png diff --git a/README.md b/README.md index d980a4822..8e7acf87d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Rapid development is achieved by the [smart and aggressive use of C++](https://w The U++ integrated development environment, TheIDE, introduces modular concepts to C++ programming. It features BLITZ-build technology to speedup C++ rebuilds up to 4 times, Visual designers for U++ libraries, a [Topic++](https://www.ultimatepp.org/app$ide$Topic$en-us.html) system for documenting code and creating rich text resources for applications (like help and code documentation) and [Assist++](https://www.ultimatepp.org/app$ide$Assist$en-us.html) - a powerful C++ code analyzer that provides features like code completion, navigation and transformation. -TheIDE can work with GCC, MinGW and Visual C++ and contains a full featured debugger. TheIDE can also be used to develop non-U++ applications. +TheIDE can work with GCC, Clang, MinGW and Visual C++ and contains a full featured debugger. TheIDE can also be used to develop non-U++ applications. U++ supports following platforms on the production level: **Windows**, **macOS**, **GNU/Linux** & **FreeBSD**. @@ -44,30 +44,40 @@ Below is the code of trivial GUI application that displays "Hello World" string ```c++ #include -class MyAppWindow : public Upp::TopWindow { +class MyApp: public Upp::TopWindow { public: - MyAppWindow() { - Title("My application").Zoomable().Sizeable(); + MyApp() + { + Title("My application").Zoomable().Sizeable().SetRect(0, 0, 320, 200); } - virtual void Paint(Upp::Draw& w) override { + virtual void Paint(Upp::Draw& w) override + { w.DrawRect(GetSize(), Upp::SWhite); - w.DrawText(20, 20, "Hello world!", Upp::Arial(30), Upp::Magenta); + w.DrawText(10, 10, "Hello, world!", Upp::Arial(30), Upp::Magenta); } }; GUI_APP_MAIN { - MyAppWindow app; - app.SetRect(0, 0, 200, 100); - app.Run(); + MyApp().Run(); } ``` +### TheIDE + +Standard part of U++ framework is integrated development environment, TheIDE. + +

+ TheIDE - U++ Integrated Developemnt Enviroment +

+ ### Additional examples See here: [examples](https://www.ultimatepp.org/www$uppweb$examples$en-us.html). Moreover, exactly the same examples can be found in the **examples** and **references** directories located in this repository. +If you would like to see more screenshots, click [here](https://www.ultimatepp.org/www$uppweb$ss$en-us.html). + # Repository ## Repository layout diff --git a/uppsrc/Docedit/Copying b/archive/PaintGL/Copying similarity index 100% rename from uppsrc/Docedit/Copying rename to archive/PaintGL/Copying diff --git a/uppsrc/PaintGL/PaintGL.cpp b/archive/PaintGL/PaintGL.cpp similarity index 95% rename from uppsrc/PaintGL/PaintGL.cpp rename to archive/PaintGL/PaintGL.cpp index 37f97eb26..e40ba1f22 100644 --- a/uppsrc/PaintGL/PaintGL.cpp +++ b/archive/PaintGL/PaintGL.cpp @@ -1,98 +1,98 @@ -#include "PaintGL.h" - -#pragma comment( lib, "opengl32.lib" ) // Search For OpenGL32.lib While Linking -#pragma comment( lib, "glu32.lib" ) // Search For GLu32.lib While Linking -#pragma comment( lib, "glaux.lib" ) // Search For GLaux.lib While Linking - -PaintGL::PaintGL() -{ - size = Null; - hbmp = ohbmp = NULL; - hdc = NULL; - hrc = NULL; -} - -PaintGL::~PaintGL() -{ - Free(); -} - -void PaintGL::Free() -{ - if(hrc) { - wglMakeCurrent(NULL, NULL); - wglDeleteContext(hrc); - SelectObject(hdc, ohbmp); - DeleteDC(hdc); - DeleteObject(hbmp); - hrc = NULL; - hbmp = ohbmp = NULL; - hdc = NULL; - hbmp = NULL; - } - size = Null; -} - - -void PaintGL::Init(Size sz) { - Free(); - - size = sz; - - BITMAPINFOHEADER bih; - memset(&bih, 0, sizeof(bih)); - bih.biSize = sizeof(bih); - bih.biWidth = ((((int) sz.cx * 8) + 31) & ~31) >> 3; - bih.biHeight = sz.cy; - bih.biPlanes = 1; - bih.biBitCount = 32; - bih.biCompression = BI_RGB; - - hdc = CreateCompatibleDC(NULL); - - void *dummy; - - hbmp = CreateDIBSection(hdc, (BITMAPINFO*)&bih, DIB_PAL_COLORS, &dummy, NULL, 0); - - ohbmp = (HBITMAP)SelectObject(hdc, hbmp); - - PIXELFORMATDESCRIPTOR pfd; - memset(&pfd, 0, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL/* | PFD_SUPPORT_GDI | PFD_ACCELERATED*/; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 32; - pfd.cDepthBits = 32; - pfd.iLayerType = PFD_MAIN_PLANE; - - GLuint PixelFormat = ChoosePixelFormat(hdc, &pfd); - SetPixelFormat(hdc, PixelFormat, &pfd); - hrc = wglCreateContext(hdc); - wglMakeCurrent(hdc, hrc); - - glShadeModel(GL_SMOOTH); - glClearColor(0.0f, 0.0f, 0.0f, 0.5f); - glClearDepth(1.0f); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - - glViewport(0, 0, (GLsizei)sz.cx, (GLsizei)sz.cy); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(45.0f, (GLfloat)(sz.cx)/(GLfloat)(sz.cy), 1.0f, 100.0f); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); -} - -void PaintGL::Paint(Draw& w, const Rect& r, Callback gl) -{ - if(r.Size() != size) - Init(r.Size()); - gl(); - glFlush(); - HDC whdc = w.BeginGdi(); - BitBlt(whdc, 0, 0, size.cx, size.cy, hdc, r.left, r.top, SRCCOPY); - w.EndGdi(); -} +#include "PaintGL.h" + +#pragma comment( lib, "opengl32.lib" ) // Search For OpenGL32.lib While Linking +#pragma comment( lib, "glu32.lib" ) // Search For GLu32.lib While Linking +#pragma comment( lib, "glaux.lib" ) // Search For GLaux.lib While Linking + +PaintGL::PaintGL() +{ + size = Null; + hbmp = ohbmp = NULL; + hdc = NULL; + hrc = NULL; +} + +PaintGL::~PaintGL() +{ + Free(); +} + +void PaintGL::Free() +{ + if(hrc) { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(hrc); + SelectObject(hdc, ohbmp); + DeleteDC(hdc); + DeleteObject(hbmp); + hrc = NULL; + hbmp = ohbmp = NULL; + hdc = NULL; + hbmp = NULL; + } + size = Null; +} + + +void PaintGL::Init(Size sz) { + Free(); + + size = sz; + + BITMAPINFOHEADER bih; + memset(&bih, 0, sizeof(bih)); + bih.biSize = sizeof(bih); + bih.biWidth = ((((int) sz.cx * 8) + 31) & ~31) >> 3; + bih.biHeight = sz.cy; + bih.biPlanes = 1; + bih.biBitCount = 32; + bih.biCompression = BI_RGB; + + hdc = CreateCompatibleDC(NULL); + + void *dummy; + + hbmp = CreateDIBSection(hdc, (BITMAPINFO*)&bih, DIB_PAL_COLORS, &dummy, NULL, 0); + + ohbmp = (HBITMAP)SelectObject(hdc, hbmp); + + PIXELFORMATDESCRIPTOR pfd; + memset(&pfd, 0, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL/* | PFD_SUPPORT_GDI | PFD_ACCELERATED*/; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 32; + pfd.cDepthBits = 32; + pfd.iLayerType = PFD_MAIN_PLANE; + + GLuint PixelFormat = ChoosePixelFormat(hdc, &pfd); + SetPixelFormat(hdc, PixelFormat, &pfd); + hrc = wglCreateContext(hdc); + wglMakeCurrent(hdc, hrc); + + glShadeModel(GL_SMOOTH); + glClearColor(0.0f, 0.0f, 0.0f, 0.5f); + glClearDepth(1.0f); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + + glViewport(0, 0, (GLsizei)sz.cx, (GLsizei)sz.cy); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45.0f, (GLfloat)(sz.cx)/(GLfloat)(sz.cy), 1.0f, 100.0f); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +void PaintGL::Paint(Draw& w, const Rect& r, Callback gl) +{ + if(r.Size() != size) + Init(r.Size()); + gl(); + glFlush(); + HDC whdc = w.BeginGdi(); + BitBlt(whdc, 0, 0, size.cx, size.cy, hdc, r.left, r.top, SRCCOPY); + w.EndGdi(); +} diff --git a/uppsrc/PaintGL/PaintGL.h b/archive/PaintGL/PaintGL.h similarity index 92% rename from uppsrc/PaintGL/PaintGL.h rename to archive/PaintGL/PaintGL.h index 81246f6ce..2ac78de9c 100644 --- a/uppsrc/PaintGL/PaintGL.h +++ b/archive/PaintGL/PaintGL.h @@ -1,27 +1,27 @@ -#ifndef _PaintGL_PaintGL_h -#define _PaintGL_PaintGL_h - -#include - -#include -#include -#include - -class PaintGL { - Size size; - HBITMAP hbmp, ohbmp; - HDC hdc; - HGLRC hrc; - - void Free(); - void Init(Size sz); - -public: - void Paint(Draw& w, const Rect& r, Callback gl); - - PaintGL(); - ~PaintGL(); -}; - - -#endif +#ifndef _PaintGL_PaintGL_h +#define _PaintGL_PaintGL_h + +#include + +#include +#include +#include + +class PaintGL { + Size size; + HBITMAP hbmp, ohbmp; + HDC hdc; + HGLRC hrc; + + void Free(); + void Init(Size sz); + +public: + void Paint(Draw& w, const Rect& r, Callback gl); + + PaintGL(); + ~PaintGL(); +}; + + +#endif diff --git a/uppsrc/PaintGL/PaintGL.upp b/archive/PaintGL/PaintGL.upp similarity index 91% rename from uppsrc/PaintGL/PaintGL.upp rename to archive/PaintGL/PaintGL.upp index 271326666..0c93bd5b7 100644 --- a/uppsrc/PaintGL/PaintGL.upp +++ b/archive/PaintGL/PaintGL.upp @@ -1,6 +1,6 @@ -file - PaintGL.h, - PaintGL.cpp, - Info readonly separator, - Copying; - +file + PaintGL.h, + PaintGL.cpp, + Info readonly separator, + Copying; + diff --git a/uppsrc/RichBook/RichBook.cpp b/archive/RichBook/RichBook.cpp similarity index 96% rename from uppsrc/RichBook/RichBook.cpp rename to archive/RichBook/RichBook.cpp index 7879363b3..8ab6caeee 100644 --- a/uppsrc/RichBook/RichBook.cpp +++ b/archive/RichBook/RichBook.cpp @@ -1,677 +1,677 @@ -#include "RichBook.h" - -#include -#include - -namespace Upp { - -struct FieldTypeVarCls : public RichPara::FieldType -{ - virtual Array Evaluate(const String& param, VectorMap& vars, - const RichPara::CharFormat& fmt); -}; - -Array FieldTypeVarCls::Evaluate(const String& dest, - VectorMap& vars, const RichPara::CharFormat& linkfmt) -{ - RichPara para; - RichPara::CharFormat fmt = linkfmt; - int f = vars.Find(dest); - if(f < 0) { - fmt.ink = LtRed(); - fmt.paper = WhiteGray(); - para.Cat(dest, fmt); - } - else - para.Cat(StdFormat(vars[f]), fmt); - return para.part; -} - -RichPara::FieldType& GLOBAL_V(FieldTypeVarCls, FieldTypeVar); - -Id FieldTypeVarID() -{ - static Id ftv("VAR"); - return ftv; -} - -INITBLOCK { - RichPara::Register(FieldTypeVarID(), FieldTypeVar()); -} - -/* -RichPara::FieldType& FieldTypeIndexEntry() -{ -} - -Id FieldTypeIndexEntryID() -{ -} - -String EncodeIndexEntry(const RichIndexEntry& idx) -{ -} - -RichIndexEntry DecodeIndexEntry(String encoded_indexentry) -{ -} -*/ - -RichBookSection::RichBookSection() -{ -// pagesize = pg; - columns = 1; - firstpage = 1; - margin = Rect(0, 0, 0, 0); - header_space = 200; - footer_space = 200; - column_space = 200; -// footer[1] = "- # -"; -} - -Rect RichBookSection::GetPageRect(Size pagesize) const -{ - return Rect(pagesize).Deflated(margin); -} - -Rect RichBookSection::GetTextRect(Size pagesize, int colindex) const -{ - Rect textarea = GetPageRect(pagesize).Deflated(0, header_space, 0, footer_space); - if(columns <= 1) - return textarea; - int colwd = (textarea.Width() - column_space * (columns - 1)) / columns; - int offset = iscale(textarea.Width() - colwd, colindex, columns - 1); - textarea.left += offset; - textarea.right = textarea.left + colwd; - return textarea; -} - -Size RichBookSection::GetTextSize(Size pagesize) const -{ - return GetTextRect(pagesize, 0).Size(); -} - -class RichSectionPageDraw : public PageDraw -{ -public: - RichSectionPageDraw(Size drawingsize, Gate2 progress, int& progress_pos); - - virtual Draw& Page(int page); - virtual Draw& Info(); - - Vector Close(); - -private: - Gate2 progress; - int& progress_pos; - Size drawingsize; - Vector pages; - DrawingDraw ddraw; - DrawingDraw info; - int currentpage; -}; - -RichSectionPageDraw::RichSectionPageDraw(Size dsz, Gate2 progress, int& progress_pos) -: progress(progress) -, progress_pos(progress_pos) -{ - currentpage = -1; - info.Create(drawingsize = dsz); -} - -Draw& RichSectionPageDraw::Page(int page) -{ - if(page != currentpage) { - ASSERT(ddraw.GetCloffLevel() == 0); - progress(progress_pos + page, -1); - if(currentpage >= 0) - pages.At(currentpage) = ddraw; - ddraw.Create(drawingsize); - ddraw.DrawDrawing(drawingsize, pages.At(currentpage = page)); - } - return ddraw; -} - -Draw& RichSectionPageDraw::Info() -{ - return Page(0); -} - -Vector RichSectionPageDraw::Close() -{ - if(currentpage >= 0) { - ASSERT(ddraw.GetCloffLevel() == 0); - pages.At(currentpage) = ddraw; - } - return pages; -} - -static String ExpandHFText(const char *text, int pageno) -{ - String out; - for(char c; c = *text++;) - if(c == '#') - switch(*text++) { - case 'r': out.Cat(FormatIntRoman(pageno, false)); break; - case 'R': out.Cat(FormatIntRoman(pageno, true)); break; - case 'a': out.Cat(FormatIntAlpha(pageno, false)); break; - case 'A': out.Cat(FormatIntAlpha(pageno, true)); break; - default: text--; out.Cat(FormatInt(pageno)); break; - } - else - out.Cat(c); - return out; -} - -Vector RichPrintSection::Print(Size pagesize, Gate2 progress, int& progress_pos) const -{ - ASSERT(columns > 0); - Size drawingsize = GetTextSize(pagesize); - RichSectionPageDraw spdraw(drawingsize, progress, progress_pos); - PaintInfo paintinfo; - paintinfo.top = PageY(0, 0); - paintinfo.bottom = PageY(32767, 0); - paintinfo.indexentry = Null; - text.Paint(spdraw, drawingsize, paintinfo); - Vector in = spdraw.Close(); - Vector out; - for(int i = 0; i < in.GetCount(); i += columns) { - int pageno = firstpage + out.GetCount(); - DrawingDraw ddraw(pagesize); - Rect pagerect = GetPageRect(pagesize); - for(int c = 0; c < columns && c + i < in.GetCount(); c++) - ddraw.DrawDrawing(GetTextRect(pagesize, c), in[i + c]); - for(int hf = 0; hf < 3; hf++) { - if(!IsNull(header[hf])) { - String s = ExpandHFText(header[hf], pageno); - Size sz = UPP::GetTextSize(s, charformat); - int x; - switch(hf) { - case 0: x = pagerect.left; break; - case 1: x = (pagerect.left + pagerect.right - sz.cx) >> 1; break; - case 2: x = pagerect.right - sz.cx; break; - } - ddraw.DrawText(x, pagerect.top, s, charformat); - } - if(!IsNull(footer[hf])) { - String s = ExpandHFText(footer[hf], pageno); - Size sz = UPP::GetTextSize(s, charformat); - int x; - switch(hf) { - case 0: x = pagerect.left; break; - case 1: x = (pagerect.left + pagerect.right - sz.cx) >> 1; break; - case 2: x = pagerect.right - sz.cx; break; - } - ddraw.DrawText(x, pagerect.bottom - sz.cy, s, charformat); - } - } - out.Add() = ddraw; - } - return out; -} - -String GetLangSuffix(int language = GetCurrentLanguage()) -{ - String lt = LNGAsText(language); - String out; - out << '$' << (char)ToLower(lt[0]) << (char)ToLower(lt[1]) << '-' << (char)ToLower(lt[3]) << (char)ToLower(lt[4]); - return out; -} - -void MakeStdToc(RichText& out, const RichToc& toc, int print_width) -{ - VectorMap< String, ArrayMap > subparts; - String suffix = GetLangSuffix(); - for(int i = 0; i < toc.entries.GetCount(); i++) { - const RichTocEntry& e = toc.entries[i]; - RichPara::Format pfmt = out.GetStyle(out.GetStyleId("Toc" + FormatInt(e.level))).format; - RichPara para; - para.format = pfmt; - WString name = e.text; - String tname = e.topic, subpart; - int th = tname.Find('#'); - if(th >= 0) { - subpart = tname.Mid(th); - tname.Trim(th); - } - tname.Cat(suffix); - Topic tp = GetTopic(tname); - if(!IsNull(name)) - para.Cat(name, pfmt); - else { - if(!IsNull(subpart)) { - int sp = subparts.Find(tname); - if(sp < 0) { - sp = subparts.GetCount(); - ArrayMap& spmap = subparts.Add(tname); - RichText rt = ParseQTF(tp.text); - for(int p = 0; p < rt.GetPartCount(); p++) - if(rt.IsPara(p)) { - RichPara rp = rt.Get(p); -// if(*rp.format.label == '#') - spmap.AddPick("#" + rp.format.label, rp); - } - } - para <<= subparts[sp].Get(subpart, RichPara()); - Array objs; - String packed = para.Pack(para.format, objs); - para.Unpack(packed, objs, pfmt); - } - else if(!IsNull(tp.title)) - para.Cat(FromUtf8(tp.title), pfmt); - } - if(para.part.IsEmpty()) { - pfmt.ink = LtRed(); - pfmt.paper = WhiteGray(); - para.Cat((WString)(tname + subpart), pfmt); - } - para.Cat("\t", pfmt); - para.Cat(FieldTypeVarID(), String().Cat() << tname << subpart << "$page", pfmt); - out.Cat(para); - } - RLOG("MakeStdToc:\n" << AsQTF(out)); -} - -void MakeOnlineToc(RichText& out, const RichToc& toc) -{ - String suffix = GetLangSuffix(); - VectorMap< String, ArrayMap > subparts; - for(int i = 0; i < toc.entries.GetCount(); i++) { - const RichTocEntry& e = toc.entries[i]; - RichPara::Format pfmt = out.GetStyle(out.GetStyleId("Topics" + FormatInt(e.level))).format; - RichPara para; - para.format = pfmt; - WString name = e.text; - String tname = e.topic, subpart; - int th = tname.Find('#'); - if(th >= 0) { - subpart = tname.Mid(th); - tname.Trim(th); - } - tname.Cat(suffix); - Topic tp = GetTopic(tname); - pfmt.link = tname; - if(!IsNull(name)) - para.Cat(name, pfmt); - else { - if(!IsNull(subpart)) { - int sp = subparts.Find(tname); - if(sp < 0) { - sp = subparts.GetCount(); - ArrayMap& spmap = subparts.Add(tname); - RichText rt = ParseQTF(tp.text); - for(int p = 0; p < rt.GetPartCount(); p++) - if(rt.IsPara(p)) { - RichPara rp = rt.Get(p); -// if(*rp.format.label == '#') - spmap.AddPick("#" + rp.format.label, rp); - } - } - para <<= subparts[sp].Get(subpart, RichPara()); - Array objs; - String packed = para.Pack(para.format, objs); - para.Unpack(packed, objs, pfmt); - } - else if(!IsNull(tp.title)) - para.Cat(FromUtf8(tp.title), pfmt); - } - if(para.part.IsEmpty()) { - pfmt.ink = LtRed(); - pfmt.paper = WhiteGray(); - para.Cat((WString)(tname + subpart), pfmt); - } - out.Cat(para); - } - RLOG("MakeOnlineToc:\n" << AsQTF(out)); -} - -void MakeTocTopics(RichText& out, const RichToc& toc) -{ - String suffix = GetLangSuffix(); - VectorMap< String, VectorMap > topic_tocrefs; - for(int i = 0; i < toc.entries.GetCount(); i++) { - String tname = toc.entries[i].topic; - int th = tname.Find('#'); - if(th >= 0) - topic_tocrefs.GetAdd(tname.Left(th)).GetAdd(tname.Mid(th), i); - } - Index done; - for(int i = 0; i < toc.entries.GetCount(); i++) { - const RichTocEntry& e = toc.entries[i]; - WString name = e.text; - String tname = e.topic; - int th = tname.Find('#'); - if(th >= 0) - tname.Trim(th); - int tr = topic_tocrefs.Find(tname); - tname << suffix; - if(done.Find(tname) >= 0) - continue; - done.Add(tname); - Topic tp = GetTopic(tname); - RichPara title_para; - title_para.format = out.GetStyle(out.GetStyleId("Heading" + FormatInt(e.level))).format; - if(IsNull(name) && IsNull(name = FromUtf8(tp.title))) { - name = (WString)tname; - title_para.format.ink = LtRed(); - title_para.format.paper = WhiteGray(); - } - title_para.format.label = tname; - title_para.Cat(name, title_para.format); - out.Cat(title_para); - RichText data = ParseQTF(tp.text); - int pcount = out.GetPartCount(); - out.CatPick(data); - for(int t = pcount; t < out.GetPartCount(); t++) - if(out.IsPara(t)) { - RichPara p = out.Get(t); - String lbl = "#" + p.format.label; - int tx; - if(tr >= 0 && (tx = topic_tocrefs[tr].Find(lbl)) >= 0) { - const RichTocEntry& ex = toc.entries[topic_tocrefs[tr][tx]]; - Array objs; - String pack = p.Pack(p.format, objs); - p.format = out.GetStyle(out.GetStyleId("Heading" + FormatInt(ex.level))).format; - p.Unpack(pack, objs, p.format); - p.format.label = tname + lbl; - out.Set(t, p, out.GetStyles()); - } - } - } -} - -//RichText MakeStdIndex( - -RichBook::RichBook(Size pg) -: page_size(pg) -{ - RichStyle toc1, toc2, toc3, toc4; - RichPara::Tab& t1tab = toc1.format.tab.Add(); - t1tab.pos = pg.cx - 300; - t1tab.align = ALIGN_RIGHT; - t1tab.fillchar = 1; - toc2 = toc3 = toc4 = toc1; - t1tab.fillchar = 0; - - toc1.name = "Toc1"; - (Font&)toc1.format = Arial(90).Bold(); - toc1.format.indent = 100; - toc1.format.before = 100; - toc1.format.number[0] = RichPara::NUMBER_1; - - toc2.name = "Toc2"; - (Font&)toc2.format = Arial(84).Bold(); - toc2.format.indent = 200; - toc2.format.lm = 200; - toc2.format.number[0] = toc2.format.number[1] = RichPara::NUMBER_1; - - toc3.name = "Toc3"; - (Font&)toc3.format = Arial(84); - toc3.format.indent = 300; - toc3.format.lm = 300; - toc3.format.number[0] = toc3.format.number[1] = toc3.format.number[2] = RichPara::NUMBER_1; - - toc4.name = "Toc4"; - toc4.format.number[0] = toc4.format.number[1] = toc4.format.number[2] = toc4.format.number[3] = RichPara::NUMBER_1; - - RichStyle head1, head2, head3, head4; - head1.name = "Heading1"; - (Font&)head1.format = Arial(144).Bold(); - head1.format.newpage = true; - head1.format.before = 300; - head1.format.after = 100; - head1.format.indent = 150; - head1.format.number[0] = RichPara::NUMBER_1; - - head2.name = "Heading2"; - (Font&)head2.format = Arial(120).Bold(); - head2.format.before = 200; - head2.format.after = 100; - head2.format.indent = 200; - head2.format.number[0] = head2.format.number[1] = RichPara::NUMBER_1; - - head3.name = "Heading3"; - (Font&)head3.format = Arial(100).Bold(); - head3.format.before = 100; - head3.format.after = 50; - head3.format.indent = 250; - head3.format.number[0] = head3.format.number[1] = head3.format.number[2] = RichPara::NUMBER_1; - - head4 = head3; - head4.name = "Heading4"; - head4.format.number[0] = head4.format.number[1] = head4.format.number[2] = head4.format.number[3] = RichPara::NUMBER_1; - - default_styles.Add(Uuid::Create(), toc1); - default_styles.Add(Uuid::Create(), toc2); - default_styles.Add(Uuid::Create(), toc3); - default_styles.Add(Uuid::Create(), toc4); - - default_styles.Add(Uuid::Create(), head1); - default_styles.Add(Uuid::Create(), head2); - default_styles.Add(Uuid::Create(), head3); - default_styles.Add(Uuid::Create(), head4); -} - -RichPrintSection& RichBook::AddSection() -{ - RichText init; - init.OverrideStyles(default_styles); - return sections.Add(new RichPrintSection(default_section, init)); -} - -Vector RichBook::Print(Size pagesize, Gate2 progress) -{ - Vector out; - int pos = 0; - - VectorMap vars; - vars.GetAdd("$book") = 1; - bool stable = false; - enum { MAX_PASSES = 10 }; - int pass; - for(pass = 1; !stable && pass <= MAX_PASSES; pass++) { - if(progress(pass, 0)) - throw AbortExc(); - stable = true; - int pageno = 1; - Index chkdup; - for(int s = 0; s < sections.GetCount(); s++) { - RichPrintSection& psec = sections[s]; - if(psec.text.GetPartCount() > 0 && psec.text.IsPara(0)) { - RichPara p0 = psec.text.Get(0); - if(p0.format.newpage) { - p0.format.newpage = false; - psec.text.Set(0, p0, psec.text.GetStyles()); - } - } - Size textsize = psec.GetTextSize(pagesize); - PageY begin; - pageno = Nvl(psec.firstpage, pageno); - psec.text.EvaluateFields(vars); - int numpages = psec.text.GetHeight(textsize).page / psec.columns + 1; - Vector posinfo = psec.text.GetValPos(textsize, RichText::LABELS); - for(int i = 0; i < posinfo.GetCount(); i++) { - String key = posinfo[i].data.ToString() + "$page"; - if(chkdup.Find(key) >= 0) { - if(pass == 1) - RLOG("Duplicate: " << key); - continue; - } - chkdup.Add(key); - int oldpage = vars.Get(key, Value()); - int newpage = pageno + posinfo[i].py.page; - if(newpage != oldpage) { - if(pass > 2) - RLOG("Unstable: " << key << ": " << oldpage << " -> " << newpage); - vars.GetAdd(key) = newpage; - stable = false; - } - } - pageno += numpages; - } - } - for(int i = 0; i < sections.GetCount(); i++) - out.AppendPick(sections[i].Print(pagesize, progress, pos)); -#ifdef _DEBUG - RichText symtext; - Vector order = GetSortOrder(vars.GetKeys()); - for(int o = 0; o < order.GetCount(); o++) { - RichPara para; - para.Cat(NFormat("<%s> %vt", vars.GetKey(order[o]), vars[order[o]]), para.format); - symtext.Cat(para); - } - RichPrintSection symsec(default_section, symtext); - out.AppendPick(symsec.Print(pagesize, progress, pos)); -#endif - return out; -} - -void CreateHelpBook(RichBook& book) -{ - Progress progress(t_("Typesetting page %d...")); - DocReport report; - Vector pages = book.Print(report.GetPageSize(), progress); - progress.SetText(t_("Printing page %d...")); - for(int i = 0; i < pages.GetCount(); i++) { - if(progress.SetCanceled(i, pages.GetCount())) - throw AbortExc(); - if(i) - report.NextPage(); - report.DrawDrawing(pages[i].GetSize(), pages[i]); - } - report.Perform(); -} - -String CreateHelpPDF(RichBook& book) -{ - PdfDraw pdf(210 * 6000 / 254, 297 * 6000 / 254); - Rect margin = Rect(pdf.GetPagePixels()).Deflated(236); - Progress progress(t_("Typesetting...")); - Vector pages = book.Print(margin.Size(), progress); - progress.SetText(t_("Exporting PDF...")); - progress.SetTotal(pages.GetCount()); - for(int i = 0; i < pages.GetCount(); i++) { - if(progress.StepCanceled()) - throw AbortExc(); - pdf.StartPage(); - pdf.DrawDrawing(margin, pages[i]); - pdf.EndPage(); - } - return pdf.Finish(); -} - -String CreateHelpRTF(RichBook& book, byte charset) -{ - RichText richtext; - for(int i = 0; i < book.sections.GetCount(); i++) - richtext.CatPick(book.sections[i].text); - return EncodeRTF(richtext, charset); -} - -RichBookHtml::RichBookHtml() -{ -} - -void RichBookHtml::AddFile(String url, String data) -{ -} - -void RichBookHtml::AddImage(String url, String data) -{ -} - -String RichBookHtml::GetURLFile(String url) const -{ - String out; - return out; -} - -void CreateHelpHtml(RichBook& book, RichBookHtml& html) -{ -} - -GLOBAL_VAR(Callback1, DefaultBook) - -void CreateDefaultBook() -{ - RichBook book; - DefaultBook()(book); - CreateHelpBook(book); -} - -void CreateDefaultPDF() -{ - RichBook book; - DefaultBook()(book); - try { - String data = CreateHelpPDF(book); - FileSelector fsel; - fsel.Type(t_("PDF documents (*.pdf)"), "*.pdf") - .DefaultExt("pdf") - .AllFilesType(); - static String recent; - fsel <<= recent; - if(fsel.ExecuteSaveAs(t_("PDF export"))) { - recent = ~fsel; - if(!SaveFile(recent, data)) - throw Exc(NFormat("Error saving file '%s' (%d B).", recent, data.GetLength())); - } - } - catch(Exc e) { - ShowExc(e); - } -} - -void CreateDefaultRTF() -{ - RichBook book; - DefaultBook()(book); - try { - String data = CreateHelpRTF(book, GetDefaultCharset()); - FileSelector fsel; - fsel.Type(t_("Rich text documents (*.rtf)"), "*.rtf") - .DefaultExt("rtf") - .AllFilesType(); - static String recent; - fsel <<= recent; - if(fsel.ExecuteSaveAs(t_("Save manual as"))) { - recent = ~fsel; - if(!SaveFile(recent, data)) - throw Exc(NFormat("Error saving file '%s' (%d B).", recent, data.GetLength())); - } - } - catch(Exc e) { - ShowExc(e); - } -} - -void CreateDefaultHTML() -{ - RichBook book; - DefaultBook()(book); - try { - RichBookHtml html; - CreateHelpHtml(book, html); - } - catch(Exc e) { - ShowExc(e); - } -} - -void ManualMenu() -{ - MenuBar menu; - bool isdb = DefaultBook(); - menu.Add(isdb, t_("Print manual"), callback(&CreateDefaultBook)); - menu.Add(isdb, t_("PDF export"), callback(&CreateDefaultPDF)); - menu.Add(isdb, t_("RTF export"), callback(&CreateDefaultRTF)); - menu.Add(isdb, t_("HTML export"), callback(&CreateDefaultHTML)); - menu.Execute(); -} - -void HelpBookMenu(Bar& bar) -{ - bar.Add(t_("Save manual"), CtrlImg::save(), callback(&ManualMenu)); -} - -} +#include "RichBook.h" + +#include +#include + +namespace Upp { + +struct FieldTypeVarCls : public RichPara::FieldType +{ + virtual Array Evaluate(const String& param, VectorMap& vars, + const RichPara::CharFormat& fmt); +}; + +Array FieldTypeVarCls::Evaluate(const String& dest, + VectorMap& vars, const RichPara::CharFormat& linkfmt) +{ + RichPara para; + RichPara::CharFormat fmt = linkfmt; + int f = vars.Find(dest); + if(f < 0) { + fmt.ink = LtRed(); + fmt.paper = WhiteGray(); + para.Cat(dest, fmt); + } + else + para.Cat(StdFormat(vars[f]), fmt); + return para.part; +} + +RichPara::FieldType& GLOBAL_V(FieldTypeVarCls, FieldTypeVar); + +Id FieldTypeVarID() +{ + static Id ftv("VAR"); + return ftv; +} + +INITBLOCK { + RichPara::Register(FieldTypeVarID(), FieldTypeVar()); +} + +/* +RichPara::FieldType& FieldTypeIndexEntry() +{ +} + +Id FieldTypeIndexEntryID() +{ +} + +String EncodeIndexEntry(const RichIndexEntry& idx) +{ +} + +RichIndexEntry DecodeIndexEntry(String encoded_indexentry) +{ +} +*/ + +RichBookSection::RichBookSection() +{ +// pagesize = pg; + columns = 1; + firstpage = 1; + margin = Rect(0, 0, 0, 0); + header_space = 200; + footer_space = 200; + column_space = 200; +// footer[1] = "- # -"; +} + +Rect RichBookSection::GetPageRect(Size pagesize) const +{ + return Rect(pagesize).Deflated(margin); +} + +Rect RichBookSection::GetTextRect(Size pagesize, int colindex) const +{ + Rect textarea = GetPageRect(pagesize).Deflated(0, header_space, 0, footer_space); + if(columns <= 1) + return textarea; + int colwd = (textarea.Width() - column_space * (columns - 1)) / columns; + int offset = iscale(textarea.Width() - colwd, colindex, columns - 1); + textarea.left += offset; + textarea.right = textarea.left + colwd; + return textarea; +} + +Size RichBookSection::GetTextSize(Size pagesize) const +{ + return GetTextRect(pagesize, 0).Size(); +} + +class RichSectionPageDraw : public PageDraw +{ +public: + RichSectionPageDraw(Size drawingsize, Gate2 progress, int& progress_pos); + + virtual Draw& Page(int page); + virtual Draw& Info(); + + Vector Close(); + +private: + Gate2 progress; + int& progress_pos; + Size drawingsize; + Vector pages; + DrawingDraw ddraw; + DrawingDraw info; + int currentpage; +}; + +RichSectionPageDraw::RichSectionPageDraw(Size dsz, Gate2 progress, int& progress_pos) +: progress(progress) +, progress_pos(progress_pos) +{ + currentpage = -1; + info.Create(drawingsize = dsz); +} + +Draw& RichSectionPageDraw::Page(int page) +{ + if(page != currentpage) { + ASSERT(ddraw.GetCloffLevel() == 0); + progress(progress_pos + page, -1); + if(currentpage >= 0) + pages.At(currentpage) = ddraw; + ddraw.Create(drawingsize); + ddraw.DrawDrawing(drawingsize, pages.At(currentpage = page)); + } + return ddraw; +} + +Draw& RichSectionPageDraw::Info() +{ + return Page(0); +} + +Vector RichSectionPageDraw::Close() +{ + if(currentpage >= 0) { + ASSERT(ddraw.GetCloffLevel() == 0); + pages.At(currentpage) = ddraw; + } + return pages; +} + +static String ExpandHFText(const char *text, int pageno) +{ + String out; + for(char c; c = *text++;) + if(c == '#') + switch(*text++) { + case 'r': out.Cat(FormatIntRoman(pageno, false)); break; + case 'R': out.Cat(FormatIntRoman(pageno, true)); break; + case 'a': out.Cat(FormatIntAlpha(pageno, false)); break; + case 'A': out.Cat(FormatIntAlpha(pageno, true)); break; + default: text--; out.Cat(FormatInt(pageno)); break; + } + else + out.Cat(c); + return out; +} + +Vector RichPrintSection::Print(Size pagesize, Gate2 progress, int& progress_pos) const +{ + ASSERT(columns > 0); + Size drawingsize = GetTextSize(pagesize); + RichSectionPageDraw spdraw(drawingsize, progress, progress_pos); + PaintInfo paintinfo; + paintinfo.top = PageY(0, 0); + paintinfo.bottom = PageY(32767, 0); + paintinfo.indexentry = Null; + text.Paint(spdraw, drawingsize, paintinfo); + Vector in = spdraw.Close(); + Vector out; + for(int i = 0; i < in.GetCount(); i += columns) { + int pageno = firstpage + out.GetCount(); + DrawingDraw ddraw(pagesize); + Rect pagerect = GetPageRect(pagesize); + for(int c = 0; c < columns && c + i < in.GetCount(); c++) + ddraw.DrawDrawing(GetTextRect(pagesize, c), in[i + c]); + for(int hf = 0; hf < 3; hf++) { + if(!IsNull(header[hf])) { + String s = ExpandHFText(header[hf], pageno); + Size sz = UPP::GetTextSize(s, charformat); + int x; + switch(hf) { + case 0: x = pagerect.left; break; + case 1: x = (pagerect.left + pagerect.right - sz.cx) >> 1; break; + case 2: x = pagerect.right - sz.cx; break; + } + ddraw.DrawText(x, pagerect.top, s, charformat); + } + if(!IsNull(footer[hf])) { + String s = ExpandHFText(footer[hf], pageno); + Size sz = UPP::GetTextSize(s, charformat); + int x; + switch(hf) { + case 0: x = pagerect.left; break; + case 1: x = (pagerect.left + pagerect.right - sz.cx) >> 1; break; + case 2: x = pagerect.right - sz.cx; break; + } + ddraw.DrawText(x, pagerect.bottom - sz.cy, s, charformat); + } + } + out.Add() = ddraw; + } + return out; +} + +String GetLangSuffix(int language = GetCurrentLanguage()) +{ + String lt = LNGAsText(language); + String out; + out << '$' << (char)ToLower(lt[0]) << (char)ToLower(lt[1]) << '-' << (char)ToLower(lt[3]) << (char)ToLower(lt[4]); + return out; +} + +void MakeStdToc(RichText& out, const RichToc& toc, int print_width) +{ + VectorMap< String, ArrayMap > subparts; + String suffix = GetLangSuffix(); + for(int i = 0; i < toc.entries.GetCount(); i++) { + const RichTocEntry& e = toc.entries[i]; + RichPara::Format pfmt = out.GetStyle(out.GetStyleId("Toc" + FormatInt(e.level))).format; + RichPara para; + para.format = pfmt; + WString name = e.text; + String tname = e.topic, subpart; + int th = tname.Find('#'); + if(th >= 0) { + subpart = tname.Mid(th); + tname.Trim(th); + } + tname.Cat(suffix); + Topic tp = GetTopic(tname); + if(!IsNull(name)) + para.Cat(name, pfmt); + else { + if(!IsNull(subpart)) { + int sp = subparts.Find(tname); + if(sp < 0) { + sp = subparts.GetCount(); + ArrayMap& spmap = subparts.Add(tname); + RichText rt = ParseQTF(tp.text); + for(int p = 0; p < rt.GetPartCount(); p++) + if(rt.IsPara(p)) { + RichPara rp = rt.Get(p); +// if(*rp.format.label == '#') + spmap.AddPick("#" + rp.format.label, rp); + } + } + para <<= subparts[sp].Get(subpart, RichPara()); + Array objs; + String packed = para.Pack(para.format, objs); + para.Unpack(packed, objs, pfmt); + } + else if(!IsNull(tp.title)) + para.Cat(FromUtf8(tp.title), pfmt); + } + if(para.part.IsEmpty()) { + pfmt.ink = LtRed(); + pfmt.paper = WhiteGray(); + para.Cat((WString)(tname + subpart), pfmt); + } + para.Cat("\t", pfmt); + para.Cat(FieldTypeVarID(), String().Cat() << tname << subpart << "$page", pfmt); + out.Cat(para); + } + RLOG("MakeStdToc:\n" << AsQTF(out)); +} + +void MakeOnlineToc(RichText& out, const RichToc& toc) +{ + String suffix = GetLangSuffix(); + VectorMap< String, ArrayMap > subparts; + for(int i = 0; i < toc.entries.GetCount(); i++) { + const RichTocEntry& e = toc.entries[i]; + RichPara::Format pfmt = out.GetStyle(out.GetStyleId("Topics" + FormatInt(e.level))).format; + RichPara para; + para.format = pfmt; + WString name = e.text; + String tname = e.topic, subpart; + int th = tname.Find('#'); + if(th >= 0) { + subpart = tname.Mid(th); + tname.Trim(th); + } + tname.Cat(suffix); + Topic tp = GetTopic(tname); + pfmt.link = tname; + if(!IsNull(name)) + para.Cat(name, pfmt); + else { + if(!IsNull(subpart)) { + int sp = subparts.Find(tname); + if(sp < 0) { + sp = subparts.GetCount(); + ArrayMap& spmap = subparts.Add(tname); + RichText rt = ParseQTF(tp.text); + for(int p = 0; p < rt.GetPartCount(); p++) + if(rt.IsPara(p)) { + RichPara rp = rt.Get(p); +// if(*rp.format.label == '#') + spmap.AddPick("#" + rp.format.label, rp); + } + } + para <<= subparts[sp].Get(subpart, RichPara()); + Array objs; + String packed = para.Pack(para.format, objs); + para.Unpack(packed, objs, pfmt); + } + else if(!IsNull(tp.title)) + para.Cat(FromUtf8(tp.title), pfmt); + } + if(para.part.IsEmpty()) { + pfmt.ink = LtRed(); + pfmt.paper = WhiteGray(); + para.Cat((WString)(tname + subpart), pfmt); + } + out.Cat(para); + } + RLOG("MakeOnlineToc:\n" << AsQTF(out)); +} + +void MakeTocTopics(RichText& out, const RichToc& toc) +{ + String suffix = GetLangSuffix(); + VectorMap< String, VectorMap > topic_tocrefs; + for(int i = 0; i < toc.entries.GetCount(); i++) { + String tname = toc.entries[i].topic; + int th = tname.Find('#'); + if(th >= 0) + topic_tocrefs.GetAdd(tname.Left(th)).GetAdd(tname.Mid(th), i); + } + Index done; + for(int i = 0; i < toc.entries.GetCount(); i++) { + const RichTocEntry& e = toc.entries[i]; + WString name = e.text; + String tname = e.topic; + int th = tname.Find('#'); + if(th >= 0) + tname.Trim(th); + int tr = topic_tocrefs.Find(tname); + tname << suffix; + if(done.Find(tname) >= 0) + continue; + done.Add(tname); + Topic tp = GetTopic(tname); + RichPara title_para; + title_para.format = out.GetStyle(out.GetStyleId("Heading" + FormatInt(e.level))).format; + if(IsNull(name) && IsNull(name = FromUtf8(tp.title))) { + name = (WString)tname; + title_para.format.ink = LtRed(); + title_para.format.paper = WhiteGray(); + } + title_para.format.label = tname; + title_para.Cat(name, title_para.format); + out.Cat(title_para); + RichText data = ParseQTF(tp.text); + int pcount = out.GetPartCount(); + out.CatPick(data); + for(int t = pcount; t < out.GetPartCount(); t++) + if(out.IsPara(t)) { + RichPara p = out.Get(t); + String lbl = "#" + p.format.label; + int tx; + if(tr >= 0 && (tx = topic_tocrefs[tr].Find(lbl)) >= 0) { + const RichTocEntry& ex = toc.entries[topic_tocrefs[tr][tx]]; + Array objs; + String pack = p.Pack(p.format, objs); + p.format = out.GetStyle(out.GetStyleId("Heading" + FormatInt(ex.level))).format; + p.Unpack(pack, objs, p.format); + p.format.label = tname + lbl; + out.Set(t, p, out.GetStyles()); + } + } + } +} + +//RichText MakeStdIndex( + +RichBook::RichBook(Size pg) +: page_size(pg) +{ + RichStyle toc1, toc2, toc3, toc4; + RichPara::Tab& t1tab = toc1.format.tab.Add(); + t1tab.pos = pg.cx - 300; + t1tab.align = ALIGN_RIGHT; + t1tab.fillchar = 1; + toc2 = toc3 = toc4 = toc1; + t1tab.fillchar = 0; + + toc1.name = "Toc1"; + (Font&)toc1.format = Arial(90).Bold(); + toc1.format.indent = 100; + toc1.format.before = 100; + toc1.format.number[0] = RichPara::NUMBER_1; + + toc2.name = "Toc2"; + (Font&)toc2.format = Arial(84).Bold(); + toc2.format.indent = 200; + toc2.format.lm = 200; + toc2.format.number[0] = toc2.format.number[1] = RichPara::NUMBER_1; + + toc3.name = "Toc3"; + (Font&)toc3.format = Arial(84); + toc3.format.indent = 300; + toc3.format.lm = 300; + toc3.format.number[0] = toc3.format.number[1] = toc3.format.number[2] = RichPara::NUMBER_1; + + toc4.name = "Toc4"; + toc4.format.number[0] = toc4.format.number[1] = toc4.format.number[2] = toc4.format.number[3] = RichPara::NUMBER_1; + + RichStyle head1, head2, head3, head4; + head1.name = "Heading1"; + (Font&)head1.format = Arial(144).Bold(); + head1.format.newpage = true; + head1.format.before = 300; + head1.format.after = 100; + head1.format.indent = 150; + head1.format.number[0] = RichPara::NUMBER_1; + + head2.name = "Heading2"; + (Font&)head2.format = Arial(120).Bold(); + head2.format.before = 200; + head2.format.after = 100; + head2.format.indent = 200; + head2.format.number[0] = head2.format.number[1] = RichPara::NUMBER_1; + + head3.name = "Heading3"; + (Font&)head3.format = Arial(100).Bold(); + head3.format.before = 100; + head3.format.after = 50; + head3.format.indent = 250; + head3.format.number[0] = head3.format.number[1] = head3.format.number[2] = RichPara::NUMBER_1; + + head4 = head3; + head4.name = "Heading4"; + head4.format.number[0] = head4.format.number[1] = head4.format.number[2] = head4.format.number[3] = RichPara::NUMBER_1; + + default_styles.Add(Uuid::Create(), toc1); + default_styles.Add(Uuid::Create(), toc2); + default_styles.Add(Uuid::Create(), toc3); + default_styles.Add(Uuid::Create(), toc4); + + default_styles.Add(Uuid::Create(), head1); + default_styles.Add(Uuid::Create(), head2); + default_styles.Add(Uuid::Create(), head3); + default_styles.Add(Uuid::Create(), head4); +} + +RichPrintSection& RichBook::AddSection() +{ + RichText init; + init.OverrideStyles(default_styles); + return sections.Add(new RichPrintSection(default_section, init)); +} + +Vector RichBook::Print(Size pagesize, Gate2 progress) +{ + Vector out; + int pos = 0; + + VectorMap vars; + vars.GetAdd("$book") = 1; + bool stable = false; + enum { MAX_PASSES = 10 }; + int pass; + for(pass = 1; !stable && pass <= MAX_PASSES; pass++) { + if(progress(pass, 0)) + throw AbortExc(); + stable = true; + int pageno = 1; + Index chkdup; + for(int s = 0; s < sections.GetCount(); s++) { + RichPrintSection& psec = sections[s]; + if(psec.text.GetPartCount() > 0 && psec.text.IsPara(0)) { + RichPara p0 = psec.text.Get(0); + if(p0.format.newpage) { + p0.format.newpage = false; + psec.text.Set(0, p0, psec.text.GetStyles()); + } + } + Size textsize = psec.GetTextSize(pagesize); + PageY begin; + pageno = Nvl(psec.firstpage, pageno); + psec.text.EvaluateFields(vars); + int numpages = psec.text.GetHeight(textsize).page / psec.columns + 1; + Vector posinfo = psec.text.GetValPos(textsize, RichText::LABELS); + for(int i = 0; i < posinfo.GetCount(); i++) { + String key = posinfo[i].data.ToString() + "$page"; + if(chkdup.Find(key) >= 0) { + if(pass == 1) + RLOG("Duplicate: " << key); + continue; + } + chkdup.Add(key); + int oldpage = vars.Get(key, Value()); + int newpage = pageno + posinfo[i].py.page; + if(newpage != oldpage) { + if(pass > 2) + RLOG("Unstable: " << key << ": " << oldpage << " -> " << newpage); + vars.GetAdd(key) = newpage; + stable = false; + } + } + pageno += numpages; + } + } + for(int i = 0; i < sections.GetCount(); i++) + out.AppendPick(sections[i].Print(pagesize, progress, pos)); +#ifdef _DEBUG + RichText symtext; + Vector order = GetSortOrder(vars.GetKeys()); + for(int o = 0; o < order.GetCount(); o++) { + RichPara para; + para.Cat(NFormat("<%s> %vt", vars.GetKey(order[o]), vars[order[o]]), para.format); + symtext.Cat(para); + } + RichPrintSection symsec(default_section, symtext); + out.AppendPick(symsec.Print(pagesize, progress, pos)); +#endif + return out; +} + +void CreateHelpBook(RichBook& book) +{ + Progress progress(t_("Typesetting page %d...")); + DocReport report; + Vector pages = book.Print(report.GetPageSize(), progress); + progress.SetText(t_("Printing page %d...")); + for(int i = 0; i < pages.GetCount(); i++) { + if(progress.SetCanceled(i, pages.GetCount())) + throw AbortExc(); + if(i) + report.NextPage(); + report.DrawDrawing(pages[i].GetSize(), pages[i]); + } + report.Perform(); +} + +String CreateHelpPDF(RichBook& book) +{ + PdfDraw pdf(210 * 6000 / 254, 297 * 6000 / 254); + Rect margin = Rect(pdf.GetPagePixels()).Deflated(236); + Progress progress(t_("Typesetting...")); + Vector pages = book.Print(margin.Size(), progress); + progress.SetText(t_("Exporting PDF...")); + progress.SetTotal(pages.GetCount()); + for(int i = 0; i < pages.GetCount(); i++) { + if(progress.StepCanceled()) + throw AbortExc(); + pdf.StartPage(); + pdf.DrawDrawing(margin, pages[i]); + pdf.EndPage(); + } + return pdf.Finish(); +} + +String CreateHelpRTF(RichBook& book, byte charset) +{ + RichText richtext; + for(int i = 0; i < book.sections.GetCount(); i++) + richtext.CatPick(book.sections[i].text); + return EncodeRTF(richtext, charset); +} + +RichBookHtml::RichBookHtml() +{ +} + +void RichBookHtml::AddFile(String url, String data) +{ +} + +void RichBookHtml::AddImage(String url, String data) +{ +} + +String RichBookHtml::GetURLFile(String url) const +{ + String out; + return out; +} + +void CreateHelpHtml(RichBook& book, RichBookHtml& html) +{ +} + +GLOBAL_VAR(Callback1, DefaultBook) + +void CreateDefaultBook() +{ + RichBook book; + DefaultBook()(book); + CreateHelpBook(book); +} + +void CreateDefaultPDF() +{ + RichBook book; + DefaultBook()(book); + try { + String data = CreateHelpPDF(book); + FileSelector fsel; + fsel.Type(t_("PDF documents (*.pdf)"), "*.pdf") + .DefaultExt("pdf") + .AllFilesType(); + static String recent; + fsel <<= recent; + if(fsel.ExecuteSaveAs(t_("PDF export"))) { + recent = ~fsel; + if(!SaveFile(recent, data)) + throw Exc(NFormat("Error saving file '%s' (%d B).", recent, data.GetLength())); + } + } + catch(Exc e) { + ShowExc(e); + } +} + +void CreateDefaultRTF() +{ + RichBook book; + DefaultBook()(book); + try { + String data = CreateHelpRTF(book, GetDefaultCharset()); + FileSelector fsel; + fsel.Type(t_("Rich text documents (*.rtf)"), "*.rtf") + .DefaultExt("rtf") + .AllFilesType(); + static String recent; + fsel <<= recent; + if(fsel.ExecuteSaveAs(t_("Save manual as"))) { + recent = ~fsel; + if(!SaveFile(recent, data)) + throw Exc(NFormat("Error saving file '%s' (%d B).", recent, data.GetLength())); + } + } + catch(Exc e) { + ShowExc(e); + } +} + +void CreateDefaultHTML() +{ + RichBook book; + DefaultBook()(book); + try { + RichBookHtml html; + CreateHelpHtml(book, html); + } + catch(Exc e) { + ShowExc(e); + } +} + +void ManualMenu() +{ + MenuBar menu; + bool isdb = DefaultBook(); + menu.Add(isdb, t_("Print manual"), callback(&CreateDefaultBook)); + menu.Add(isdb, t_("PDF export"), callback(&CreateDefaultPDF)); + menu.Add(isdb, t_("RTF export"), callback(&CreateDefaultRTF)); + menu.Add(isdb, t_("HTML export"), callback(&CreateDefaultHTML)); + menu.Execute(); +} + +void HelpBookMenu(Bar& bar) +{ + bar.Add(t_("Save manual"), CtrlImg::save(), callback(&ManualMenu)); +} + +} diff --git a/uppsrc/RichBook/RichBook.h b/archive/RichBook/RichBook.h similarity index 96% rename from uppsrc/RichBook/RichBook.h rename to archive/RichBook/RichBook.h index 63630b6f7..15d9a96a3 100644 --- a/uppsrc/RichBook/RichBook.h +++ b/archive/RichBook/RichBook.h @@ -1,134 +1,134 @@ -#ifndef _RichBook_RichBook_h -#define _RichBook_RichBook_h - -#include - -namespace Upp { - -RichPara::FieldType& FieldTypeVar(); -Id FieldTypeVarID(); - -class RichIndexEntry : DeepCopyOption -{ -public: - RichIndexEntry() {} - RichIndexEntry(const RichIndexEntry& rti, bool deep) : reflist(rti.reflist, deep) {} - -public: - Vector reflist; -}; - -RichPara::FieldType& FieldTypeIndexEntry(); -Id FieldTypeIndexEntryID(); -String EncodeIndexEntry(const RichIndexEntry& idx); -RichIndexEntry DecodeIndexEntry(String encoded_indexentry); - -class RichBookSection { -public: - RichBookSection(); - - Rect GetPageRect(Size pagesize) const; - Rect GetTextRect(Size pagesize, int columnindex) const; - Size GetTextSize(Size pagesize) const; - -public: - bool nested; - int columns; - int firstpage; - Rect margin; - int header_space; - int footer_space; - int column_space; - String header[3], footer[3]; - RichPara::CharFormat charformat; -}; - -class RichPrintSection : public RichBookSection { -public: - RichPrintSection(const RichBookSection& s, pick_ RichText& t) - : RichBookSection(s), text(t) {} - - Vector Print(Size pagesize, Gate2 progress, int& progress_pos) const; - -public: - RichText text; -}; - -class RichTocEntry { -public: - RichTocEntry(String topic = Null, int level = 1, bool numbered = true, bool appendix = false, WString text = Null) - : topic(topic), level(level), numbered(numbered), text(text) {} - - String topic; - int level; - bool numbered; - bool appendix; - WString text; -}; - -class RichToc : DeepCopyOption { -public: - RichToc() {} - RichToc(const RichToc& rtoc, int deep) : entries(rtoc.entries, deep) {} - - void Add(String topic, int level, bool numbered = true, bool appendix = false, WString text = Null) - { entries.Add(new RichTocEntry(topic, level, numbered, appendix, text)); } - - Array entries; -}; - -void MakeOnlineToc(RichText& out, const RichToc& toc); -void MakeStdToc(RichText& out, const RichToc& toc, int print_width); -void MakeTocTopics(RichText& out, const RichToc& toc); -//RichText MakeStdIndex( - -class RichBook { -public: - RichBook(Size page_size = Size(3968, 6074)); - - RichPrintSection& AddSection(); - - Vector Print(Size pagesize, Gate2 progress); - -public: - Size page_size; - RichBookSection default_section; - RichStyles default_styles; - enum { TOC_DEPTH = 4 }; - Array sections; -}; - -void CreateHelpBook(RichBook& book); -String CreateHelpPDF(RichBook& book); -String CreateHelpRTF(RichBook& book, byte charset); - -class RichBookHtml { -public: - RichBookHtml(); - - void AddFile(String url, String data); - void AddImage(String url, String data); - String GetURLFile(String url) const; - -public: - String output_path; - enum { STYLE_DEEP, STYLE_FLAT, STYLE_ONEFILE }; - int style; - VectorMap files; - VectorMap images; -}; - -void CreateHelpHtml(const RichBook& book, RichBookHtml& html); - -Callback1& DefaultBook(); - -void CreateDefaultBook(); -void CreateDefaultPDF(); -void CreateDefaultRTF(); -void CreateDefaultHTML(); - -void HelpBookMenu(Bar& bar); - -} - -#endif +#ifndef _RichBook_RichBook_h +#define _RichBook_RichBook_h + +#include + +namespace Upp { + +RichPara::FieldType& FieldTypeVar(); +Id FieldTypeVarID(); + +class RichIndexEntry : DeepCopyOption +{ +public: + RichIndexEntry() {} + RichIndexEntry(const RichIndexEntry& rti, bool deep) : reflist(rti.reflist, deep) {} + +public: + Vector reflist; +}; + +RichPara::FieldType& FieldTypeIndexEntry(); +Id FieldTypeIndexEntryID(); +String EncodeIndexEntry(const RichIndexEntry& idx); +RichIndexEntry DecodeIndexEntry(String encoded_indexentry); + +class RichBookSection { +public: + RichBookSection(); + + Rect GetPageRect(Size pagesize) const; + Rect GetTextRect(Size pagesize, int columnindex) const; + Size GetTextSize(Size pagesize) const; + +public: + bool nested; + int columns; + int firstpage; + Rect margin; + int header_space; + int footer_space; + int column_space; + String header[3], footer[3]; + RichPara::CharFormat charformat; +}; + +class RichPrintSection : public RichBookSection { +public: + RichPrintSection(const RichBookSection& s, pick_ RichText& t) + : RichBookSection(s), text(t) {} + + Vector Print(Size pagesize, Gate2 progress, int& progress_pos) const; + +public: + RichText text; +}; + +class RichTocEntry { +public: + RichTocEntry(String topic = Null, int level = 1, bool numbered = true, bool appendix = false, WString text = Null) + : topic(topic), level(level), numbered(numbered), text(text) {} + + String topic; + int level; + bool numbered; + bool appendix; + WString text; +}; + +class RichToc : DeepCopyOption { +public: + RichToc() {} + RichToc(const RichToc& rtoc, int deep) : entries(rtoc.entries, deep) {} + + void Add(String topic, int level, bool numbered = true, bool appendix = false, WString text = Null) + { entries.Add(new RichTocEntry(topic, level, numbered, appendix, text)); } + + Array entries; +}; + +void MakeOnlineToc(RichText& out, const RichToc& toc); +void MakeStdToc(RichText& out, const RichToc& toc, int print_width); +void MakeTocTopics(RichText& out, const RichToc& toc); +//RichText MakeStdIndex( + +class RichBook { +public: + RichBook(Size page_size = Size(3968, 6074)); + + RichPrintSection& AddSection(); + + Vector Print(Size pagesize, Gate2 progress); + +public: + Size page_size; + RichBookSection default_section; + RichStyles default_styles; + enum { TOC_DEPTH = 4 }; + Array sections; +}; + +void CreateHelpBook(RichBook& book); +String CreateHelpPDF(RichBook& book); +String CreateHelpRTF(RichBook& book, byte charset); + +class RichBookHtml { +public: + RichBookHtml(); + + void AddFile(String url, String data); + void AddImage(String url, String data); + String GetURLFile(String url) const; + +public: + String output_path; + enum { STYLE_DEEP, STYLE_FLAT, STYLE_ONEFILE }; + int style; + VectorMap files; + VectorMap images; +}; + +void CreateHelpHtml(const RichBook& book, RichBookHtml& html); + +Callback1& DefaultBook(); + +void CreateDefaultBook(); +void CreateDefaultPDF(); +void CreateDefaultRTF(); +void CreateDefaultHTML(); + +void HelpBookMenu(Bar& bar); + +} + +#endif diff --git a/uppsrc/RichBook/RichBook.t b/archive/RichBook/RichBook.t similarity index 94% rename from uppsrc/RichBook/RichBook.t rename to archive/RichBook/RichBook.t index 1be4fc304..2bfa537ab 100644 --- a/uppsrc/RichBook/RichBook.t +++ b/archive/RichBook/RichBook.t @@ -1,38 +1,38 @@ - -// RichBook.cpp - -T_("Typesetting page %d...") -csCZ("Sázím stranu %d...") - -T_("Printing page %d...") -csCZ("Tisknu stranu %d...") - -T_("Typesetting...") -csCZ("Sázím...") - -T_("Exporting PDF...") -csCZ("Exportuji PDF...") - -T_("PDF documents (*.pdf)") -csCZ("Dokumenty PDF (*.pdf)") - -T_("PDF export") -csCZ("Export PDF") - -T_("Rich text documents (*.rtf)") -csCZ("Dokumenty Rich text (*.rtf)") - -T_("Save manual as") -csCZ("Uložit příručku jako") - -T_("Print manual") -csCZ("Tisk příručky") - -T_("RTF export") -csCZ("Export do RTF") - -T_("HTML export") -csCZ("Export do HTML") - -T_("Save manual") -csCZ("Uložit příručku") + +// RichBook.cpp + +T_("Typesetting page %d...") +csCZ("Sázím stranu %d...") + +T_("Printing page %d...") +csCZ("Tisknu stranu %d...") + +T_("Typesetting...") +csCZ("Sázím...") + +T_("Exporting PDF...") +csCZ("Exportuji PDF...") + +T_("PDF documents (*.pdf)") +csCZ("Dokumenty PDF (*.pdf)") + +T_("PDF export") +csCZ("Export PDF") + +T_("Rich text documents (*.rtf)") +csCZ("Dokumenty Rich text (*.rtf)") + +T_("Save manual as") +csCZ("Uložit příručku jako") + +T_("Print manual") +csCZ("Tisk příručky") + +T_("RTF export") +csCZ("Export do RTF") + +T_("HTML export") +csCZ("Export do HTML") + +T_("Save manual") +csCZ("Uložit příručku") diff --git a/uppsrc/RichBook/RichBook.upp b/archive/RichBook/RichBook.upp similarity index 91% rename from uppsrc/RichBook/RichBook.upp rename to archive/RichBook/RichBook.upp index be67ca334..1434e3afc 100644 --- a/uppsrc/RichBook/RichBook.upp +++ b/archive/RichBook/RichBook.upp @@ -1,9 +1,9 @@ -uses - RichText, - CtrlLib; - -file - RichBook.h, - RichBook_init.icpp, - RichBook.t, - RichBook.cpp; +uses + RichText, + CtrlLib; + +file + RichBook.h, + RichBook_init.icpp, + RichBook.t, + RichBook.cpp; diff --git a/uppsrc/RichBook/RichBook_init.icpp b/archive/RichBook/RichBook_init.icpp similarity index 92% rename from uppsrc/RichBook/RichBook_init.icpp rename to archive/RichBook/RichBook_init.icpp index 96e3c053e..cad4d0d72 100644 --- a/uppsrc/RichBook/RichBook_init.icpp +++ b/archive/RichBook/RichBook_init.icpp @@ -1,8 +1,8 @@ -#include "RichBook.h" - -namespace Upp { - -#define TFILE -#include - -} +#include "RichBook.h" + +namespace Upp { + +#define TFILE +#include + +} diff --git a/uppsrc/PaintGL/Copying b/archive/uppsrc/Docedit/Copying similarity index 100% rename from uppsrc/PaintGL/Copying rename to archive/uppsrc/Docedit/Copying diff --git a/uppsrc/Docedit/DocItem.cpp b/archive/uppsrc/Docedit/DocItem.cpp similarity index 95% rename from uppsrc/Docedit/DocItem.cpp rename to archive/uppsrc/Docedit/DocItem.cpp index 42b181199..f74185469 100644 --- a/uppsrc/Docedit/DocItem.cpp +++ b/archive/uppsrc/Docedit/DocItem.cpp @@ -1,346 +1,346 @@ -#include "Docedit.h" - -#define IMAGECLASS DppImg -#define IMAGEFILE -#include - -bool IsCppKeyword(const String& id) -{ - static Index kw; - if(kw.GetCount() == 0) - for(int i = 0; CppKeyword[i]; i++) - kw.Add(CppKeyword[i]); - return kw.Find(id) >= 0; -} - -void DocItemDisplay::Paint(Draw& w, const Rect& r, const Value& q, - Color _ink, Color paper, dword style) const -{ - ValueArray va = q; - String txt = va.Get(0); - String name = va.Get(1); - int kind = va.Get(2); - int access = va.Get(3); - int status = va.Get(4); - String pname = va.Get(5); - String tname = va.Get(6); - Color c = Color(230, 255, 230); - switch(status) { - case DocDir::IGNORED: c = SGray; break; - case DocDir::OBSOLETELINK: - case DocDir::OBSOLETE: c = SLtRed; break; - case DocDir::UNDOCUMENTED: c = paper; break; - } - w.DrawRect(r, style & (FOCUS|CURSOR) ? paper : c); - if(IsNull(q)) return; - int x0 = r.left; - if(access == PROTECTED) - w.DrawImage(x0, r.top + 1, DppImg::Protected()); - x0 += 6; - Image img = DppImg::Other(); - switch(kind) { - case FUNCTION: - img = DppImg::Function(); - break; - case INSTANCEFUNCTION: - img = DppImg::InstanceFunction(); - break; - case CLASSFUNCTION: - img = DppImg::ClassFunction(); - break; - case FUNCTIONTEMPLATE: - img = DppImg::FunctionTemplate(); - break; - case INSTANCEFUNCTIONTEMPLATE: - img = DppImg::InstanceFunctionTemplate(); - break; - case CLASSFUNCTIONTEMPLATE: - img = DppImg::ClassFunctionTemplate(); - break; - case STRUCT: - img = DppImg::Struct(); - break; - case STRUCTTEMPLATE: - img = DppImg::StructTemplate(); - break; - case INSTANCEVARIABLE: - img = DppImg::InstanceVariable(); - break; - case CLASSVARIABLE: - img = DppImg::ClassVariable(); - break; - case VARIABLE: - img = DppImg::Variable(); - break; - case ENUM: - img = DppImg::Enum(); - break; - case INLINEFRIEND: - img = DppImg::InlineFriend(); - break; - case TYPEDEF: - img = DppImg::Typedef(); - break; - case CONSTRUCTOR: - img = DppImg::Constructor(); - break; - case DESTRUCTOR: - img = DppImg::Destructor(); - break; - case MACRO: - img = DppImg::Macro(); - break; - } - if(style & (CURSOR|FOCUS)) - DrawHighlightImage(w, x0, r.top + 1, img); - else - w.DrawImage(x0, r.top + 1, img); - x0 += 20; - int x = x0; - int y = r.top + 2; - const char *s = txt; - while(*s && y < r.bottom) { - Font f = Arial(11); - Color ink = SBlack; - int n = 1; - if(*s >= '0' && *s <= '9') { - while(s[n] >= '0' && s[n] <= '9') - n++; - ink = SRed; - } - else - if(iscid(*s)) { - if(strncmp(s, name, name.GetLength()) == 0 && !iscid(s[name.GetLength()])) { - f = Arial(11).Bold(); - n = name.GetLength(); - name.Clear(); - } - else { - String id; - n = 0; - while(IsAlNum(s[n]) || s[n] == '_') { - id.Cat(s[n]); - n++; - } - if(IsCppKeyword(id)) - ink = SLtBlue; - else - if(InScList(id, pname)) { - ink = SRed; - f = Arial(11).Bold(); - } - else - if(InScList(id, tname)) { - ink = SGreen; - f = Arial(11).Bold(); - } - } - } - else - ink = SMagenta; - if(style & (CURSOR|FOCUS)) ink = _ink; - Size fsz = w.GetTextSize(s, f, n); - if(x + fsz.cx >= r.right && fsz.cx < r.Width()) { - if(x0 + 70 < r.right) - x = x0 + 24; - else - x = x0; - y += fsz.cy; - } - w.DrawText(x, y, s, f, ink, n); - x += fsz.cx; - s += n; - } -} - -void DocNestDisplay::Paint(Draw& w, const Rect& r, const Value& q, - Color _ink, Color paper, dword style) const -{ - String text = q; - w.DrawRect(r, paper); - if(IsNull(text)) { - w.DrawText(r.left, r.top, "Globals", Arial(11).Bold().Italic(), - style & (CURSOR|FOCUS) ? _ink : SBlue); - return; - } - int x = r.left; - int y = r.top; - const char *s = text; - Font idf = Arial(11).Bold(); - Color idink = SBlack; - while(*s && y < r.bottom) { - Font f = Arial(11); - Color ink = SBlack; - int n = 1; - if(*s >= '0' && *s <= '9') { - while(s[n] >= '0' && s[n] <= '9') - n++; - ink = SRed; - } - else - if(iscid(*s)) { - String id; - n = 0; - while(IsAlNum(s[n]) || s[n] == '_') { - id.Cat(s[n]); - n++; - } - if(IsCppKeyword(id)) { - ink = SLtBlue; - if(id == "class" || id == "typename") - idink = SGreen; - } - else { - ink = idink; - f = idf; - idink = SBlack; - idf = Arial(11); - } - } - else { - ink = SMagenta; - if(*s == ':') { - idf = Arial(11).Bold(); - idink = SBlack; - } - } - if(style & (CURSOR|FOCUS)) ink = _ink; - Size fsz = w.GetTextSize(s, f, n); - w.DrawText(x, y, s, f, ink, n); - x += fsz.cx; - s += n; - } -} - -int GetItemHeight(const String& txt, const String& nm, const String& pname, - const String& tname, int cx) -{ - String name = nm; - int x = 26; - int y = ScreenInfo().GetFontInfo(Arial(11)).GetHeight() + 3; - const char *s = txt; - while(*s) { - Font f = Arial(11); - int n = 1; - if(*s >= '0' && *s <= '9') - while(s[n] >= '0' && s[n] <= '9') - n++; - else - if(iscid(*s)) { - if(strncmp(s, name, name.GetLength()) == 0 && !iscid(s[name.GetLength()])) { - f = Arial(11).Bold(); - n = name.GetLength(); - name.Clear(); - } - else { - String id; - n = 0; - while(IsAlNum(s[n]) || s[n] == '_') { - id.Cat(s[n]); - n++; - } - if(!IsCppKeyword(id) && InScList(id, pname) || InScList(id, tname)) - f = Arial(11).Bold(); - } - } - Size fsz = ScreenInfo().GetTextSize(s, f, n); - if(x + fsz.cx >= cx && fsz.cx < cx) { - if(26 + 70 < cx) - x = 26 + 24; - else - x = 26; - y += fsz.cy; - } - x += fsz.cx; - s += n; - } - return y; -} - -void InitItemArray(ArrayCtrl& item) -{ - item.NoHeader(); - item.AddIndex(); - item.AddIndex().Accel(); - item.AddIndex(); - item.AddIndex(); - item.AddIndex(); - item.AddIndex(); - item.AddIndex(); - item.AddIndex(); - item.AddIndex(); - item.AddColumnAt(0, "").Add(1).Add(2).Add(3).Add(4).Add(5).Add(6).Add(7).Add(8) - .SetDisplay(Single()).Accel().HeaderTab().SetMargin(0); - item.HeaderObject().Tab(0).SetMargin(0); -} - -void LoadItems(const DocSet& set, const String& nameing, const String& nesting, ArrayCtrl& item) -{ - const ArrayMap& nt = set.Get(~nameing).Get(nesting); - item.Clear(); - int cx = item.HeaderObject().GetTabWidth(0) - 2 * item.HeaderObject().Tab(0).GetMargin(); - for(int i = 0; i < nt.GetCount(); i++) { - const DocItem& im = nt[i]; - if(im.cppitem) { - item.Add(nt.GetKey(i), im.cppitem->name, im.cppitem->kind, im.cppitem->access, - im.status, im.cppitem->pname, im.cppitem->tname, - im.package, im.cppitem->file, im.cppitem->line); - item.SetLineCy(item.GetCount() - 1, - GetItemHeight(nt.GetKey(i), im.cppitem->name, - im.cppitem->pname, im.cppitem->tname, cx)); - } - else { - item.Add(nt.GetKey(i), Null, Null, Null, im.status, Null, Null, im.package, - Null, Null); - item.SetLineCy(item.GetCount() - 1, - GetItemHeight(nt.GetKey(i), Null, Null, Null, cx)); - } - } -} - -int ByOrder(int a1, int a2, int *order) -{ - if(a1 == a2) return 0; - while(*order != -1) { - if(a1 == *order) return -1; - if(a2 == *order) return 1; - order++; - } - return 0; -} - -int CompareItems(const Vector& row1, const Vector& row2) -{ - int q; - int status_order[] = { - STATUS_UNDOCUMENTED, STATUS_OBSOLETE, STATUS_IGNORED, STATUS_EXTERNAL, STATUS_NORMAL, - -1 - }; - int kind1 = row1[2]; - int kind2 = row2[2]; - if(kind1 != STRUCT && kind2 != STRUCT && kind1 != STRUCTTEMPLATE && kind2 != STRUCTTEMPLATE) { - q = (int)row2[3] - (int)row1[3]; - if(q) return q; - q = ByOrder(row1[4], row2[4], status_order); - if(q) return q; - } - int kind_order[] = { - STRUCT, STRUCTTEMPLATE, - MACRO, - CONSTRUCTOR, DESTRUCTOR, - ENUM, TYPEDEF, - INSTANCEFUNCTION, CLASSFUNCTION, INLINEFRIEND, - INSTANCEVARIABLE, CLASSVARIABLE, - INSTANCEFUNCTION, INSTANCEVARIABLE, - VARIABLE, FUNCTION, FUNCTIONTEMPLATE, - -1 - }; - q = ByOrder(kind1, kind2, kind_order); - if(q) return q; - return strcmp((String)row1[1], (String)row2[1]); -} - -int CompareNests(const Value& v1, const Value& v2) -{ - return strcmp(String(v1), String(v2)); -} +#include "Docedit.h" + +#define IMAGECLASS DppImg +#define IMAGEFILE +#include + +bool IsCppKeyword(const String& id) +{ + static Index kw; + if(kw.GetCount() == 0) + for(int i = 0; CppKeyword[i]; i++) + kw.Add(CppKeyword[i]); + return kw.Find(id) >= 0; +} + +void DocItemDisplay::Paint(Draw& w, const Rect& r, const Value& q, + Color _ink, Color paper, dword style) const +{ + ValueArray va = q; + String txt = va.Get(0); + String name = va.Get(1); + int kind = va.Get(2); + int access = va.Get(3); + int status = va.Get(4); + String pname = va.Get(5); + String tname = va.Get(6); + Color c = Color(230, 255, 230); + switch(status) { + case DocDir::IGNORED: c = SGray; break; + case DocDir::OBSOLETELINK: + case DocDir::OBSOLETE: c = SLtRed; break; + case DocDir::UNDOCUMENTED: c = paper; break; + } + w.DrawRect(r, style & (FOCUS|CURSOR) ? paper : c); + if(IsNull(q)) return; + int x0 = r.left; + if(access == PROTECTED) + w.DrawImage(x0, r.top + 1, DppImg::Protected()); + x0 += 6; + Image img = DppImg::Other(); + switch(kind) { + case FUNCTION: + img = DppImg::Function(); + break; + case INSTANCEFUNCTION: + img = DppImg::InstanceFunction(); + break; + case CLASSFUNCTION: + img = DppImg::ClassFunction(); + break; + case FUNCTIONTEMPLATE: + img = DppImg::FunctionTemplate(); + break; + case INSTANCEFUNCTIONTEMPLATE: + img = DppImg::InstanceFunctionTemplate(); + break; + case CLASSFUNCTIONTEMPLATE: + img = DppImg::ClassFunctionTemplate(); + break; + case STRUCT: + img = DppImg::Struct(); + break; + case STRUCTTEMPLATE: + img = DppImg::StructTemplate(); + break; + case INSTANCEVARIABLE: + img = DppImg::InstanceVariable(); + break; + case CLASSVARIABLE: + img = DppImg::ClassVariable(); + break; + case VARIABLE: + img = DppImg::Variable(); + break; + case ENUM: + img = DppImg::Enum(); + break; + case INLINEFRIEND: + img = DppImg::InlineFriend(); + break; + case TYPEDEF: + img = DppImg::Typedef(); + break; + case CONSTRUCTOR: + img = DppImg::Constructor(); + break; + case DESTRUCTOR: + img = DppImg::Destructor(); + break; + case MACRO: + img = DppImg::Macro(); + break; + } + if(style & (CURSOR|FOCUS)) + DrawHighlightImage(w, x0, r.top + 1, img); + else + w.DrawImage(x0, r.top + 1, img); + x0 += 20; + int x = x0; + int y = r.top + 2; + const char *s = txt; + while(*s && y < r.bottom) { + Font f = Arial(11); + Color ink = SBlack; + int n = 1; + if(*s >= '0' && *s <= '9') { + while(s[n] >= '0' && s[n] <= '9') + n++; + ink = SRed; + } + else + if(iscid(*s)) { + if(strncmp(s, name, name.GetLength()) == 0 && !iscid(s[name.GetLength()])) { + f = Arial(11).Bold(); + n = name.GetLength(); + name.Clear(); + } + else { + String id; + n = 0; + while(IsAlNum(s[n]) || s[n] == '_') { + id.Cat(s[n]); + n++; + } + if(IsCppKeyword(id)) + ink = SLtBlue; + else + if(InScList(id, pname)) { + ink = SRed; + f = Arial(11).Bold(); + } + else + if(InScList(id, tname)) { + ink = SGreen; + f = Arial(11).Bold(); + } + } + } + else + ink = SMagenta; + if(style & (CURSOR|FOCUS)) ink = _ink; + Size fsz = w.GetTextSize(s, f, n); + if(x + fsz.cx >= r.right && fsz.cx < r.Width()) { + if(x0 + 70 < r.right) + x = x0 + 24; + else + x = x0; + y += fsz.cy; + } + w.DrawText(x, y, s, f, ink, n); + x += fsz.cx; + s += n; + } +} + +void DocNestDisplay::Paint(Draw& w, const Rect& r, const Value& q, + Color _ink, Color paper, dword style) const +{ + String text = q; + w.DrawRect(r, paper); + if(IsNull(text)) { + w.DrawText(r.left, r.top, "Globals", Arial(11).Bold().Italic(), + style & (CURSOR|FOCUS) ? _ink : SBlue); + return; + } + int x = r.left; + int y = r.top; + const char *s = text; + Font idf = Arial(11).Bold(); + Color idink = SBlack; + while(*s && y < r.bottom) { + Font f = Arial(11); + Color ink = SBlack; + int n = 1; + if(*s >= '0' && *s <= '9') { + while(s[n] >= '0' && s[n] <= '9') + n++; + ink = SRed; + } + else + if(iscid(*s)) { + String id; + n = 0; + while(IsAlNum(s[n]) || s[n] == '_') { + id.Cat(s[n]); + n++; + } + if(IsCppKeyword(id)) { + ink = SLtBlue; + if(id == "class" || id == "typename") + idink = SGreen; + } + else { + ink = idink; + f = idf; + idink = SBlack; + idf = Arial(11); + } + } + else { + ink = SMagenta; + if(*s == ':') { + idf = Arial(11).Bold(); + idink = SBlack; + } + } + if(style & (CURSOR|FOCUS)) ink = _ink; + Size fsz = w.GetTextSize(s, f, n); + w.DrawText(x, y, s, f, ink, n); + x += fsz.cx; + s += n; + } +} + +int GetItemHeight(const String& txt, const String& nm, const String& pname, + const String& tname, int cx) +{ + String name = nm; + int x = 26; + int y = ScreenInfo().GetFontInfo(Arial(11)).GetHeight() + 3; + const char *s = txt; + while(*s) { + Font f = Arial(11); + int n = 1; + if(*s >= '0' && *s <= '9') + while(s[n] >= '0' && s[n] <= '9') + n++; + else + if(iscid(*s)) { + if(strncmp(s, name, name.GetLength()) == 0 && !iscid(s[name.GetLength()])) { + f = Arial(11).Bold(); + n = name.GetLength(); + name.Clear(); + } + else { + String id; + n = 0; + while(IsAlNum(s[n]) || s[n] == '_') { + id.Cat(s[n]); + n++; + } + if(!IsCppKeyword(id) && InScList(id, pname) || InScList(id, tname)) + f = Arial(11).Bold(); + } + } + Size fsz = ScreenInfo().GetTextSize(s, f, n); + if(x + fsz.cx >= cx && fsz.cx < cx) { + if(26 + 70 < cx) + x = 26 + 24; + else + x = 26; + y += fsz.cy; + } + x += fsz.cx; + s += n; + } + return y; +} + +void InitItemArray(ArrayCtrl& item) +{ + item.NoHeader(); + item.AddIndex(); + item.AddIndex().Accel(); + item.AddIndex(); + item.AddIndex(); + item.AddIndex(); + item.AddIndex(); + item.AddIndex(); + item.AddIndex(); + item.AddIndex(); + item.AddColumnAt(0, "").Add(1).Add(2).Add(3).Add(4).Add(5).Add(6).Add(7).Add(8) + .SetDisplay(Single()).Accel().HeaderTab().SetMargin(0); + item.HeaderObject().Tab(0).SetMargin(0); +} + +void LoadItems(const DocSet& set, const String& nameing, const String& nesting, ArrayCtrl& item) +{ + const ArrayMap& nt = set.Get(~nameing).Get(nesting); + item.Clear(); + int cx = item.HeaderObject().GetTabWidth(0) - 2 * item.HeaderObject().Tab(0).GetMargin(); + for(int i = 0; i < nt.GetCount(); i++) { + const DocItem& im = nt[i]; + if(im.cppitem) { + item.Add(nt.GetKey(i), im.cppitem->name, im.cppitem->kind, im.cppitem->access, + im.status, im.cppitem->pname, im.cppitem->tname, + im.package, im.cppitem->file, im.cppitem->line); + item.SetLineCy(item.GetCount() - 1, + GetItemHeight(nt.GetKey(i), im.cppitem->name, + im.cppitem->pname, im.cppitem->tname, cx)); + } + else { + item.Add(nt.GetKey(i), Null, Null, Null, im.status, Null, Null, im.package, + Null, Null); + item.SetLineCy(item.GetCount() - 1, + GetItemHeight(nt.GetKey(i), Null, Null, Null, cx)); + } + } +} + +int ByOrder(int a1, int a2, int *order) +{ + if(a1 == a2) return 0; + while(*order != -1) { + if(a1 == *order) return -1; + if(a2 == *order) return 1; + order++; + } + return 0; +} + +int CompareItems(const Vector& row1, const Vector& row2) +{ + int q; + int status_order[] = { + STATUS_UNDOCUMENTED, STATUS_OBSOLETE, STATUS_IGNORED, STATUS_EXTERNAL, STATUS_NORMAL, + -1 + }; + int kind1 = row1[2]; + int kind2 = row2[2]; + if(kind1 != STRUCT && kind2 != STRUCT && kind1 != STRUCTTEMPLATE && kind2 != STRUCTTEMPLATE) { + q = (int)row2[3] - (int)row1[3]; + if(q) return q; + q = ByOrder(row1[4], row2[4], status_order); + if(q) return q; + } + int kind_order[] = { + STRUCT, STRUCTTEMPLATE, + MACRO, + CONSTRUCTOR, DESTRUCTOR, + ENUM, TYPEDEF, + INSTANCEFUNCTION, CLASSFUNCTION, INLINEFRIEND, + INSTANCEVARIABLE, CLASSVARIABLE, + INSTANCEFUNCTION, INSTANCEVARIABLE, + VARIABLE, FUNCTION, FUNCTIONTEMPLATE, + -1 + }; + q = ByOrder(kind1, kind2, kind_order); + if(q) return q; + return strcmp((String)row1[1], (String)row2[1]); +} + +int CompareNests(const Value& v1, const Value& v2) +{ + return strcmp(String(v1), String(v2)); +} diff --git a/uppsrc/Docedit/DocLink.cpp b/archive/uppsrc/Docedit/DocLink.cpp similarity index 95% rename from uppsrc/Docedit/DocLink.cpp rename to archive/uppsrc/Docedit/DocLink.cpp index 0d27dd0a3..4624c1fae 100644 --- a/uppsrc/Docedit/DocLink.cpp +++ b/archive/uppsrc/Docedit/DocLink.cpp @@ -1,114 +1,114 @@ -#include "Docedit.h" - -void DocLinkDlg::Nameing() -{ - nesting.Clear(); - if(IsNull(nameing)) { - Nesting(); - return; - } - const VectorMap >& 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 DocLinkDlg::Nesting() -{ - item.Clear(); - if(!nesting.IsCursor()) { - Item(); - return; - } - LoadItems(*set, ~nameing, nesting.GetKey(), item); - if(sort) - item.Sort(CompareItems); - item.GoBegin(); -} - -String DocLinkDlg::Get() -{ - return "dpp://" + String(~nameing) + "/" + String(nesting.GetKey()) + "/" - + String(item.GetKey()); -} - -void DocLinkDlg::Item() -{ - link <<= Get(); - String s = doc_dir.GetText(DocKey(~nameing, nesting.GetKey(), item.GetKey(), lang)); - label.KillCursor(); - label.Clear(); - label.Disable(); - if(IsNull(s)) return; - Array pi = ParseQTF(s).GetPosInfo(Rect(0, 0, 5000, 5000), PageY()); - for(int i = 0; i < pi.GetCount(); i++) - if(pi[i].type == RichPosInfo::LABEL) - label.Add(FromUnicode(pi[i].data, CHARSET_WIN1252)); - if(label.GetCount()) - label.Enable(); -} - -void DocLinkDlg::Label() -{ - if(label.IsCursor()) - link <<= Get() + "#" + String(label.GetKey()); -} - -bool DocLinkDlg::Perform(const DocSet& _set, bool _sort, String& _link, dword _lang, - const String& _nameing, const String& _nesting) -{ - lang = _lang; - set = &_set; - sort = _sort; - nameing.Clear(); - for(int i = 0; i < _set.GetCount(); i++) - nameing.Add(_set.GetKey(i)); - if(nameing.GetCount()) - nameing.SetIndex(0); - if(!IsNull(_nameing) && nameing.HasKey(_nameing)) - nameing <<= _nameing; - Nameing(); - if(!IsNull(_nesting)) - nesting.FindSetCursor(_nesting); - link <<= _link; - link.SetFocus(); - if(Execute() == IDOK) { - link.AddHistory(); - _link = link; - return true; - } - return false; -} - -DocLinkDlg::DocLinkDlg() -{ - CtrlLayoutOKCancel(*this, "Link"); - nesting.AddColumn().SetDisplay(Single()); - nesting.NoHeader().NoGrid(); - nameing <<= THISBACK(Nameing); - nesting.WhenEnterRow = THISBACK(Nesting); - InitItemArray(item); - item.WhenLeftClick = THISBACK(Item); - label.NoHeader().NoGrid(); - label.AddColumn(); - label.WhenLeftClick = THISBACK(Label); -} - -bool ParseLink(const String& link, DocKey& key, String& label) -{ - if(memcmp(link, "dpp://", 6)) return false; - Vector p = Split(~link + 6, '/', false); - if(p.GetCount() != 3) return false; - key.nameing = p[0]; - key.nesting = p[1]; - key.item = p[2]; - int q = key.item.Find('#'); - label = Null; - if(q < 0) return true; - label = key.item.Mid(q + 1); - key.item = key.item.Mid(0, q); - return true; -} +#include "Docedit.h" + +void DocLinkDlg::Nameing() +{ + nesting.Clear(); + if(IsNull(nameing)) { + Nesting(); + return; + } + const VectorMap >& 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 DocLinkDlg::Nesting() +{ + item.Clear(); + if(!nesting.IsCursor()) { + Item(); + return; + } + LoadItems(*set, ~nameing, nesting.GetKey(), item); + if(sort) + item.Sort(CompareItems); + item.GoBegin(); +} + +String DocLinkDlg::Get() +{ + return "dpp://" + String(~nameing) + "/" + String(nesting.GetKey()) + "/" + + String(item.GetKey()); +} + +void DocLinkDlg::Item() +{ + link <<= Get(); + String s = doc_dir.GetText(DocKey(~nameing, nesting.GetKey(), item.GetKey(), lang)); + label.KillCursor(); + label.Clear(); + label.Disable(); + if(IsNull(s)) return; + Array pi = ParseQTF(s).GetPosInfo(Rect(0, 0, 5000, 5000), PageY()); + for(int i = 0; i < pi.GetCount(); i++) + if(pi[i].type == RichPosInfo::LABEL) + label.Add(FromUnicode(pi[i].data, CHARSET_WIN1252)); + if(label.GetCount()) + label.Enable(); +} + +void DocLinkDlg::Label() +{ + if(label.IsCursor()) + link <<= Get() + "#" + String(label.GetKey()); +} + +bool DocLinkDlg::Perform(const DocSet& _set, bool _sort, String& _link, dword _lang, + const String& _nameing, const String& _nesting) +{ + lang = _lang; + set = &_set; + sort = _sort; + nameing.Clear(); + for(int i = 0; i < _set.GetCount(); i++) + nameing.Add(_set.GetKey(i)); + if(nameing.GetCount()) + nameing.SetIndex(0); + if(!IsNull(_nameing) && nameing.HasKey(_nameing)) + nameing <<= _nameing; + Nameing(); + if(!IsNull(_nesting)) + nesting.FindSetCursor(_nesting); + link <<= _link; + link.SetFocus(); + if(Execute() == IDOK) { + link.AddHistory(); + _link = link; + return true; + } + return false; +} + +DocLinkDlg::DocLinkDlg() +{ + CtrlLayoutOKCancel(*this, "Link"); + nesting.AddColumn().SetDisplay(Single()); + nesting.NoHeader().NoGrid(); + nameing <<= THISBACK(Nameing); + nesting.WhenEnterRow = THISBACK(Nesting); + InitItemArray(item); + item.WhenLeftClick = THISBACK(Item); + label.NoHeader().NoGrid(); + label.AddColumn(); + label.WhenLeftClick = THISBACK(Label); +} + +bool ParseLink(const String& link, DocKey& key, String& label) +{ + if(memcmp(link, "dpp://", 6)) return false; + Vector p = Split(~link + 6, '/', false); + if(p.GetCount() != 3) return false; + key.nameing = p[0]; + key.nesting = p[1]; + key.item = p[2]; + int q = key.item.Find('#'); + label = Null; + if(q < 0) return true; + label = key.item.Mid(q + 1); + key.item = key.item.Mid(0, q); + return true; +} diff --git a/uppsrc/Docedit/Docbase.cpp b/archive/uppsrc/Docedit/Docbase.cpp similarity index 95% rename from uppsrc/Docedit/Docbase.cpp rename to archive/uppsrc/Docedit/Docbase.cpp index 97a509ebb..67f9edb32 100644 --- a/uppsrc/Docedit/Docbase.cpp +++ b/archive/uppsrc/Docedit/Docbase.cpp @@ -1,66 +1,66 @@ -#include "Docedit.h" - -String PackageDirectory(const String& name) -{ - return AppendFileName("F:/uppsrc", name); -} - -String SourcePath(const String& package, const String& name) -{ - return AppendFileName(PackageDirectory(package), name); -} - -String CommonPath(const String& filename) -{ - return AppendFileName("f:/theide", filename); -} - -DocBase doc_base; - -void DocBase::RemoveFile(const String& file) -{ - CppBase base; - CppBase& doc_base = *this; - for(int i = 0; i < doc_base.GetCount(); i++) { - String m = doc_base.GetKey(i); - CppNamespace& mm = doc_base[i]; - for(int i = 0; i < mm.GetCount(); i++) { - String n = mm.GetKey(i); - CppNest& nn = mm[i]; - for(int i = 0; i < nn.GetCount(); i++) { - CppItem& q = nn[i]; - if(q.file != file) - base.GetAdd(m).GetAdd(n).GetAdd(nn.GetKey(i)) = q; - } - } - } - doc_base = base; -} - -void DocBase::ParseFile(const String& file, const String& package) throw(CParser::Error) -{ - Parse(FileIn(file), ignore, doc_base, package, file); -} - -void DocBase::RefreshFile(const String& file, const String& package) throw(CParser::Error) -{ - RemoveFile(file); - ParseFile(file, package); -} - -Vector DocBase::GetHeaders() -{ - Index h; - for(int i = 0; i < doc_base.GetCount(); i++) { - String m = doc_base.GetKey(i); - CppNamespace& mm = doc_base[i]; - for(int i = 0; i < mm.GetCount(); i++) { - String n = mm.GetKey(i); - CppNest& nn = mm[i]; - for(int i = 0; i < nn.GetCount(); i++) { - h.FindAdd(nn[i].file); - } - } - } - return h.PickKeys(); -} +#include "Docedit.h" + +String PackageDirectory(const String& name) +{ + return AppendFileName("F:/uppsrc", name); +} + +String SourcePath(const String& package, const String& name) +{ + return AppendFileName(PackageDirectory(package), name); +} + +String CommonPath(const String& filename) +{ + return AppendFileName("f:/theide", filename); +} + +DocBase doc_base; + +void DocBase::RemoveFile(const String& file) +{ + CppBase base; + CppBase& doc_base = *this; + for(int i = 0; i < doc_base.GetCount(); i++) { + String m = doc_base.GetKey(i); + CppNamespace& mm = doc_base[i]; + for(int i = 0; i < mm.GetCount(); i++) { + String n = mm.GetKey(i); + CppNest& nn = mm[i]; + for(int i = 0; i < nn.GetCount(); i++) { + CppItem& q = nn[i]; + if(q.file != file) + base.GetAdd(m).GetAdd(n).GetAdd(nn.GetKey(i)) = q; + } + } + } + doc_base = base; +} + +void DocBase::ParseFile(const String& file, const String& package) throw(CParser::Error) +{ + Parse(FileIn(file), ignore, doc_base, package, file); +} + +void DocBase::RefreshFile(const String& file, const String& package) throw(CParser::Error) +{ + RemoveFile(file); + ParseFile(file, package); +} + +Vector DocBase::GetHeaders() +{ + Index h; + for(int i = 0; i < doc_base.GetCount(); i++) { + String m = doc_base.GetKey(i); + CppNamespace& mm = doc_base[i]; + for(int i = 0; i < mm.GetCount(); i++) { + String n = mm.GetKey(i); + CppNest& nn = mm[i]; + for(int i = 0; i < nn.GetCount(); i++) { + h.FindAdd(nn[i].file); + } + } + } + return h.PickKeys(); +} diff --git a/uppsrc/Docedit/Docdir.cpp b/archive/uppsrc/Docedit/Docdir.cpp similarity index 95% rename from uppsrc/Docedit/Docdir.cpp rename to archive/uppsrc/Docedit/Docdir.cpp index 590fb2749..391afff99 100644 --- a/uppsrc/Docedit/Docdir.cpp +++ b/archive/uppsrc/Docedit/Docdir.cpp @@ -1,511 +1,511 @@ -#include "Docedit.h" - -bool DocKey::operator==(const DocKey& b) const -{ - return nameing == b.nameing && nesting == b.nesting && item == b.item && lang == b.lang; -} - -dword GetHashValue(const DocKey& k) -{ - return CombineHash(GetHashValue(k.nameing), GetHashValue(k.nesting), - GetHashValue(k.item)) << k.lang; -} - -int CharFilterNameing(int c) -{ - return c == ':' ? '_' : c; -} - -String DocFile(const String& package, const String& name) -{ - return AppendFileName(SourcePath(package, "doc.dpp"), name); -} - -Time GetFileTime(const char *path) -{ - FindFile ff(path); - return ff ? Time(ff.GetLastWriteTime()) : Null; -} - -void CreateDocDir(const String& package) -{ - ::CreateDirectory(SourcePath(package, "doc.dpp"), 0); -} - -String AsCode(const DocKey& k) -{ - return AsCString(k.nameing) + ", " + AsCString(k.nesting) + ", " + - AsCString(k.item) + ", " + AsCString(LNGAsText(k.lang)); -} - -bool ReadCode(CParser& p, DocKey& key) -{ - if(!p.IsString()) return false; - key.nameing = p.ReadString(); - if(!p.Char(',') || !p.IsString()) return false; - key.nesting = p.ReadString(); - if(!p.Char(',') || !p.IsString()) return false; - key.item = p.ReadString(); - if(!p.Char(',') || !p.IsString()) return false; - key.lang = LNGFromText(p.ReadString()); - return true; -} - -void DocDir::SaveLinks(const String& package) const -{ - CreateDocDir(package); - FileOut out(DocFile(package, "links")); - int q = dir.Find(package); - if(q >= 0) { - const ArrayMap& p = dir[q]; - for(int i = 0; i < p.GetCount(); i++) { - const Entry& w = p[i]; - const DocKey& k = p.GetKey(i); - if(w.type == LINK) - out << "LINK(" << AsCode(k) << ", " << AsCString(w.text) << ")\r\n"; - if(w.type == IGNORED) - out << "IGNORED(" << AsCode(k) << ")\r\n"; - } - } -} - -void DocDir::SaveDir(const String& package) const -{ - CreateDocDir(package); - FileOut out(DocFile(package, "dir.h")); - int q = dir.Find(package); - if(q >= 0) { - const ArrayMap& p = dir[q]; - for(int i = 0; i < p.GetCount(); i++) { - const Entry& w = p[i]; - if(w.type == NORMAL || w.type == EXTERNAL) { - const DocKey& k = p.GetKey(i); - out << "#ifdef INCLUDE_NAMESPACE_" << - Filter(k.nameing, CharFilterNameing) << "\r\n"; - out << "//" << k.item << "\r\n"; - out << "//" << k.nesting << "\r\n"; - out << "//" << k.nameing << "\r\n"; - out << "#include \"doc.dpp/"; - out << w.text; - out << "\" //"; - if(w.type == EXTERNAL) - out << "*"; - out << LNGAsText(k.lang) << "\r\n"; - out << "#endif\r\n\r\n"; - } - } - } - SaveLinks(package); -} - -bool DocDir::LoadLinks(const String& package) -{ - String f = LoadFile(DocFile(package, "links")); - CParser p(f); - ArrayMap& pk = dir.GetAdd(package); - try { - while(!p.IsEof()) { - if(p.Id("LINK")) { - DocKey key; - p.PassChar('('); - if(!ReadCode(p, key)) return false; - p.PassChar(','); - String link = p.ReadString(); - p.PassChar(')'); - Entry& e = pk.GetAdd(key); - e.text = link; - e.type = LINK; - } - if(p.Id("IGNORED")) { - DocKey key; - p.PassChar('('); - if(!ReadCode(p, key)) return false; - p.PassChar(')'); - Entry& e = pk.GetAdd(key); - e.text.Clear(); - e.type = IGNORED; - } - } - return true; - } - catch(CParser::Error) { - return false; - } -} - -bool DocDir::LoadDir(const String& package) -{ - ArrayMap& p = dir.GetAdd(package); - p.Clear(); - LoadLinks(package); - FileIn in(DocFile(package, "dir.h")); - int q = 0; - String d[3]; - while(!in.IsEof()) { - String l = in.GetLine(); - if(memcmp(l, "#include ", 9) == 0) { - const char *b = strchr(l, '/'); - if(!b) return false; - const char *e = strchr(b + 1, '\"'); - if(!e) return false; - String fn = String(b + 1, e); - e = strchr(e, '/'); - if(!e || e[1] != '/') return false; - e += 2; - int type = NORMAL; - if(*e == '*') { - type = EXTERNAL; - e++; - } - Entry& w = p.GetAdd(DocKey(d[2], d[1], d[0], LNGFromText(e))); - w.text = fn; - w.type = type; - q = 0; - } - if(l[0] == '/' && l[1] == '/') { - if(q >= 3) return false; - d[q] = l.Mid(2); - q++; - } - } - return true; -} - -int DocDir::ReadDocHeader(const char *filename, DocKey& key) -{ - FileIn in(filename); - if(!in) return -1; - String l = in.GetLine(); - CParser p(l); - if(!p.Id("ITEM") || !p.Char('(') || !ReadCode(p, key)) return -1; - p.Char(')'); - if(p.Id("EXTERNAL")) - return EXTERNAL; - return NORMAL; -} - -void DocDir::RebuildDir(const String& package) -{ - FindFile ff(DocFile(package, "*.dpp")); - Progress pi("Rebuilding " + package + " doc directory %d"); - ArrayMap& p = dir.GetAdd(package); - p.Clear(); - LoadLinks(package); - while(ff) { - DocKey key; - pi.Step(); - int q = ReadDocHeader(DocFile(package, ff.GetName()), key); - if(q >= 0) { - Entry& w = p.GetAdd(key); - w.text = ff.GetName(); - w.type = q; - } - ff.Next(); - } - SaveDir(package); -} - -void DocDir::Refresh(const String& package) -{ - FindFile ff(DocFile(package, "dir.h")); - if(!ff) { - RebuildDir(package); - return; - } - FileTime dirtime = ff.GetLastWriteTime(); - ff.Search(DocFile(package, "links")); - if(ff && ff.GetLastWriteTime() > dirtime) { - RebuildDir(package); - return; - } - const ArrayMap& p = dir.GetAdd(package); - Index dfn; - for(int i = 0; i < p.GetCount(); i++) - if(p[i].type == NORMAL || p[i].type == EXTERNAL) - dfn.Add(p[i].text); - ff.Search(DocFile(package, "*.dpp")); - int count = 0; - while(ff) { - DocKey key; - if(dfn.Find(ff.GetName()) >= 0) - if(ff.GetLastWriteTime() > dirtime) { - RebuildDir(package); - return; - } - else - count++; - else - if(ReadDocHeader(DocFile(package, ff.GetName()), key) >= 0) { - RebuildDir(package); - return; - } - ff.Next(); - } - if(count != dfn.GetCount()) - RebuildDir(package); -} - -int CharFilterLNG_(int c) -{ - return c == '-' ? '_' : c; -} - -String DocDir::GetAddFileName(const String& package, const DocKey& key, int type) -{ - Entry& w = dir.GetAdd(package).GetAdd(key); - String& fn = w.text; - w.type = type; - if(!IsEmpty(fn)) return fn; - String nm = key.nameing + '_' + key.nesting + '_' + key.item; - String n; - const char *s = nm; - while(*s && n.GetLength() < 30) - if(iscid(*s)) - n.Cat(*s++); - else { - n.Cat('_'); - while(*s && !iscid(*s)) - s++; - } - n << '_' << LNGAsText(key.lang); - int i = 0; - for(;;) { - fn = n + FormatIntAlpha(i) + ".dpp"; - if(!FindFile(DocFile(package, fn))) - return fn; - i++; - } -} - -bool DocDir::GetFileName(const DocKey& key, String& fn, String& package) -{ - dword hv = GetHashValue(key); - for(int i = 0; i < dir.GetCount(); i++) { - const ArrayMap& p = dir[i]; - int q = p.Find(key, hv); - if(q >= 0) { - fn = p[q].text; - package = dir.GetKey(i); - return true; - } - } - return false; -} - -void DocDir::RemoveOtherKey(const DocKey& key, int t1, int t2) -{ - dword hv = GetHashValue(key); - for(int i = 0; i < dir.GetCount(); i++) { - int q = dir[i].Find(key, hv); - if(q >= 0) { - Entry& e = dir[i][q]; - if(e.type != t1 && e.type != t2) { - if(e.type == NORMAL || e.type == EXTERNAL) - DeleteFile(DocFile(dir.GetKey(i), dir[i][q].text)); - dir[i].Remove(q); - } - SaveDir(dir.GetKey(i)); - SaveLinks(dir.GetKey(i)); - } - } -} - -void DocDir::Remove(const DocKey& k) -{ - RemoveOtherKey(k, UNDOCUMENTED, UNDOCUMENTED); -} - -void DocDir::SaveText(const String& package, const DocKey& k, const String& text, bool external) -{ - RemoveOtherKey(k, NORMAL, EXTERNAL); - CreateDocDir(package); - String fn = DocFile(package, GetAddFileName(package, k, external ? EXTERNAL : NORMAL)); - FileOut out(fn); - out << "ITEM(" << AsCode(k) << ")"; - if(external) - out << " EXTERNAL"; - out << "\r\n"; - int n = 0; - for(;;) { - int m = min(text.GetLength() - n, 2048); - if(m == 0) break; - out << "TEXT(\r\n\t"; - out << AsCString(~text + n, ~text + n + m, 64, "\t") << "\r\n"; - out << ")\r\n"; - n += m; - } - out << "END_ITEM\r\n"; - SaveDir(package); - SaveLinks(package); -} - -void DocDir::SaveLink(const String& package, const DocKey& key, const String& text) -{ - RemoveOtherKey(key, LINK); - Entry& w = dir.GetAdd(package).GetAdd(key); - w.text = text; - w.type = LINK; - SaveLinks(package); -} - -void DocDir::Ignore(const String& package, const DocKey& key) -{ - RemoveOtherKey(key, IGNORED); - Entry& w = dir.GetAdd(package).GetAdd(key); - w.type = IGNORED; - SaveLinks(package); -} - -DocDir::Entry *DocDir::Find(const DocKey& key, String& package) const -{ - dword hv = GetHashValue(key); - for(int i = 0; i < dir.GetCount(); i++) { - int q = dir[i].Find(key, hv); - if(q >= 0) { - package = dir.GetKey(i); - return const_cast(&dir[i][q]); - } - } - return NULL; -} - -DocDir::Entry *DocDir::Find(const DocKey& key) const -{ - String dm; - return Find(key, dm); -} - -int DocDir::GetStatus(const DocKey& key) -{ - DocDir::Entry *e = Find(key); - return e ? e->type : UNDOCUMENTED; -} - -int DocDir::GetStatus(const String& nameing, const String& nesting, const String& item, - int lang) -{ - return GetStatus(DocKey(nameing, nesting, item, lang)); -} - -String DocDir::GetFilePath(const DocKey& key) const -{ - String package; - Entry *e = Find(key, package); - if(!e || e->type != NORMAL && e->type != EXTERNAL) return Null; - return DocFile(package, e->text); -} - -String DocDir::GetPackage(const DocKey& key) const -{ - String package; - Entry *e = Find(key, package); - return e ? package : Null; -} - -String DocDir::GetText(const DocKey& key) const -{ - String s = LoadFile(GetFilePath(key)); - if(s.IsEmpty()) return Null; - CParser p(s); - DocKey dummy; - if(!p.Id("ITEM") || !p.Char('(') || !ReadCode(p, dummy)) return "Invalid file"; - p.Char(')'); - p.Id("EXTERNAL"); - String text; - while(p.Id("TEXT")) { - p.Char('('); - if(p.IsString()) - text.Cat(p.ReadString()); - else - return "Invalid file"; - p.Char(')'); - } - return p.Id("END_ITEM") ? text : "Invalid file"; -} - -String DocDir::GetLink(const DocKey& key) const -{ - DocDir::Entry *e = Find(key); - if(!e) return Null; - return e->type == LINK ? e->text : Null; -} - -bool Contains(const DocSet& r, const DocKey& key) -{ - int q = r.Find(key.nameing); - if(q < 0) return false; - int w = r[q].Find(key.nesting); - if(w < 0) return false; - return r[q][w].Find(key.item) >= 0; -} - -bool Contains(const String& big, const String& part) -{ - if(part.GetLength() > big.GetLength()) return false; - const char *s = big; - const char *e = s + big.GetLength() - part.GetLength(); - int l = part.GetLength(); - while(s <= e) { - if(memcmp(s, part, l) == 0) - return true; - s++; - } - return false; -} - -DocSet DocDir::Select(const DocQuery& query) -{ - DocSet r; - CppBase base; - int i; - for(i = 0; i < doc_base.GetCount(); i++) { - String nameing = doc_base.GetKey(i); - CppNamespace& mm = doc_base[i]; - for(int i = 0; i < mm.GetCount(); i++) { - String nesting = mm.GetKey(i); - CppNest& nn = mm[i]; - for(int i = 0; i < nn.GetCount(); i++) { - CppItem& q = nn[i]; - String item = nn.GetKey(i); - if((query.name.IsEmpty() || query.name == q.name) && - (query.text.IsEmpty() || Contains(item, query.text)) && - (query.package.IsEmpty() || q.package.CompareNoCase(query.package) == 0) && - (query.header.IsEmpty() || q.file.CompareNoCase(query.header) == 0)) { - String pk; - const Entry *e = Find(DocKey(nameing, nesting, item, query.lang), pk); - int st = e ? e->type : UNDOCUMENTED; - if((query.undocumented || e) && (st != IGNORED || query.ignored)) { - DocItem& a = r.GetAdd(nameing).GetAdd(nesting).GetAdd(item); - a.cppitem = &q; - a.item = item; - a.status = st; - a.package = e ? pk : q.package; - } - } - } - } - } - for(i = 0; i < dir.GetCount(); i++) { - ArrayMap& pk = dir[i]; - String package = dir.GetKey(i); - for(int j = 0; j < pk.GetCount(); j++) { - const DocKey& k = pk.GetKey(j); - if(k.lang == query.lang && - query.name.IsEmpty() && - (query.text.IsEmpty() || Contains(k.item, query.text)) && - (query.package.IsEmpty() || package.CompareNoCase(query.package) == 0) && - query.header.IsEmpty() && - !Contains(r, k)) { - DocItem& a = r.GetAdd(k.nameing).GetAdd(k.nesting).GetAdd(k.item); - a.cppitem = NULL; - a.item = k.item; - int st = pk[j].type; - a.status = st == NORMAL ? OBSOLETE : st == LINK ? OBSOLETELINK : st; - a.package = package; - } - } - } - return r; -} - -DocDir doc_dir; +#include "Docedit.h" + +bool DocKey::operator==(const DocKey& b) const +{ + return nameing == b.nameing && nesting == b.nesting && item == b.item && lang == b.lang; +} + +dword GetHashValue(const DocKey& k) +{ + return CombineHash(GetHashValue(k.nameing), GetHashValue(k.nesting), + GetHashValue(k.item)) << k.lang; +} + +int CharFilterNameing(int c) +{ + return c == ':' ? '_' : c; +} + +String DocFile(const String& package, const String& name) +{ + return AppendFileName(SourcePath(package, "doc.dpp"), name); +} + +Time GetFileTime(const char *path) +{ + FindFile ff(path); + return ff ? Time(ff.GetLastWriteTime()) : Null; +} + +void CreateDocDir(const String& package) +{ + ::CreateDirectory(SourcePath(package, "doc.dpp"), 0); +} + +String AsCode(const DocKey& k) +{ + return AsCString(k.nameing) + ", " + AsCString(k.nesting) + ", " + + AsCString(k.item) + ", " + AsCString(LNGAsText(k.lang)); +} + +bool ReadCode(CParser& p, DocKey& key) +{ + if(!p.IsString()) return false; + key.nameing = p.ReadString(); + if(!p.Char(',') || !p.IsString()) return false; + key.nesting = p.ReadString(); + if(!p.Char(',') || !p.IsString()) return false; + key.item = p.ReadString(); + if(!p.Char(',') || !p.IsString()) return false; + key.lang = LNGFromText(p.ReadString()); + return true; +} + +void DocDir::SaveLinks(const String& package) const +{ + CreateDocDir(package); + FileOut out(DocFile(package, "links")); + int q = dir.Find(package); + if(q >= 0) { + const ArrayMap& p = dir[q]; + for(int i = 0; i < p.GetCount(); i++) { + const Entry& w = p[i]; + const DocKey& k = p.GetKey(i); + if(w.type == LINK) + out << "LINK(" << AsCode(k) << ", " << AsCString(w.text) << ")\r\n"; + if(w.type == IGNORED) + out << "IGNORED(" << AsCode(k) << ")\r\n"; + } + } +} + +void DocDir::SaveDir(const String& package) const +{ + CreateDocDir(package); + FileOut out(DocFile(package, "dir.h")); + int q = dir.Find(package); + if(q >= 0) { + const ArrayMap& p = dir[q]; + for(int i = 0; i < p.GetCount(); i++) { + const Entry& w = p[i]; + if(w.type == NORMAL || w.type == EXTERNAL) { + const DocKey& k = p.GetKey(i); + out << "#ifdef INCLUDE_NAMESPACE_" << + Filter(k.nameing, CharFilterNameing) << "\r\n"; + out << "//" << k.item << "\r\n"; + out << "//" << k.nesting << "\r\n"; + out << "//" << k.nameing << "\r\n"; + out << "#include \"doc.dpp/"; + out << w.text; + out << "\" //"; + if(w.type == EXTERNAL) + out << "*"; + out << LNGAsText(k.lang) << "\r\n"; + out << "#endif\r\n\r\n"; + } + } + } + SaveLinks(package); +} + +bool DocDir::LoadLinks(const String& package) +{ + String f = LoadFile(DocFile(package, "links")); + CParser p(f); + ArrayMap& pk = dir.GetAdd(package); + try { + while(!p.IsEof()) { + if(p.Id("LINK")) { + DocKey key; + p.PassChar('('); + if(!ReadCode(p, key)) return false; + p.PassChar(','); + String link = p.ReadString(); + p.PassChar(')'); + Entry& e = pk.GetAdd(key); + e.text = link; + e.type = LINK; + } + if(p.Id("IGNORED")) { + DocKey key; + p.PassChar('('); + if(!ReadCode(p, key)) return false; + p.PassChar(')'); + Entry& e = pk.GetAdd(key); + e.text.Clear(); + e.type = IGNORED; + } + } + return true; + } + catch(CParser::Error) { + return false; + } +} + +bool DocDir::LoadDir(const String& package) +{ + ArrayMap& p = dir.GetAdd(package); + p.Clear(); + LoadLinks(package); + FileIn in(DocFile(package, "dir.h")); + int q = 0; + String d[3]; + while(!in.IsEof()) { + String l = in.GetLine(); + if(memcmp(l, "#include ", 9) == 0) { + const char *b = strchr(l, '/'); + if(!b) return false; + const char *e = strchr(b + 1, '\"'); + if(!e) return false; + String fn = String(b + 1, e); + e = strchr(e, '/'); + if(!e || e[1] != '/') return false; + e += 2; + int type = NORMAL; + if(*e == '*') { + type = EXTERNAL; + e++; + } + Entry& w = p.GetAdd(DocKey(d[2], d[1], d[0], LNGFromText(e))); + w.text = fn; + w.type = type; + q = 0; + } + if(l[0] == '/' && l[1] == '/') { + if(q >= 3) return false; + d[q] = l.Mid(2); + q++; + } + } + return true; +} + +int DocDir::ReadDocHeader(const char *filename, DocKey& key) +{ + FileIn in(filename); + if(!in) return -1; + String l = in.GetLine(); + CParser p(l); + if(!p.Id("ITEM") || !p.Char('(') || !ReadCode(p, key)) return -1; + p.Char(')'); + if(p.Id("EXTERNAL")) + return EXTERNAL; + return NORMAL; +} + +void DocDir::RebuildDir(const String& package) +{ + FindFile ff(DocFile(package, "*.dpp")); + Progress pi("Rebuilding " + package + " doc directory %d"); + ArrayMap& p = dir.GetAdd(package); + p.Clear(); + LoadLinks(package); + while(ff) { + DocKey key; + pi.Step(); + int q = ReadDocHeader(DocFile(package, ff.GetName()), key); + if(q >= 0) { + Entry& w = p.GetAdd(key); + w.text = ff.GetName(); + w.type = q; + } + ff.Next(); + } + SaveDir(package); +} + +void DocDir::Refresh(const String& package) +{ + FindFile ff(DocFile(package, "dir.h")); + if(!ff) { + RebuildDir(package); + return; + } + FileTime dirtime = ff.GetLastWriteTime(); + ff.Search(DocFile(package, "links")); + if(ff && ff.GetLastWriteTime() > dirtime) { + RebuildDir(package); + return; + } + const ArrayMap& p = dir.GetAdd(package); + Index dfn; + for(int i = 0; i < p.GetCount(); i++) + if(p[i].type == NORMAL || p[i].type == EXTERNAL) + dfn.Add(p[i].text); + ff.Search(DocFile(package, "*.dpp")); + int count = 0; + while(ff) { + DocKey key; + if(dfn.Find(ff.GetName()) >= 0) + if(ff.GetLastWriteTime() > dirtime) { + RebuildDir(package); + return; + } + else + count++; + else + if(ReadDocHeader(DocFile(package, ff.GetName()), key) >= 0) { + RebuildDir(package); + return; + } + ff.Next(); + } + if(count != dfn.GetCount()) + RebuildDir(package); +} + +int CharFilterLNG_(int c) +{ + return c == '-' ? '_' : c; +} + +String DocDir::GetAddFileName(const String& package, const DocKey& key, int type) +{ + Entry& w = dir.GetAdd(package).GetAdd(key); + String& fn = w.text; + w.type = type; + if(!IsEmpty(fn)) return fn; + String nm = key.nameing + '_' + key.nesting + '_' + key.item; + String n; + const char *s = nm; + while(*s && n.GetLength() < 30) + if(iscid(*s)) + n.Cat(*s++); + else { + n.Cat('_'); + while(*s && !iscid(*s)) + s++; + } + n << '_' << LNGAsText(key.lang); + int i = 0; + for(;;) { + fn = n + FormatIntAlpha(i) + ".dpp"; + if(!FindFile(DocFile(package, fn))) + return fn; + i++; + } +} + +bool DocDir::GetFileName(const DocKey& key, String& fn, String& package) +{ + dword hv = GetHashValue(key); + for(int i = 0; i < dir.GetCount(); i++) { + const ArrayMap& p = dir[i]; + int q = p.Find(key, hv); + if(q >= 0) { + fn = p[q].text; + package = dir.GetKey(i); + return true; + } + } + return false; +} + +void DocDir::RemoveOtherKey(const DocKey& key, int t1, int t2) +{ + dword hv = GetHashValue(key); + for(int i = 0; i < dir.GetCount(); i++) { + int q = dir[i].Find(key, hv); + if(q >= 0) { + Entry& e = dir[i][q]; + if(e.type != t1 && e.type != t2) { + if(e.type == NORMAL || e.type == EXTERNAL) + DeleteFile(DocFile(dir.GetKey(i), dir[i][q].text)); + dir[i].Remove(q); + } + SaveDir(dir.GetKey(i)); + SaveLinks(dir.GetKey(i)); + } + } +} + +void DocDir::Remove(const DocKey& k) +{ + RemoveOtherKey(k, UNDOCUMENTED, UNDOCUMENTED); +} + +void DocDir::SaveText(const String& package, const DocKey& k, const String& text, bool external) +{ + RemoveOtherKey(k, NORMAL, EXTERNAL); + CreateDocDir(package); + String fn = DocFile(package, GetAddFileName(package, k, external ? EXTERNAL : NORMAL)); + FileOut out(fn); + out << "ITEM(" << AsCode(k) << ")"; + if(external) + out << " EXTERNAL"; + out << "\r\n"; + int n = 0; + for(;;) { + int m = min(text.GetLength() - n, 2048); + if(m == 0) break; + out << "TEXT(\r\n\t"; + out << AsCString(~text + n, ~text + n + m, 64, "\t") << "\r\n"; + out << ")\r\n"; + n += m; + } + out << "END_ITEM\r\n"; + SaveDir(package); + SaveLinks(package); +} + +void DocDir::SaveLink(const String& package, const DocKey& key, const String& text) +{ + RemoveOtherKey(key, LINK); + Entry& w = dir.GetAdd(package).GetAdd(key); + w.text = text; + w.type = LINK; + SaveLinks(package); +} + +void DocDir::Ignore(const String& package, const DocKey& key) +{ + RemoveOtherKey(key, IGNORED); + Entry& w = dir.GetAdd(package).GetAdd(key); + w.type = IGNORED; + SaveLinks(package); +} + +DocDir::Entry *DocDir::Find(const DocKey& key, String& package) const +{ + dword hv = GetHashValue(key); + for(int i = 0; i < dir.GetCount(); i++) { + int q = dir[i].Find(key, hv); + if(q >= 0) { + package = dir.GetKey(i); + return const_cast(&dir[i][q]); + } + } + return NULL; +} + +DocDir::Entry *DocDir::Find(const DocKey& key) const +{ + String dm; + return Find(key, dm); +} + +int DocDir::GetStatus(const DocKey& key) +{ + DocDir::Entry *e = Find(key); + return e ? e->type : UNDOCUMENTED; +} + +int DocDir::GetStatus(const String& nameing, const String& nesting, const String& item, + int lang) +{ + return GetStatus(DocKey(nameing, nesting, item, lang)); +} + +String DocDir::GetFilePath(const DocKey& key) const +{ + String package; + Entry *e = Find(key, package); + if(!e || e->type != NORMAL && e->type != EXTERNAL) return Null; + return DocFile(package, e->text); +} + +String DocDir::GetPackage(const DocKey& key) const +{ + String package; + Entry *e = Find(key, package); + return e ? package : Null; +} + +String DocDir::GetText(const DocKey& key) const +{ + String s = LoadFile(GetFilePath(key)); + if(s.IsEmpty()) return Null; + CParser p(s); + DocKey dummy; + if(!p.Id("ITEM") || !p.Char('(') || !ReadCode(p, dummy)) return "Invalid file"; + p.Char(')'); + p.Id("EXTERNAL"); + String text; + while(p.Id("TEXT")) { + p.Char('('); + if(p.IsString()) + text.Cat(p.ReadString()); + else + return "Invalid file"; + p.Char(')'); + } + return p.Id("END_ITEM") ? text : "Invalid file"; +} + +String DocDir::GetLink(const DocKey& key) const +{ + DocDir::Entry *e = Find(key); + if(!e) return Null; + return e->type == LINK ? e->text : Null; +} + +bool Contains(const DocSet& r, const DocKey& key) +{ + int q = r.Find(key.nameing); + if(q < 0) return false; + int w = r[q].Find(key.nesting); + if(w < 0) return false; + return r[q][w].Find(key.item) >= 0; +} + +bool Contains(const String& big, const String& part) +{ + if(part.GetLength() > big.GetLength()) return false; + const char *s = big; + const char *e = s + big.GetLength() - part.GetLength(); + int l = part.GetLength(); + while(s <= e) { + if(memcmp(s, part, l) == 0) + return true; + s++; + } + return false; +} + +DocSet DocDir::Select(const DocQuery& query) +{ + DocSet r; + CppBase base; + int i; + for(i = 0; i < doc_base.GetCount(); i++) { + String nameing = doc_base.GetKey(i); + CppNamespace& mm = doc_base[i]; + for(int i = 0; i < mm.GetCount(); i++) { + String nesting = mm.GetKey(i); + CppNest& nn = mm[i]; + for(int i = 0; i < nn.GetCount(); i++) { + CppItem& q = nn[i]; + String item = nn.GetKey(i); + if((query.name.IsEmpty() || query.name == q.name) && + (query.text.IsEmpty() || Contains(item, query.text)) && + (query.package.IsEmpty() || q.package.CompareNoCase(query.package) == 0) && + (query.header.IsEmpty() || q.file.CompareNoCase(query.header) == 0)) { + String pk; + const Entry *e = Find(DocKey(nameing, nesting, item, query.lang), pk); + int st = e ? e->type : UNDOCUMENTED; + if((query.undocumented || e) && (st != IGNORED || query.ignored)) { + DocItem& a = r.GetAdd(nameing).GetAdd(nesting).GetAdd(item); + a.cppitem = &q; + a.item = item; + a.status = st; + a.package = e ? pk : q.package; + } + } + } + } + } + for(i = 0; i < dir.GetCount(); i++) { + ArrayMap& pk = dir[i]; + String package = dir.GetKey(i); + for(int j = 0; j < pk.GetCount(); j++) { + const DocKey& k = pk.GetKey(j); + if(k.lang == query.lang && + query.name.IsEmpty() && + (query.text.IsEmpty() || Contains(k.item, query.text)) && + (query.package.IsEmpty() || package.CompareNoCase(query.package) == 0) && + query.header.IsEmpty() && + !Contains(r, k)) { + DocItem& a = r.GetAdd(k.nameing).GetAdd(k.nesting).GetAdd(k.item); + a.cppitem = NULL; + a.item = k.item; + int st = pk[j].type; + a.status = st == NORMAL ? OBSOLETE : st == LINK ? OBSOLETELINK : st; + a.package = package; + } + } + } + return r; +} + +DocDir doc_dir; diff --git a/uppsrc/Docedit/Docedit.cpp b/archive/uppsrc/Docedit/Docedit.cpp similarity index 95% rename from uppsrc/Docedit/Docedit.cpp rename to archive/uppsrc/Docedit/Docedit.cpp index 91bdd618d..a8cc8ada5 100644 --- a/uppsrc/Docedit/Docedit.cpp +++ b/archive/uppsrc/Docedit/Docedit.cpp @@ -1,539 +1,539 @@ -#include - -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 >& 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 h = doc_base.GetHeaders(); - for(int i = 0; i < h.GetCount(); i++) - query.header.Add(h[i], GetFileName(h[i])); - query.header.Add(Null, ""); - 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 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()); - 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(); -} +#include + +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 >& 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 h = doc_base.GetHeaders(); + for(int i = 0; i < h.GetCount(); i++) + query.header.Add(h[i], GetFileName(h[i])); + query.header.Add(Null, ""); + 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 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()); + 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(); +} diff --git a/uppsrc/Docedit/Docedit.h b/archive/uppsrc/Docedit/Docedit.h similarity index 96% rename from uppsrc/Docedit/Docedit.h rename to archive/uppsrc/Docedit/Docedit.h index 650f15e89..4dcd2341e 100644 --- a/uppsrc/Docedit/Docedit.h +++ b/archive/uppsrc/Docedit/Docedit.h @@ -1,241 +1,241 @@ -#include -#include - -#define IMAGECLASS DppImg -#define IMAGEFILE -#include - -// before placed to IDE... - -String SourcePath(const String& package, const String& name); -String PackageDirectory(const String& name); -String CommonPath(const String& filename); - -// ------ - -struct DocBase : public CppBase { - Vector DocBase::ignore; - Vector package; - - void RemoveFile(const String& file); - void ParseFile(const String& file, const String& package) throw(Parser::Error); - void RefreshFile(const String& file, const String& package) throw(Parser::Error); - Vector GetHeaders(); - Vector GetPackages(); -}; - -extern DocBase doc_base; - -Time GetFileTime(const char *path); -String DocFile(const String& package, const String& name); - -struct DocKey { - String nameing; - String nesting; - String item; - dword lang; - - bool operator==(const DocKey& b) const; - dword GetHashValue(const DocKey& k); - operator bool() const { return item.GetLength(); } - void Clear() { item.Clear(); nesting.Clear(); nameing.Clear(); lang = 0; } - - DocKey() {} - DocKey(const String& m, const String& n, const String& s, dword l) - : nameing(m), nesting(n), item(s), lang(l) {} -}; - -dword GetHashValue(const DocKey& k); - -struct DocQuery { - String name, text, package, header; - bool undocumented, normal, external, obsolete, ignored; - dword lang; -}; - -struct DocItem { - CppItem *cppitem; - String item; - int status; - String package; -}; - -typedef VectorMap > > DocSet; - -class DocDir { - struct Entry { - int type; - String text; - }; - VectorMap > dir; - - int ReadDocHeader(const char *filename, DocKey& key); - String GetAddFileName(const String& package, const DocKey& key, int type); - bool GetFileName(const DocKey& key, String& fn, String& package); - - bool LoadLinks(const String& package); - void SaveLinks(const String& package) const; - - void RemoveOtherKey(const DocKey& k, int t1, int t2 = UNDOCUMENTED); - Entry *Find(const DocKey& key, String& package) const; - Entry *Find(const DocKey& key) const; - -public: - enum { - NORMAL, EXTERNAL, LINK, IGNORED, - UNDOCUMENTED = -1, OBSOLETE = -2, OBSOLETELINK = -3 - }; - - bool LoadDir(const String& package); - void SaveDir(const String& package) const; - - void RebuildDir(const String& package); - - void Refresh(const String& package); - - int GetStatus(const DocKey& key); - int GetStatus(const String& nameing, const String& nesting, const String& item, int lang); - - String GetFilePath(const DocKey& key) const; - String GetPackage(const DocKey& key) const; - String GetText(const DocKey& key) const; - String GetLink(const DocKey& key) const; - - void Remove(const DocKey& key); - void SaveText(const String& package, const DocKey& key, const String& text, bool external); - void SaveLink(const String& package, const DocKey& key, const String& text); - void Ignore(const String& package, const DocKey& key); - - DocSet Select(const DocQuery& query); -}; - -bool ParseLink(const String& link, DocKey& key, String& label); - -extern DocDir doc_dir; - -#define LAYOUTFILE "DocEdit.lay" -#include - -struct DocItemDisplay : public Display -{ - virtual void Paint(Draw& w, const Rect& r, const Value& q, - Color _ink, Color paper, dword style) const; -}; - -struct DocNestDisplay : public Display -{ - virtual void Paint(Draw& w, const Rect& r, const Value& q, - Color _ink, Color paper, dword style) const; -}; - -void InitItemArray(ArrayCtrl& item); -void LoadItems(const DocSet& set, const String& nameing, const String& nesting, ArrayCtrl& item); -int PosOf(const String& s, const String& subs); -bool IsCppKeyword(const String& id); -int CompareNests(const Value& v1, const Value& v2); -int CompareItems(const Vector& row1, const Vector& row2); - -struct DocLinkDlg : public WithLinkLayout { - const DocSet *set; - bool sort; - dword lang; - - void Nameing(); - void Nesting(); - void Item(); - bool Perform(const DocSet& set, bool sort, String& link, int lang, - const String& nameing = Null, const String& nesting = Null); - void Label(); - String Get(); - - typedef DocLinkDlg CLASSNAME; - - DocLinkDlg(); -}; - -class DocBrowser : public TopWindow { -public: - virtual bool Key(dword key, int count); - virtual void Close(); - -private: - struct FileInfo { - Time time; - RichEdit::UndoInfo info; - }; - - ArrayMap editstate; - ArrayMap posinfo; - - DropList nameing; - StaticRect larea, rarea; - ArrayCtrl nesting; - ArrayCtrl item; - Splitter ni_split; - Splitter vi_split; - - FrameTop trect; - Label title; - DataPusher package; - RichTextView view; - RichEdit edit; - - DropList lang; - - MenuBar menu; - ToolBar tool; - - ToolBar editbar; - - WithQueryLayout query; - DocSet set; - DocKey current, target; - - DocLinkDlg linkdlg; - - bool sort; - - WithExternalLayout external; - - void Nameing(); - void Nesting(); - void Item(); - void EnterItem(); - - void ReloadItems(); - - DocKey Key(); - void Flush(); - int GetCurrentStatus(); - void SetCurrentStatus(int status); - String GetItemPackage() { return item.Get(7); } - - void EditLink(String& s); - - void Edit(); - void View(); - void Sort(); - void Select(); - void Link(); - void Ignore(); - void Delete(); - void New(); - - void FollowLink(const String& s); - - void SetMainBar(); - - void MainMenu(Bar& bar); - void ItemMenu(Bar& bar); - void BrowseMenu(Bar& bar); - - void EditBar(Bar& bar); - void SetEditBar(); - -public: - typedef DocBrowser CLASSNAME; - - void Query(); - - DocBrowser(); -}; +#include +#include + +#define IMAGECLASS DppImg +#define IMAGEFILE +#include + +// before placed to IDE... + +String SourcePath(const String& package, const String& name); +String PackageDirectory(const String& name); +String CommonPath(const String& filename); + +// ------ + +struct DocBase : public CppBase { + Vector DocBase::ignore; + Vector package; + + void RemoveFile(const String& file); + void ParseFile(const String& file, const String& package) throw(Parser::Error); + void RefreshFile(const String& file, const String& package) throw(Parser::Error); + Vector GetHeaders(); + Vector GetPackages(); +}; + +extern DocBase doc_base; + +Time GetFileTime(const char *path); +String DocFile(const String& package, const String& name); + +struct DocKey { + String nameing; + String nesting; + String item; + dword lang; + + bool operator==(const DocKey& b) const; + dword GetHashValue(const DocKey& k); + operator bool() const { return item.GetLength(); } + void Clear() { item.Clear(); nesting.Clear(); nameing.Clear(); lang = 0; } + + DocKey() {} + DocKey(const String& m, const String& n, const String& s, dword l) + : nameing(m), nesting(n), item(s), lang(l) {} +}; + +dword GetHashValue(const DocKey& k); + +struct DocQuery { + String name, text, package, header; + bool undocumented, normal, external, obsolete, ignored; + dword lang; +}; + +struct DocItem { + CppItem *cppitem; + String item; + int status; + String package; +}; + +typedef VectorMap > > DocSet; + +class DocDir { + struct Entry { + int type; + String text; + }; + VectorMap > dir; + + int ReadDocHeader(const char *filename, DocKey& key); + String GetAddFileName(const String& package, const DocKey& key, int type); + bool GetFileName(const DocKey& key, String& fn, String& package); + + bool LoadLinks(const String& package); + void SaveLinks(const String& package) const; + + void RemoveOtherKey(const DocKey& k, int t1, int t2 = UNDOCUMENTED); + Entry *Find(const DocKey& key, String& package) const; + Entry *Find(const DocKey& key) const; + +public: + enum { + NORMAL, EXTERNAL, LINK, IGNORED, + UNDOCUMENTED = -1, OBSOLETE = -2, OBSOLETELINK = -3 + }; + + bool LoadDir(const String& package); + void SaveDir(const String& package) const; + + void RebuildDir(const String& package); + + void Refresh(const String& package); + + int GetStatus(const DocKey& key); + int GetStatus(const String& nameing, const String& nesting, const String& item, int lang); + + String GetFilePath(const DocKey& key) const; + String GetPackage(const DocKey& key) const; + String GetText(const DocKey& key) const; + String GetLink(const DocKey& key) const; + + void Remove(const DocKey& key); + void SaveText(const String& package, const DocKey& key, const String& text, bool external); + void SaveLink(const String& package, const DocKey& key, const String& text); + void Ignore(const String& package, const DocKey& key); + + DocSet Select(const DocQuery& query); +}; + +bool ParseLink(const String& link, DocKey& key, String& label); + +extern DocDir doc_dir; + +#define LAYOUTFILE "DocEdit.lay" +#include + +struct DocItemDisplay : public Display +{ + virtual void Paint(Draw& w, const Rect& r, const Value& q, + Color _ink, Color paper, dword style) const; +}; + +struct DocNestDisplay : public Display +{ + virtual void Paint(Draw& w, const Rect& r, const Value& q, + Color _ink, Color paper, dword style) const; +}; + +void InitItemArray(ArrayCtrl& item); +void LoadItems(const DocSet& set, const String& nameing, const String& nesting, ArrayCtrl& item); +int PosOf(const String& s, const String& subs); +bool IsCppKeyword(const String& id); +int CompareNests(const Value& v1, const Value& v2); +int CompareItems(const Vector& row1, const Vector& row2); + +struct DocLinkDlg : public WithLinkLayout { + const DocSet *set; + bool sort; + dword lang; + + void Nameing(); + void Nesting(); + void Item(); + bool Perform(const DocSet& set, bool sort, String& link, int lang, + const String& nameing = Null, const String& nesting = Null); + void Label(); + String Get(); + + typedef DocLinkDlg CLASSNAME; + + DocLinkDlg(); +}; + +class DocBrowser : public TopWindow { +public: + virtual bool Key(dword key, int count); + virtual void Close(); + +private: + struct FileInfo { + Time time; + RichEdit::UndoInfo info; + }; + + ArrayMap editstate; + ArrayMap posinfo; + + DropList nameing; + StaticRect larea, rarea; + ArrayCtrl nesting; + ArrayCtrl item; + Splitter ni_split; + Splitter vi_split; + + FrameTop trect; + Label title; + DataPusher package; + RichTextView view; + RichEdit edit; + + DropList lang; + + MenuBar menu; + ToolBar tool; + + ToolBar editbar; + + WithQueryLayout query; + DocSet set; + DocKey current, target; + + DocLinkDlg linkdlg; + + bool sort; + + WithExternalLayout external; + + void Nameing(); + void Nesting(); + void Item(); + void EnterItem(); + + void ReloadItems(); + + DocKey Key(); + void Flush(); + int GetCurrentStatus(); + void SetCurrentStatus(int status); + String GetItemPackage() { return item.Get(7); } + + void EditLink(String& s); + + void Edit(); + void View(); + void Sort(); + void Select(); + void Link(); + void Ignore(); + void Delete(); + void New(); + + void FollowLink(const String& s); + + void SetMainBar(); + + void MainMenu(Bar& bar); + void ItemMenu(Bar& bar); + void BrowseMenu(Bar& bar); + + void EditBar(Bar& bar); + void SetEditBar(); + +public: + typedef DocBrowser CLASSNAME; + + void Query(); + + DocBrowser(); +}; diff --git a/uppsrc/Docedit/Docedit.iml b/archive/uppsrc/Docedit/Docedit.iml similarity index 98% rename from uppsrc/Docedit/Docedit.iml rename to archive/uppsrc/Docedit/Docedit.iml index d0449c13d..c3f98a271 100644 --- a/uppsrc/Docedit/Docedit.iml +++ b/archive/uppsrc/Docedit/Docedit.iml @@ -1,53 +1,53 @@ -PREMULTIPLIED -IMAGE_ID(Variable) -IMAGE_ID(SmallIcon) -IMAGE_ID(InstanceVariable) -IMAGE_ID(ClassVariable) -IMAGE_ID(Function) -IMAGE_ID(InstanceFunction) -IMAGE_ID(InlineFriend) -IMAGE_ID(ClassFunction) -IMAGE_ID(FunctionTemplate) -IMAGE_ID(InstanceFunctionTemplate) -IMAGE_ID(ClassFunctionTemplate) -IMAGE_ID(Enum) -IMAGE_ID(Protected) -IMAGE_ID(Struct) -IMAGE_ID(StructTemplate) -IMAGE_ID(Other) -IMAGE_ID(Typedef) -IMAGE_ID(Constructor) -IMAGE_ID(Destructor) -IMAGE_ID(Macro) - -IMAGE_BEGIN_DATA -IMAGE_DATA(120,156,237,152,11,146,131,32,12,134,115,132,30,185,71,243,102,217,105,187,190,32,228,137,21,107,226,48,221,110,249,18) -IMAGE_DATA(192,248,19,129,7,60,0,0,17,86,67,69,147,236,211,175,117,89,252,112,215,119,124,212,227,246,142,225,181,208,136,30) -IMAGE_DATA(31,103,242,209,249,71,214,223,203,70,242,175,71,254,95,211,8,49,104,153,117,17,202,254,210,119,142,71,152,147,88,199) -IMAGE_DATA(151,201,82,242,136,80,249,235,197,215,137,135,184,182,127,118,110,132,143,8,223,78,126,157,143,40,127,246,252,123,220,191) -IMAGE_DATA(30,60,144,243,226,191,247,230,237,118,64,101,64,239,32,58,101,174,110,60,123,145,137,84,240,54,31,60,175,219,25,169) -IMAGE_DATA(249,45,125,179,50,112,198,182,177,89,25,120,44,95,19,12,201,236,123,24,86,31,223,121,152,35,98,132,65,49,228,121) -IMAGE_DATA(121,253,107,222,126,239,34,155,81,185,126,183,23,3,141,69,22,36,178,160,33,22,245,15,111,119,214,201,111,31,13,107) -IMAGE_DATA(114,238,88,170,113,108,171,5,230,178,140,233,4,22,224,188,188,155,249,241,173,33,6,26,245,108,25,181,59,80,190,61) -IMAGE_DATA(188,114,23,37,121,75,50,149,243,79,49,72,49,184,173,24,72,118,187,202,96,154,166,16,235,21,131,153,221,196,87,139) -IMAGE_DATA(193,150,165,62,57,182,213,12,115,169,229,199,42,200,126,182,246,225,207,157,8,187,245,49,190,165,24,124,135,205,202,96) -IMAGE_DATA(29,211,134,181,60,104,53,203,87,160,21,95,244,177,240,212,239,86,158,243,59,134,88,12,46,6,229,98,181,18,73,149) -IMAGE_DATA(76,198,221,125,23,171,96,45,177,223,172,179,178,88,88,111,101,192,53,142,109,181,192,92,150,49,41,88,106,126,220,61) -IMAGE_DATA(80,197,86,246,37,99,7,226,206,204,248,118,128,24,136,73,202,254,70,157,70,235,197,128,61,111,80,36,98,243,188,193) -IMAGE_DATA(32,6,100,18,167,24,172,99,82,176,41,6,103,88,86,6,170,113,102,101,160,23,3,110,92,50,75,111,6,20,75,197) -IMAGE_DATA(57,236,240,89,136,187,247,65,141,235,10,230,20,131,163,141,75,124,233,97,144,94,149,171,86,248,40,255,159,241,239,21) -IMAGE_DATA(31,12,113,61,2,63,174,213,98,240,124,125,193,167,123,146,31,254,253,151,203,71,198,207,248,87,142,127,97,99,42,131) -IMAGE_DATA(136,42,234,133,153,82,101,155,176,215,37,89,242,119,230,163,249,183,250,184,83,85,240,178,163,196,64,122,95,101,222,61) -IMAGE_DATA(165,190,187,70,248,96,251,42,198,144,241,175,29,159,245,209,227,220,164,104,191,99,131,158,25,80,102,175,78,54,173,101) -IMAGE_DATA(28,175,49,137,111,37,97,198,63,63,62,195,138,241,5,22,224,130,34,242,7,126,154,4,137,0,0,0,0,0,0,0) -IMAGE_END_DATA(608, 16) - -IMAGE_BEGIN_DATA -IMAGE_DATA(120,156,237,150,137,13,195,48,8,69,25,33,35,103,52,111,70,213,86,74,28,204,241,125,201,74,90,34,164,28,188,143) -IMAGE_DATA(141,45,28,218,104,35,34,102,26,111,108,56,206,107,23,174,161,243,184,134,205,99,26,62,31,107,196,188,175,49,55,127) -IMAGE_DATA(207,252,123,234,95,179,254,125,251,239,247,172,178,25,212,22,51,143,103,46,23,211,221,140,34,62,122,142,52,172,251,112) -IMAGE_DATA(14,239,88,233,0,123,201,101,240,150,142,202,88,110,105,116,228,31,49,255,131,165,182,250,15,89,127,71,79,126,71,236) -IMAGE_DATA(217,205,100,226,159,193,104,107,237,238,95,102,223,79,199,117,174,156,116,164,33,180,243,62,27,107,172,230,87,215,239,212) -IMAGE_DATA(104,95,255,82,231,201,13,193,105,6,218,233,81,117,162,164,148,62,158,243,202,59,51,175,136,53,223,89,121,17,159,193) -IMAGE_DATA(119,142,255,95,191,181,245,43,198,145,243,64,222,219,218,11,170,178,33,106,0,0,0,0,0,0,0,0,0,0,0,0) -IMAGE_END_DATA(224, 4) +PREMULTIPLIED +IMAGE_ID(Variable) +IMAGE_ID(SmallIcon) +IMAGE_ID(InstanceVariable) +IMAGE_ID(ClassVariable) +IMAGE_ID(Function) +IMAGE_ID(InstanceFunction) +IMAGE_ID(InlineFriend) +IMAGE_ID(ClassFunction) +IMAGE_ID(FunctionTemplate) +IMAGE_ID(InstanceFunctionTemplate) +IMAGE_ID(ClassFunctionTemplate) +IMAGE_ID(Enum) +IMAGE_ID(Protected) +IMAGE_ID(Struct) +IMAGE_ID(StructTemplate) +IMAGE_ID(Other) +IMAGE_ID(Typedef) +IMAGE_ID(Constructor) +IMAGE_ID(Destructor) +IMAGE_ID(Macro) + +IMAGE_BEGIN_DATA +IMAGE_DATA(120,156,237,152,11,146,131,32,12,134,115,132,30,185,71,243,102,217,105,187,190,32,228,137,21,107,226,48,221,110,249,18) +IMAGE_DATA(192,248,19,129,7,60,0,0,17,86,67,69,147,236,211,175,117,89,252,112,215,119,124,212,227,246,142,225,181,208,136,30) +IMAGE_DATA(31,103,242,209,249,71,214,223,203,70,242,175,71,254,95,211,8,49,104,153,117,17,202,254,210,119,142,71,152,147,88,199) +IMAGE_DATA(151,201,82,242,136,80,249,235,197,215,137,135,184,182,127,118,110,132,143,8,223,78,126,157,143,40,127,246,252,123,220,191) +IMAGE_DATA(30,60,144,243,226,191,247,230,237,118,64,101,64,239,32,58,101,174,110,60,123,145,137,84,240,54,31,60,175,219,25,169) +IMAGE_DATA(249,45,125,179,50,112,198,182,177,89,25,120,44,95,19,12,201,236,123,24,86,31,223,121,152,35,98,132,65,49,228,121) +IMAGE_DATA(121,253,107,222,126,239,34,155,81,185,126,183,23,3,141,69,22,36,178,160,33,22,245,15,111,119,214,201,111,31,13,107) +IMAGE_DATA(114,238,88,170,113,108,171,5,230,178,140,233,4,22,224,188,188,155,249,241,173,33,6,26,245,108,25,181,59,80,190,61) +IMAGE_DATA(188,114,23,37,121,75,50,149,243,79,49,72,49,184,173,24,72,118,187,202,96,154,166,16,235,21,131,153,221,196,87,139) +IMAGE_DATA(193,150,165,62,57,182,213,12,115,169,229,199,42,200,126,182,246,225,207,157,8,187,245,49,190,165,24,124,135,205,202,96) +IMAGE_DATA(29,211,134,181,60,104,53,203,87,160,21,95,244,177,240,212,239,86,158,243,59,134,88,12,46,6,229,98,181,18,73,149) +IMAGE_DATA(76,198,221,125,23,171,96,45,177,223,172,179,178,88,88,111,101,192,53,142,109,181,192,92,150,49,41,88,106,126,220,61) +IMAGE_DATA(80,197,86,246,37,99,7,226,206,204,248,118,128,24,136,73,202,254,70,157,70,235,197,128,61,111,80,36,98,243,188,193) +IMAGE_DATA(32,6,100,18,167,24,172,99,82,176,41,6,103,88,86,6,170,113,102,101,160,23,3,110,92,50,75,111,6,20,75,197) +IMAGE_DATA(57,236,240,89,136,187,247,65,141,235,10,230,20,131,163,141,75,124,233,97,144,94,149,171,86,248,40,255,159,241,239,21) +IMAGE_DATA(31,12,113,61,2,63,174,213,98,240,124,125,193,167,123,146,31,254,253,151,203,71,198,207,248,87,142,127,97,99,42,131) +IMAGE_DATA(136,42,234,133,153,82,101,155,176,215,37,89,242,119,230,163,249,183,250,184,83,85,240,178,163,196,64,122,95,101,222,61) +IMAGE_DATA(165,190,187,70,248,96,251,42,198,144,241,175,29,159,245,209,227,220,164,104,191,99,131,158,25,80,102,175,78,54,173,101) +IMAGE_DATA(28,175,49,137,111,37,97,198,63,63,62,195,138,241,5,22,224,130,34,242,7,126,154,4,137,0,0,0,0,0,0,0) +IMAGE_END_DATA(608, 16) + +IMAGE_BEGIN_DATA +IMAGE_DATA(120,156,237,150,137,13,195,48,8,69,25,33,35,103,52,111,70,213,86,74,28,204,241,125,201,74,90,34,164,28,188,143) +IMAGE_DATA(141,45,28,218,104,35,34,102,26,111,108,56,206,107,23,174,161,243,184,134,205,99,26,62,31,107,196,188,175,49,55,127) +IMAGE_DATA(207,252,123,234,95,179,254,125,251,239,247,172,178,25,212,22,51,143,103,46,23,211,221,140,34,62,122,142,52,172,251,112) +IMAGE_DATA(14,239,88,233,0,123,201,101,240,150,142,202,88,110,105,116,228,31,49,255,131,165,182,250,15,89,127,71,79,126,71,236) +IMAGE_DATA(217,205,100,226,159,193,104,107,237,238,95,102,223,79,199,117,174,156,116,164,33,180,243,62,27,107,172,230,87,215,239,212) +IMAGE_DATA(104,95,255,82,231,201,13,193,105,6,218,233,81,117,162,164,148,62,158,243,202,59,51,175,136,53,223,89,121,17,159,193) +IMAGE_DATA(119,142,255,95,191,181,245,43,198,145,243,64,222,219,218,11,170,178,33,106,0,0,0,0,0,0,0,0,0,0,0,0) +IMAGE_END_DATA(224, 4) diff --git a/uppsrc/Docedit/Docedit.lay b/archive/uppsrc/Docedit/Docedit.lay similarity index 98% rename from uppsrc/Docedit/Docedit.lay rename to archive/uppsrc/Docedit/Docedit.lay index 4560f8373..5e1f14410 100644 --- a/uppsrc/Docedit/Docedit.lay +++ b/archive/uppsrc/Docedit/Docedit.lay @@ -1,48 +1,48 @@ -#ifdef LAYOUTFILE - -LAYOUT(QueryLayout, 372, 120) - ITEM(LabelBox, dv___0, LeftPosZ(8, 132).TopPosZ(4, 108).SetLabel("Status")) - ITEM(Switch, status, LeftPosZ(16, 117).TopPosZ(20, 85).SetLabel("Any except ignored\nUndocumented\nObsolete\nIgnored\nAny")) - ITEM(Label, dv___2, LeftPosZ(152, 48).TopPosZ(12, 13).SetLabel("Name")) - ITEM(WithDropChoice, name, LeftPosZ(204, 160).TopPosZ(8, 19)) - ITEM(Label, dv___4, LeftPosZ(152, 48).TopPosZ(36, 13).SetLabel("Contains")) - ITEM(WithDropChoice, text, LeftPosZ(204, 160).TopPosZ(32, 19)) - ITEM(Label, dv___6, LeftPosZ(152, 44).TopPosZ(59, 13).SetLabel("Header")) - ITEM(DropList, header, LeftPosZ(204, 160).TopPosZ(56, 19)) - ITEM(Button, ok, LeftPosZ(232, 64).TopPosZ(88, 24).SetLabel("OK")) - ITEM(Button, cancel, LeftPosZ(300, 64).TopPosZ(88, 24).SetLabel("Cancel")) - ITEM(Button, clear, LeftPosZ(152, 64).TopPosZ(88, 24).SetLabel("Clear")) -END_LAYOUT - -LAYOUT(LinkLayout, 632, 500) - ITEM(Label, dv___0, LeftPosZ(8, 28).TopPosZ(12, 13).SetLabel("Link")) - ITEM(WithDropChoice, link, LeftPosZ(44, 580).TopPosZ(8, 19)) - ITEM(DropList, nameing, LeftPosZ(8, 224).TopPosZ(36, 19)) - ITEM(ArrayCtrl, nesting, LeftPosZ(8, 224).TopPosZ(60, 400)) - ITEM(ArrayCtrl, item, LeftPosZ(240, 384).TopPosZ(36, 300)) - ITEM(ArrayCtrl, label, LeftPosZ(240, 384).TopPosZ(340, 120)) - ITEM(Button, ok, LeftPosZ(492, 64).TopPosZ(468, 24).SetLabel("OK")) - ITEM(Button, cancel, LeftPosZ(560, 64).TopPosZ(468, 24).SetLabel("Cancel")) -END_LAYOUT - -LAYOUT(ExternalLayout, 400, 108) - ITEM(Label, dv___0, LeftPosZ(4, 68).TopPosZ(8, 13).SetLabel("Namespace")) - ITEM(WithDropChoice, nameing, LeftPosZ(80, 76).TopPosZ(4, 19)) - ITEM(Label, dv___2, LeftPosZ(176, 43).TopPosZ(8, 13).SetLabel("Nesting")) - ITEM(WithDropChoice, nesting, LeftPosZ(224, 168).TopPosZ(4, 19)) - ITEM(Label, dv___4, LeftPosZ(4, 28).TopPosZ(31, 13).SetLabel("Item")) - ITEM(EditString, item, LeftPosZ(80, 312).TopPosZ(28, 19)) - ITEM(Label, dv___6, LeftPosZ(4, 72).TopPosZ(56, 13).SetLabel("Host package")) - ITEM(DropList, package, LeftPosZ(80, 100).TopPosZ(52, 19)) - ITEM(Button, ok, LeftPosZ(260, 64).TopPosZ(76, 24).SetLabel("OK")) - ITEM(Button, cancel, LeftPosZ(328, 64).TopPosZ(76, 24).SetLabel("Cancel")) -END_LAYOUT - -LAYOUT(TemplateLayout, 672, 568) - ITEM(Button, ok, LeftPosZ(532, 64).TopPosZ(536, 24).SetLabel("OK")) - ITEM(Button, cancel, LeftPosZ(600, 64).TopPosZ(536, 24).SetLabel("Cancel")) - ITEM(DocEdit, code, LeftPosZ(164, 500).TopPosZ(8, 160)) - ITEM(RichTextView, view, LeftPosZ(164, 500).TopPosZ(172, 352)) -END_LAYOUT - -#endif +#ifdef LAYOUTFILE + +LAYOUT(QueryLayout, 372, 120) + ITEM(LabelBox, dv___0, LeftPosZ(8, 132).TopPosZ(4, 108).SetLabel("Status")) + ITEM(Switch, status, LeftPosZ(16, 117).TopPosZ(20, 85).SetLabel("Any except ignored\nUndocumented\nObsolete\nIgnored\nAny")) + ITEM(Label, dv___2, LeftPosZ(152, 48).TopPosZ(12, 13).SetLabel("Name")) + ITEM(WithDropChoice, name, LeftPosZ(204, 160).TopPosZ(8, 19)) + ITEM(Label, dv___4, LeftPosZ(152, 48).TopPosZ(36, 13).SetLabel("Contains")) + ITEM(WithDropChoice, text, LeftPosZ(204, 160).TopPosZ(32, 19)) + ITEM(Label, dv___6, LeftPosZ(152, 44).TopPosZ(59, 13).SetLabel("Header")) + ITEM(DropList, header, LeftPosZ(204, 160).TopPosZ(56, 19)) + ITEM(Button, ok, LeftPosZ(232, 64).TopPosZ(88, 24).SetLabel("OK")) + ITEM(Button, cancel, LeftPosZ(300, 64).TopPosZ(88, 24).SetLabel("Cancel")) + ITEM(Button, clear, LeftPosZ(152, 64).TopPosZ(88, 24).SetLabel("Clear")) +END_LAYOUT + +LAYOUT(LinkLayout, 632, 500) + ITEM(Label, dv___0, LeftPosZ(8, 28).TopPosZ(12, 13).SetLabel("Link")) + ITEM(WithDropChoice, link, LeftPosZ(44, 580).TopPosZ(8, 19)) + ITEM(DropList, nameing, LeftPosZ(8, 224).TopPosZ(36, 19)) + ITEM(ArrayCtrl, nesting, LeftPosZ(8, 224).TopPosZ(60, 400)) + ITEM(ArrayCtrl, item, LeftPosZ(240, 384).TopPosZ(36, 300)) + ITEM(ArrayCtrl, label, LeftPosZ(240, 384).TopPosZ(340, 120)) + ITEM(Button, ok, LeftPosZ(492, 64).TopPosZ(468, 24).SetLabel("OK")) + ITEM(Button, cancel, LeftPosZ(560, 64).TopPosZ(468, 24).SetLabel("Cancel")) +END_LAYOUT + +LAYOUT(ExternalLayout, 400, 108) + ITEM(Label, dv___0, LeftPosZ(4, 68).TopPosZ(8, 13).SetLabel("Namespace")) + ITEM(WithDropChoice, nameing, LeftPosZ(80, 76).TopPosZ(4, 19)) + ITEM(Label, dv___2, LeftPosZ(176, 43).TopPosZ(8, 13).SetLabel("Nesting")) + ITEM(WithDropChoice, nesting, LeftPosZ(224, 168).TopPosZ(4, 19)) + ITEM(Label, dv___4, LeftPosZ(4, 28).TopPosZ(31, 13).SetLabel("Item")) + ITEM(EditString, item, LeftPosZ(80, 312).TopPosZ(28, 19)) + ITEM(Label, dv___6, LeftPosZ(4, 72).TopPosZ(56, 13).SetLabel("Host package")) + ITEM(DropList, package, LeftPosZ(80, 100).TopPosZ(52, 19)) + ITEM(Button, ok, LeftPosZ(260, 64).TopPosZ(76, 24).SetLabel("OK")) + ITEM(Button, cancel, LeftPosZ(328, 64).TopPosZ(76, 24).SetLabel("Cancel")) +END_LAYOUT + +LAYOUT(TemplateLayout, 672, 568) + ITEM(Button, ok, LeftPosZ(532, 64).TopPosZ(536, 24).SetLabel("OK")) + ITEM(Button, cancel, LeftPosZ(600, 64).TopPosZ(536, 24).SetLabel("Cancel")) + ITEM(DocEdit, code, LeftPosZ(164, 500).TopPosZ(8, 160)) + ITEM(RichTextView, view, LeftPosZ(164, 500).TopPosZ(172, 352)) +END_LAYOUT + +#endif diff --git a/uppsrc/Docedit/Docedit.upp b/archive/uppsrc/Docedit/Docedit.upp similarity index 91% rename from uppsrc/Docedit/Docedit.upp rename to archive/uppsrc/Docedit/Docedit.upp index 6ce06d047..40b910b8e 100644 --- a/uppsrc/Docedit/Docedit.upp +++ b/archive/uppsrc/Docedit/Docedit.upp @@ -1,15 +1,15 @@ -uses - docpp, - RichEdit; - -file - Docedit.h, - Docbase.cpp, - Docdir.cpp, - DocItem.cpp, - DocLink.cpp, - Docedit.cpp, - Docedit.iml, - Info readonly separator, - Copying; - +uses + docpp, + RichEdit; + +file + Docedit.h, + Docbase.cpp, + Docdir.cpp, + DocItem.cpp, + DocLink.cpp, + Docedit.cpp, + Docedit.iml, + Info readonly separator, + Copying; + diff --git a/archive/uppsrc/TCore/Copying b/archive/uppsrc/TCore/Copying index 9159e0082..27fc52607 100644 --- a/archive/uppsrc/TCore/Copying +++ b/archive/uppsrc/TCore/Copying @@ -1,4 +1,4 @@ -Copyright (c) 1998, 2019, The U++ Project +Copyright (c) 1998, 2020, The U++ Project All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted diff --git a/archive/uppsrc/TCtrlLib/Copying b/archive/uppsrc/TCtrlLib/Copying index 9159e0082..27fc52607 100644 --- a/archive/uppsrc/TCtrlLib/Copying +++ b/archive/uppsrc/TCtrlLib/Copying @@ -1,4 +1,4 @@ -Copyright (c) 1998, 2019, The U++ Project +Copyright (c) 1998, 2020, The U++ Project All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted diff --git a/archive/uppsrc/TDraw/Copying b/archive/uppsrc/TDraw/Copying index 9159e0082..27fc52607 100644 --- a/archive/uppsrc/TDraw/Copying +++ b/archive/uppsrc/TDraw/Copying @@ -1,4 +1,4 @@ -Copyright (c) 1998, 2019, The U++ Project +Copyright (c) 1998, 2020, The U++ Project All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted diff --git a/archive/uppsrc/TSql/Copying b/archive/uppsrc/TSql/Copying index 9159e0082..27fc52607 100644 --- a/archive/uppsrc/TSql/Copying +++ b/archive/uppsrc/TSql/Copying @@ -1,4 +1,4 @@ -Copyright (c) 1998, 2019, The U++ Project +Copyright (c) 1998, 2020, The U++ Project All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted diff --git a/archive/uppsrc/Web/Copying b/archive/uppsrc/Web/Copying index 9159e0082..27fc52607 100644 --- a/archive/uppsrc/Web/Copying +++ b/archive/uppsrc/Web/Copying @@ -1,4 +1,4 @@ -Copyright (c) 1998, 2019, The U++ Project +Copyright (c) 1998, 2020, The U++ Project All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted diff --git a/archive/uppsrc/Web/SSL/Copying b/archive/uppsrc/Web/SSL/Copying index 9159e0082..27fc52607 100644 --- a/archive/uppsrc/Web/SSL/Copying +++ b/archive/uppsrc/Web/SSL/Copying @@ -1,4 +1,4 @@ -Copyright (c) 1998, 2019, The U++ Project +Copyright (c) 1998, 2020, The U++ Project All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted diff --git a/archive/uppsrc/Web/ctrl/Copying b/archive/uppsrc/Web/ctrl/Copying index 9159e0082..27fc52607 100644 --- a/archive/uppsrc/Web/ctrl/Copying +++ b/archive/uppsrc/Web/ctrl/Copying @@ -1,4 +1,4 @@ -Copyright (c) 1998, 2019, The U++ Project +Copyright (c) 1998, 2020, The U++ Project All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted diff --git a/archive/uppsrc/Web/wisapi/Copying b/archive/uppsrc/Web/wisapi/Copying index 9159e0082..27fc52607 100644 --- a/archive/uppsrc/Web/wisapi/Copying +++ b/archive/uppsrc/Web/wisapi/Copying @@ -1,4 +1,4 @@ -Copyright (c) 1998, 2019, The U++ Project +Copyright (c) 1998, 2020, The U++ Project All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted diff --git a/uppsrc/docpp/Copying b/archive/uppsrc/docpp/Copying similarity index 100% rename from uppsrc/docpp/Copying rename to archive/uppsrc/docpp/Copying diff --git a/uppsrc/docpp/Parser.cpp b/archive/uppsrc/docpp/Parser.cpp similarity index 95% rename from uppsrc/docpp/Parser.cpp rename to archive/uppsrc/docpp/Parser.cpp index 9a4ed5286..a87884312 100644 --- a/uppsrc/docpp/Parser.cpp +++ b/archive/uppsrc/docpp/Parser.cpp @@ -1,825 +1,825 @@ -#include "docpp.h" - -String Purify(const char *s) { - String res; - while(*s) { - if(*s >= 'a' && *s <= 'z') { - String q; - while(*s >= 'a' && *s <= 'z') - q.Cat(*s++); - if(q != "virtual" && q != "inline") - res.Cat(q); - else - while((byte)*s <= ' ' && *s) s++; - } - else - if((byte)*s <= ' ') { - res.Cat(' '); - while(*s <= ' ' && *s) - s++; - } - else - res.Cat(*s++); - } - return res; -} - -void ScAdd(String& s, const String& a) -{ - if(a.IsEmpty()) return; - if(!s.IsEmpty()) - s << ';'; - s << a; -} - -String Parser::Context::Dump() const -{ - return "Namespace: " + nameing + " Struct: " + nesting; -} - -void Parser::Context::operator<<=(const Context& t) -{ - nameing = t.nameing; - nesting = t.nesting; - typenames <<= t.typenames; - access = t.access; -} - - -Parser::Decla::Decla() -{ - function = type_def = false; - s_static = s_auto = s_register = s_extern = s_mutable = s_explicit = s_virtual = false; - isfriend = istemplate = istructor = isptr = nofn = false; -} - -bool Parser::Key(int code) -{ - if(lex == code) { - ++lex; - return true; - } - return false; -} - -int Parser::GetLine(const char *p) -{ - int pos = p - ~file.text; - int l = 0; - int h = file.linepos.GetCount(); - while(l < h) { - int q = (l + h) / 2; - if(file.linepos[q] < pos) - l = q + 1; - else - h = q; - } - return l; -} - -void Parser::Line() -{ - int pos = lex.Pos() - ~file.text; - while(line + 1 < file.linepos.GetCount() && file.linepos[line + 1] <= pos) - line++; -} - -void Parser::ThrowError(const String& e) -{ - throw Error(Format("(%d) : %s", GetLine(lex.Pos()), ~e)); -} - -void Parser::Check(bool b, const char *err) -{ - if(!b) ThrowError(err); -} - -void Parser::CheckKey(int c) -{ - if(!Key(c)) ThrowError(Format("Missing %c", c)); -} - -String Parser::TemplateParams(String& param) -{ - const char *pos = lex.Pos(); - CheckKey('<'); - int level = 1; - String id; - bool gp = true; - for(;;) { - if(lex.IsId() && gp) - id = lex.GetId(); - else - if(Key(',')) { - ScAdd(param, id); - id.Clear(); - gp = true; - } - else - if(Key('=')) { - if(!id.IsEmpty()) { - ScAdd(param, id); - id.Clear(); - } - gp = false; - } - else - if(Key('>')) { - level--; - if(level <= 0) { - ScAdd(param, id); - break; - } - } - else - if(Key('<')) - level++; - else - ++lex; - } - return String(pos, lex.Pos()); -} - -String Parser::TemplateParams() -{ - String dummy; - return TemplateParams(dummy); -} - -String Parser::TemplatePnames() -{ - String pnames; - TemplateParams(pnames); - return pnames; -} - -String Parser::Name() -{ - String s; - if(Key(t_dblcolon)) - s << "::"; - Check(lex.IsId(), "Name expected"); - while(lex.IsId()) { - s << lex.GetId(); - if(lex == '<') - s << TemplateParams(); - if(Key(t_dblcolon)) { - s << "::"; - if(Key('~')) - s << "~"; - } - else - break; - } - return s; -} - -String Parser::Constant() -{ - const char *p = lex.Pos(); - const char *p1 = p; - int level = 0; - for(;;) { - p1 = lex.Pos(); - if(lex == t_eof) break; - if(level <= 0 && (lex == ',' || lex == ';' || lex == ')' || lex == '}' || lex == ']')) - break; - if(Key('(') || Key('[') || Key('{')) level++; - else - if(Key(')') || Key(']') || Key('}')) level--; - else - ++lex; - } - return String(p, p1); -} - -String Parser::SimpleType() -{ - if(Key(tk_struct) || Key(tk_class) || Key(tk_union) || Key(tk_enum) || Key(tk_typename)) { - if(lex.IsId() || lex == t_dblcolon) Name(); - if(lex == '{') EatBody(); - return Null; - } - if(Key(tk_bool) || Key(tk_float) || Key(tk_double) || Key(tk_void)) - return Null; - bool sgn = Key(tk_signed) || Key(tk_unsigned); - if(Key(tk_long)) { - Key(tk_int); - return Null; - } - if(Key(tk_short)) { - Key(tk_int); - return Null; - } - if(Key(tk_int) || Key(tk_char) || - Key(tk___int8) || Key(tk___int16) || Key(tk___int32) || Key(tk___int64)) return Null; - if(sgn) return Null; - const char *p = lex.Pos(); - int cs = 0; - Index cix; - Key(t_dblcolon); - Check(lex.IsId(), "Name expected"); - while(lex.IsId()) { - if(cix.Find(lex) >= 0) - cs++; - else - cix.Add(lex); - ++lex; - if(lex == '<') - TemplateParams(); - if(Key(t_dblcolon)) - Key('~'); - else - break; - } - return cs ? String(p, lex.Pos()) : String(); -} - -void Parser::Qualifier() -{ - Key(tk_const); - Key(tk_volatile); - if(Key(tk_throw)) { - while(lex != t_eof && !Key(')')) - ++lex; - } -} - -void Parser::Elipsis(Decl& d) -{ - Decl& q = d.param.Add(); - q.name = "..."; - CheckKey(')'); -} - -void Parser::ParamList(Decl& d) { - if(!Key(')')) - for(;;) { - if(Key(t_elipsis)) { - Elipsis(d); - break; - } - else - d.param.Add() = Declaration().Top(); - if(Key(t_elipsis)) { - Elipsis(d); - break; - } - if(Key(')')) break; - CheckKey(','); - } -} - -int Parser::RPtr() -{ - int n = 0; - int q = 0; - int tlevel = 0; - for(;;) { - int t = lex[n]; - if(t == '*') return n + 1; - if(t == '<') { - tlevel++; - n++; - } - else - if(t == '>') { - tlevel--; - n++; - } - else - if(t == t_dblcolon || lex.IsId(n) || t == ',' && tlevel > 0) - n++; - else - return 0; - } -} - -void Parser::EatInitializers() -{ - if(Key(':')) { - while(lex != '{' && lex != t_eof) ++lex; - } -} - -String Parser::ReadOper() { - const char *p = lex.Pos(); - const char *p1 = p; - Key(tk_operator); - int level = 0; - if(Key('(')) - level++; - for(;;) { - p1 = lex.Pos(); - if(lex == t_eof) break; - if(level <= 0 && lex == '(') break; - if(Key('(') || Key('[')) level++; - else - if(Key(')') || Key(']')) level--; - else - ++lex; - } - return TrimRight(Purify(String(p, p1))); -} - -void Parser::Declarator(Decl& d, const char *p) -{ - int n = RPtr(); - if(n) { - while(n--) lex.Get(); - Declarator(d, p); - d.isptr = true; - return; - } - if(Key('&')) { - Declarator(d, p); - return; - } - if(Key(tk_const)) { - Declarator(d, p); - return; - } - if(Key('(')) { - Declarator(d, p); - if(d.isptr) - d.nofn = true; - CheckKey(')'); - } - if(lex == tk_operator) - d.name = ReadOper(); - else - if(lex.IsId() || lex == t_dblcolon) { - d.name = Name(); - if(Key(':')) - if(!Key(t_integer)) - Name(); - } - if(Key('(')) { - if((lex < 256 || lex == tk_true || lex == tk_false) && lex != ')') { - int level = 0; - for(;;) { - if(lex == t_eof) break; - if(Key('(')) level++; - else - if(Key(')')) { - if(--level < 0) break; - } - else - ++lex; - } - return; - } - else { - d.header = String(p, lex.Pos() - 1); - d.function = !d.nofn; - ParamList(d); - p = lex.Pos(); - Qualifier(); - d.ender = String(p, lex.Pos()); - } - } - EatInitializers(); - while(Key('[')) { - const char *p = lex.Pos(); - int level = 1; - while(level && lex != t_eof) { - if(Key('[')) level++; - else - if(Key(']')) level--; - else - ++lex; - } - } - if(Key('=')) { - Constant(); - } -} - -Parser::Decl& Parser::Finish(Decl& d, const char *s) -{ - d.natural = String(s, lex.Pos()); - return d; -} - -Parser::Decl Parser::Type() { - Decl d; - const char *p = lex.Pos(); - Qualifier(); - SimpleType(); - Declarator(d, p); - return Finish(d, p); -} - -Array Parser::Declaration(bool l0, bool more) -{ - Array r; - Decla d; - const char *p = lex.Pos(); - if(Key(tk_typedef)) { - r = Declaration(); - r.Top().type_def = true; - r.Top().natural = String(p, lex.Pos()); - return r; - } - if(Key(tk_friend)) - d.isfriend = true; -// if(Key(tk_template)) { -// d.istemplate = true; -// d.template_params = TemplateParams(d.tnames); -// } - for(;;) { - if(Key(tk_static)) - d.s_static = true; - else - if(Key(tk_extern)) - d.s_extern = true; - else - if(Key(tk_auto)) - d.s_auto = true; - else - if(Key(tk_register)) - d.s_register = true; - else - if(Key(tk_mutable)) - d.s_mutable = true; - else - if(Key(tk_explicit)) - d.s_explicit = true; - else - if(Key(tk_virtual)) - d.s_virtual = true; - else - if(!Key(tk_inline)) - break; - } - Qualifier(); - bool isdestructor = Key('~'); - if(l0 && context.typenames.Find(lex) >= 0 && lex[1] == '(') { - Decl& a = r.Add(); - a.name = lex.GetId(); - a.isdestructor = isdestructor; - a.function = true; - a.istructor = true; - a.header = String(p, lex.Pos()); - ++lex; - ParamList(a); - const char *p1 = lex.Pos(); - Qualifier(); - a.ender = String(p1, lex.Pos()); - a.natural = String(p, lex.Pos()); - EatInitializers(); - return r; - } - if(lex == tk_operator) { - Decl& a = r.Add(); - (Decla&)a = d; - a.name = ReadOper(); - a.header = String(p, lex.Pos()); - Key('('); - ParamList(a); - const char *p1 = lex.Pos(); - Qualifier(); - a.ender = String(p1, lex.Pos()); - a.function = true; - a.natural = String(p, lex.Pos()); - return r; - } - String st = SimpleType(); - if(!st.IsEmpty()) { - Decl& a = r.Add(); - a.name = st; - a.isdestructor = st.Find('~') > 0; - a.function = true; - a.istructor = true; - a.header = String(p, lex.Pos()); - if(Key('(')) - ParamList(a); - const char *p1 = lex.Pos(); - Qualifier(); - a.ender = String(p1, lex.Pos()); - a.natural = String(p, lex.Pos()); - EatInitializers(); - return r; - } - String natural1 = String(p, lex.Pos()); - do { - const char *p1 = lex.Pos(); - Decl& a = r.Add(); - (Decla&)a = d; - Declarator(a, p); - a.natural = natural1 + String(p1, lex.Pos()); - p = lex.Pos(); - } - while(more && Key(',')); - return r; -} - -bool Parser::EatBody() -{ - if(!Key('{')) return false; - int level = 1; - while(level && lex != t_eof) { - if(Key('{')) level++; - else - if(Key('}')) level--; - else - ++lex; - } - return true; -} - -String CleanTp(const String& tp) -{ - int q = tp.Find('<'); - int w = tp.ReverseFind('>'); - if(q < 0 || w < 0) return tp; - String a = TrimLeft(TrimRight(tp.Mid(q + 1, w - q - 1))); - const char *s = a; - String r; - while(*s) { - if(*s == ',') { - r.Cat(';'); - s++; - while(*s == ' ') - s++; - } - else - r.Cat(*s++); - } - return r; -} - -bool Parser::Nest(const String& tp, const String& tn) { - if(Key(tk_namespace)) { - Check(lex.IsId(), "Expected name of namespace"); - String name = lex.GetId(); - if(Key('{')) { - Context cc; - cc <<= context; - context.nameing << name << "::"; - Do(); - context <<= cc; - Key('}'); - } - Key(';'); - return true; - } - if((lex == tk_class || lex == tk_struct || lex == tk_union) && - lex.IsId(1) && - (lex[2] == ':' || lex[2] == ';' || lex[2] == '{')) { - int t = lex.GetCode(); - context.typenames.FindAdd(lex); - String name = lex.GetId(); - Context cc; - cc <<= context; - if(context.nesting.IsEmpty()) - context.nesting = name + TrimRight(tp); - else - context.nesting = context.nesting + "::" + name + TrimRight(tp); - context.access = t == tk_class ? PRIVATE : PUBLIC; - String nn; - if(!tp.IsEmpty()) - nn = "template " + tp + " "; - nn << (t == tk_class ? "class " : t == tk_union ? "union " : "struct ") + name; - CppItem& im = Item(context.nameing, context.nesting, nn); - im.kind = tp.IsEmpty() ? STRUCT : STRUCTTEMPLATE; - im.name = name; - im.access = cc.access; - im.tname = tn; - im.tparam = CleanTp(tp); - if(Key(':')) { - do { - String access = t == tk_class ? "private" : "public"; - if(Key(tk_public)) access = "public"; - else - if(Key(tk_protected)) access = "protected"; - else - if(Key(tk_private)) access = "private"; - if(Key(tk_virtual)) access << " virtual"; - String n = Name(); - ScAdd(im.pname, n); - ScAdd(im.param, access + ' ' + n); - } - while(Key(',')); - } - if(Key('{')) { - Do(); - CheckKey('}'); - } - CheckKey(';'); - context = cc; - return true; - } - return false; -} - -CppItem& Parser::Item(const String& nameing, const String& nesting, const String& item) -{ - CppItem& im = base->GetAdd(nameing).GetAdd(nesting).GetAdd(TrimRight(Purify(item))); - im.pname.Clear(); - im.param.Clear(); - im.package = package; - im.file = filename; - im.line = line + 1; - im.name.Clear(); - return im; -} - -void Parser::Do() -{ - while(lex != t_eof && lex != '}') { - Line(); - if(Key(tk_using)) { - while(!Key(';')) - ++lex; - } - else - if(Key(tk_extern) && lex == t_string) { - ++lex; - ++lex; - if(Key('{')) { - Do(); - Key('}'); - } - Key(';'); - } - else - if(Key(tk_template)) { - if(lex.IsId() || lex == tk_class && lex.IsId(1)) { - Key(tk_class); - for(;;) { - if(lex.IsId()) - lex.GetId(); - else - if(!Key(t_dblcolon)) - break; - } - TemplateParams(); - Key(';'); - } - else { - String tnames; - String tparam = TemplateParams(tnames); - if(!Nest(tparam, tnames)) { - Array r = Declaration(true, true); - for(int i = 0; i < r.GetCount(); i++) { - Decl& d = r[i]; - d.natural = "template" + tparam + ' ' + d.natural; - if(context.access != PRIVATE && !d.isfriend && d.function) { - CppItem& im = Item(context.nameing, context.nesting, d.natural); - im.name = d.name; - im.access = context.access; - im.header = Purify(d.header); - im.ender = Purify(d.ender); - im.kind = context.nesting.IsEmpty() ? FUNCTIONTEMPLATE : - d.s_static ? CLASSFUNCTIONTEMPLATE - : INSTANCEFUNCTIONTEMPLATE; - for(int i = 0; i < d.param.GetCount(); i++) { - ScAdd(im.param, d.param[i].natural); - ScAdd(im.pname, d.param[i].name); - } - im.tname = tnames; - im.tparam = CleanTp(tparam); - } - } - EatBody(); - Key(';'); - } - } - } - else - if(lex == tk_enum && (lex[1] == '{' || lex[2] == '{')) { - ++lex; - String name; - if(lex.IsId()) - name = lex.GetId(); - String param; - String pname; - String n = "enum " + name + " { "; - Key('{'); - for(;;) { - String val; - Check(lex.IsId(), "Expected identifier"); - String nm = lex.GetId(); - if(Key('=')) - val = Constant(); - if(!param.IsEmpty()) - n << ", "; - n << nm; - ScAdd(param, nm + " = " + val); - ScAdd(pname, nm); - Key(','); - if(Key('}')) break; - } - n << " }"; - CppItem& im = Item(context.nameing, context.nesting, n); - im.kind = ENUM; - im.name = name; - im.access = context.access; - im.param = param; - im.pname = pname; - if(lex.IsId()) - im.name = lex.GetId(); - CheckKey(';'); - } - else - if(Key('#')) { - String n = lex.GetText(); - CppItem& im = Item(context.nameing, context.nesting, n); - im.kind = MACRO; - im.name.Clear(); - const char *s = n; - while(*s && iscid(*s)) - im.name.Cat(*s++); - s = strchr(n, '('); - if(s) { - s++; - String p; - for(;;) { - if(iscid(*s)) - p.Cat(*s++); - else { - ScAdd(im.pname, p); - p.Clear(); - if(*s == ')' || *s == '\0') break; - s++; - } - } - } - im.access = context.access; - } - else - if(!Nest(String(), String())) { - if(Key(tk_public)) { - context.access = PUBLIC; - Key(':'); - } - else - if(Key(tk_private)) { - context.access = PRIVATE; - Key(':'); - } - else - if(Key(tk_protected)) { - context.access = PROTECTED; - Key(':'); - } - else { - const char *p = lex.Pos(); - Array r = Declaration(true, true); - bool body = EatBody(); - for(int i = 0; i < r.GetCount(); i++) { - Decl& d = r[i]; - if(context.access != PRIVATE && !d.isfriend || d.isfriend && body) { - CppItem& im = Item(context.nameing, context.nesting, d.natural); - im.name = d.name; - im.header = Purify(d.header); - im.ender = Purify(d.ender); - im.access = context.access; - if(d.function) { - im.kind = d.istructor ? (d.isdestructor ? DESTRUCTOR : CONSTRUCTOR) : - d.isfriend ? INLINEFRIEND : - context.nesting.IsEmpty() ? FUNCTION : - d.s_static ? CLASSFUNCTION : INSTANCEFUNCTION; - for(int i = 0; i < d.param.GetCount(); i++) { - ScAdd(im.param, d.param[i].natural); - ScAdd(im.pname, d.param[i].name); - } - } - else - im.kind = d.type_def ? TYPEDEF : - context.nesting.IsEmpty() ? VARIABLE : - d.s_static ? CLASSVARIABLE : INSTANCEVARIABLE; - } - } - EatBody(); - Key(';'); - } - } - } -} - -void Parser::Do(Stream& in, const Vector& ignore, CppBase& _base, - const String& p, const String& f) throw(Parser::Error) -{ - base = &_base; - file = PreProcess(in); - lex = ~file.text; - lex.Ignore(ignore); - context.nesting.Clear(); - context.nameing = "::"; - context.access = PUBLIC; - context.typenames.Clear(); - package = p; - filename = f; - lpos = 0; - line = 0; - Do(); -} - -void Parse(Stream& s, const Vector& ignore, CppBase& base, - const String& package, const String& file) throw(Parser::Error) -{ - Parser p; - p.Do(s, ignore, base, package, file); -} +#include "docpp.h" + +String Purify(const char *s) { + String res; + while(*s) { + if(*s >= 'a' && *s <= 'z') { + String q; + while(*s >= 'a' && *s <= 'z') + q.Cat(*s++); + if(q != "virtual" && q != "inline") + res.Cat(q); + else + while((byte)*s <= ' ' && *s) s++; + } + else + if((byte)*s <= ' ') { + res.Cat(' '); + while(*s <= ' ' && *s) + s++; + } + else + res.Cat(*s++); + } + return res; +} + +void ScAdd(String& s, const String& a) +{ + if(a.IsEmpty()) return; + if(!s.IsEmpty()) + s << ';'; + s << a; +} + +String Parser::Context::Dump() const +{ + return "Namespace: " + nameing + " Struct: " + nesting; +} + +void Parser::Context::operator<<=(const Context& t) +{ + nameing = t.nameing; + nesting = t.nesting; + typenames <<= t.typenames; + access = t.access; +} + + +Parser::Decla::Decla() +{ + function = type_def = false; + s_static = s_auto = s_register = s_extern = s_mutable = s_explicit = s_virtual = false; + isfriend = istemplate = istructor = isptr = nofn = false; +} + +bool Parser::Key(int code) +{ + if(lex == code) { + ++lex; + return true; + } + return false; +} + +int Parser::GetLine(const char *p) +{ + int pos = p - ~file.text; + int l = 0; + int h = file.linepos.GetCount(); + while(l < h) { + int q = (l + h) / 2; + if(file.linepos[q] < pos) + l = q + 1; + else + h = q; + } + return l; +} + +void Parser::Line() +{ + int pos = lex.Pos() - ~file.text; + while(line + 1 < file.linepos.GetCount() && file.linepos[line + 1] <= pos) + line++; +} + +void Parser::ThrowError(const String& e) +{ + throw Error(Format("(%d) : %s", GetLine(lex.Pos()), ~e)); +} + +void Parser::Check(bool b, const char *err) +{ + if(!b) ThrowError(err); +} + +void Parser::CheckKey(int c) +{ + if(!Key(c)) ThrowError(Format("Missing %c", c)); +} + +String Parser::TemplateParams(String& param) +{ + const char *pos = lex.Pos(); + CheckKey('<'); + int level = 1; + String id; + bool gp = true; + for(;;) { + if(lex.IsId() && gp) + id = lex.GetId(); + else + if(Key(',')) { + ScAdd(param, id); + id.Clear(); + gp = true; + } + else + if(Key('=')) { + if(!id.IsEmpty()) { + ScAdd(param, id); + id.Clear(); + } + gp = false; + } + else + if(Key('>')) { + level--; + if(level <= 0) { + ScAdd(param, id); + break; + } + } + else + if(Key('<')) + level++; + else + ++lex; + } + return String(pos, lex.Pos()); +} + +String Parser::TemplateParams() +{ + String dummy; + return TemplateParams(dummy); +} + +String Parser::TemplatePnames() +{ + String pnames; + TemplateParams(pnames); + return pnames; +} + +String Parser::Name() +{ + String s; + if(Key(t_dblcolon)) + s << "::"; + Check(lex.IsId(), "Name expected"); + while(lex.IsId()) { + s << lex.GetId(); + if(lex == '<') + s << TemplateParams(); + if(Key(t_dblcolon)) { + s << "::"; + if(Key('~')) + s << "~"; + } + else + break; + } + return s; +} + +String Parser::Constant() +{ + const char *p = lex.Pos(); + const char *p1 = p; + int level = 0; + for(;;) { + p1 = lex.Pos(); + if(lex == t_eof) break; + if(level <= 0 && (lex == ',' || lex == ';' || lex == ')' || lex == '}' || lex == ']')) + break; + if(Key('(') || Key('[') || Key('{')) level++; + else + if(Key(')') || Key(']') || Key('}')) level--; + else + ++lex; + } + return String(p, p1); +} + +String Parser::SimpleType() +{ + if(Key(tk_struct) || Key(tk_class) || Key(tk_union) || Key(tk_enum) || Key(tk_typename)) { + if(lex.IsId() || lex == t_dblcolon) Name(); + if(lex == '{') EatBody(); + return Null; + } + if(Key(tk_bool) || Key(tk_float) || Key(tk_double) || Key(tk_void)) + return Null; + bool sgn = Key(tk_signed) || Key(tk_unsigned); + if(Key(tk_long)) { + Key(tk_int); + return Null; + } + if(Key(tk_short)) { + Key(tk_int); + return Null; + } + if(Key(tk_int) || Key(tk_char) || + Key(tk___int8) || Key(tk___int16) || Key(tk___int32) || Key(tk___int64)) return Null; + if(sgn) return Null; + const char *p = lex.Pos(); + int cs = 0; + Index cix; + Key(t_dblcolon); + Check(lex.IsId(), "Name expected"); + while(lex.IsId()) { + if(cix.Find(lex) >= 0) + cs++; + else + cix.Add(lex); + ++lex; + if(lex == '<') + TemplateParams(); + if(Key(t_dblcolon)) + Key('~'); + else + break; + } + return cs ? String(p, lex.Pos()) : String(); +} + +void Parser::Qualifier() +{ + Key(tk_const); + Key(tk_volatile); + if(Key(tk_throw)) { + while(lex != t_eof && !Key(')')) + ++lex; + } +} + +void Parser::Elipsis(Decl& d) +{ + Decl& q = d.param.Add(); + q.name = "..."; + CheckKey(')'); +} + +void Parser::ParamList(Decl& d) { + if(!Key(')')) + for(;;) { + if(Key(t_elipsis)) { + Elipsis(d); + break; + } + else + d.param.Add() = Declaration().Top(); + if(Key(t_elipsis)) { + Elipsis(d); + break; + } + if(Key(')')) break; + CheckKey(','); + } +} + +int Parser::RPtr() +{ + int n = 0; + int q = 0; + int tlevel = 0; + for(;;) { + int t = lex[n]; + if(t == '*') return n + 1; + if(t == '<') { + tlevel++; + n++; + } + else + if(t == '>') { + tlevel--; + n++; + } + else + if(t == t_dblcolon || lex.IsId(n) || t == ',' && tlevel > 0) + n++; + else + return 0; + } +} + +void Parser::EatInitializers() +{ + if(Key(':')) { + while(lex != '{' && lex != t_eof) ++lex; + } +} + +String Parser::ReadOper() { + const char *p = lex.Pos(); + const char *p1 = p; + Key(tk_operator); + int level = 0; + if(Key('(')) + level++; + for(;;) { + p1 = lex.Pos(); + if(lex == t_eof) break; + if(level <= 0 && lex == '(') break; + if(Key('(') || Key('[')) level++; + else + if(Key(')') || Key(']')) level--; + else + ++lex; + } + return TrimRight(Purify(String(p, p1))); +} + +void Parser::Declarator(Decl& d, const char *p) +{ + int n = RPtr(); + if(n) { + while(n--) lex.Get(); + Declarator(d, p); + d.isptr = true; + return; + } + if(Key('&')) { + Declarator(d, p); + return; + } + if(Key(tk_const)) { + Declarator(d, p); + return; + } + if(Key('(')) { + Declarator(d, p); + if(d.isptr) + d.nofn = true; + CheckKey(')'); + } + if(lex == tk_operator) + d.name = ReadOper(); + else + if(lex.IsId() || lex == t_dblcolon) { + d.name = Name(); + if(Key(':')) + if(!Key(t_integer)) + Name(); + } + if(Key('(')) { + if((lex < 256 || lex == tk_true || lex == tk_false) && lex != ')') { + int level = 0; + for(;;) { + if(lex == t_eof) break; + if(Key('(')) level++; + else + if(Key(')')) { + if(--level < 0) break; + } + else + ++lex; + } + return; + } + else { + d.header = String(p, lex.Pos() - 1); + d.function = !d.nofn; + ParamList(d); + p = lex.Pos(); + Qualifier(); + d.ender = String(p, lex.Pos()); + } + } + EatInitializers(); + while(Key('[')) { + const char *p = lex.Pos(); + int level = 1; + while(level && lex != t_eof) { + if(Key('[')) level++; + else + if(Key(']')) level--; + else + ++lex; + } + } + if(Key('=')) { + Constant(); + } +} + +Parser::Decl& Parser::Finish(Decl& d, const char *s) +{ + d.natural = String(s, lex.Pos()); + return d; +} + +Parser::Decl Parser::Type() { + Decl d; + const char *p = lex.Pos(); + Qualifier(); + SimpleType(); + Declarator(d, p); + return Finish(d, p); +} + +Array Parser::Declaration(bool l0, bool more) +{ + Array r; + Decla d; + const char *p = lex.Pos(); + if(Key(tk_typedef)) { + r = Declaration(); + r.Top().type_def = true; + r.Top().natural = String(p, lex.Pos()); + return r; + } + if(Key(tk_friend)) + d.isfriend = true; +// if(Key(tk_template)) { +// d.istemplate = true; +// d.template_params = TemplateParams(d.tnames); +// } + for(;;) { + if(Key(tk_static)) + d.s_static = true; + else + if(Key(tk_extern)) + d.s_extern = true; + else + if(Key(tk_auto)) + d.s_auto = true; + else + if(Key(tk_register)) + d.s_register = true; + else + if(Key(tk_mutable)) + d.s_mutable = true; + else + if(Key(tk_explicit)) + d.s_explicit = true; + else + if(Key(tk_virtual)) + d.s_virtual = true; + else + if(!Key(tk_inline)) + break; + } + Qualifier(); + bool isdestructor = Key('~'); + if(l0 && context.typenames.Find(lex) >= 0 && lex[1] == '(') { + Decl& a = r.Add(); + a.name = lex.GetId(); + a.isdestructor = isdestructor; + a.function = true; + a.istructor = true; + a.header = String(p, lex.Pos()); + ++lex; + ParamList(a); + const char *p1 = lex.Pos(); + Qualifier(); + a.ender = String(p1, lex.Pos()); + a.natural = String(p, lex.Pos()); + EatInitializers(); + return r; + } + if(lex == tk_operator) { + Decl& a = r.Add(); + (Decla&)a = d; + a.name = ReadOper(); + a.header = String(p, lex.Pos()); + Key('('); + ParamList(a); + const char *p1 = lex.Pos(); + Qualifier(); + a.ender = String(p1, lex.Pos()); + a.function = true; + a.natural = String(p, lex.Pos()); + return r; + } + String st = SimpleType(); + if(!st.IsEmpty()) { + Decl& a = r.Add(); + a.name = st; + a.isdestructor = st.Find('~') > 0; + a.function = true; + a.istructor = true; + a.header = String(p, lex.Pos()); + if(Key('(')) + ParamList(a); + const char *p1 = lex.Pos(); + Qualifier(); + a.ender = String(p1, lex.Pos()); + a.natural = String(p, lex.Pos()); + EatInitializers(); + return r; + } + String natural1 = String(p, lex.Pos()); + do { + const char *p1 = lex.Pos(); + Decl& a = r.Add(); + (Decla&)a = d; + Declarator(a, p); + a.natural = natural1 + String(p1, lex.Pos()); + p = lex.Pos(); + } + while(more && Key(',')); + return r; +} + +bool Parser::EatBody() +{ + if(!Key('{')) return false; + int level = 1; + while(level && lex != t_eof) { + if(Key('{')) level++; + else + if(Key('}')) level--; + else + ++lex; + } + return true; +} + +String CleanTp(const String& tp) +{ + int q = tp.Find('<'); + int w = tp.ReverseFind('>'); + if(q < 0 || w < 0) return tp; + String a = TrimLeft(TrimRight(tp.Mid(q + 1, w - q - 1))); + const char *s = a; + String r; + while(*s) { + if(*s == ',') { + r.Cat(';'); + s++; + while(*s == ' ') + s++; + } + else + r.Cat(*s++); + } + return r; +} + +bool Parser::Nest(const String& tp, const String& tn) { + if(Key(tk_namespace)) { + Check(lex.IsId(), "Expected name of namespace"); + String name = lex.GetId(); + if(Key('{')) { + Context cc; + cc <<= context; + context.nameing << name << "::"; + Do(); + context <<= cc; + Key('}'); + } + Key(';'); + return true; + } + if((lex == tk_class || lex == tk_struct || lex == tk_union) && + lex.IsId(1) && + (lex[2] == ':' || lex[2] == ';' || lex[2] == '{')) { + int t = lex.GetCode(); + context.typenames.FindAdd(lex); + String name = lex.GetId(); + Context cc; + cc <<= context; + if(context.nesting.IsEmpty()) + context.nesting = name + TrimRight(tp); + else + context.nesting = context.nesting + "::" + name + TrimRight(tp); + context.access = t == tk_class ? PRIVATE : PUBLIC; + String nn; + if(!tp.IsEmpty()) + nn = "template " + tp + " "; + nn << (t == tk_class ? "class " : t == tk_union ? "union " : "struct ") + name; + CppItem& im = Item(context.nameing, context.nesting, nn); + im.kind = tp.IsEmpty() ? STRUCT : STRUCTTEMPLATE; + im.name = name; + im.access = cc.access; + im.tname = tn; + im.tparam = CleanTp(tp); + if(Key(':')) { + do { + String access = t == tk_class ? "private" : "public"; + if(Key(tk_public)) access = "public"; + else + if(Key(tk_protected)) access = "protected"; + else + if(Key(tk_private)) access = "private"; + if(Key(tk_virtual)) access << " virtual"; + String n = Name(); + ScAdd(im.pname, n); + ScAdd(im.param, access + ' ' + n); + } + while(Key(',')); + } + if(Key('{')) { + Do(); + CheckKey('}'); + } + CheckKey(';'); + context = cc; + return true; + } + return false; +} + +CppItem& Parser::Item(const String& nameing, const String& nesting, const String& item) +{ + CppItem& im = base->GetAdd(nameing).GetAdd(nesting).GetAdd(TrimRight(Purify(item))); + im.pname.Clear(); + im.param.Clear(); + im.package = package; + im.file = filename; + im.line = line + 1; + im.name.Clear(); + return im; +} + +void Parser::Do() +{ + while(lex != t_eof && lex != '}') { + Line(); + if(Key(tk_using)) { + while(!Key(';')) + ++lex; + } + else + if(Key(tk_extern) && lex == t_string) { + ++lex; + ++lex; + if(Key('{')) { + Do(); + Key('}'); + } + Key(';'); + } + else + if(Key(tk_template)) { + if(lex.IsId() || lex == tk_class && lex.IsId(1)) { + Key(tk_class); + for(;;) { + if(lex.IsId()) + lex.GetId(); + else + if(!Key(t_dblcolon)) + break; + } + TemplateParams(); + Key(';'); + } + else { + String tnames; + String tparam = TemplateParams(tnames); + if(!Nest(tparam, tnames)) { + Array r = Declaration(true, true); + for(int i = 0; i < r.GetCount(); i++) { + Decl& d = r[i]; + d.natural = "template" + tparam + ' ' + d.natural; + if(context.access != PRIVATE && !d.isfriend && d.function) { + CppItem& im = Item(context.nameing, context.nesting, d.natural); + im.name = d.name; + im.access = context.access; + im.header = Purify(d.header); + im.ender = Purify(d.ender); + im.kind = context.nesting.IsEmpty() ? FUNCTIONTEMPLATE : + d.s_static ? CLASSFUNCTIONTEMPLATE + : INSTANCEFUNCTIONTEMPLATE; + for(int i = 0; i < d.param.GetCount(); i++) { + ScAdd(im.param, d.param[i].natural); + ScAdd(im.pname, d.param[i].name); + } + im.tname = tnames; + im.tparam = CleanTp(tparam); + } + } + EatBody(); + Key(';'); + } + } + } + else + if(lex == tk_enum && (lex[1] == '{' || lex[2] == '{')) { + ++lex; + String name; + if(lex.IsId()) + name = lex.GetId(); + String param; + String pname; + String n = "enum " + name + " { "; + Key('{'); + for(;;) { + String val; + Check(lex.IsId(), "Expected identifier"); + String nm = lex.GetId(); + if(Key('=')) + val = Constant(); + if(!param.IsEmpty()) + n << ", "; + n << nm; + ScAdd(param, nm + " = " + val); + ScAdd(pname, nm); + Key(','); + if(Key('}')) break; + } + n << " }"; + CppItem& im = Item(context.nameing, context.nesting, n); + im.kind = ENUM; + im.name = name; + im.access = context.access; + im.param = param; + im.pname = pname; + if(lex.IsId()) + im.name = lex.GetId(); + CheckKey(';'); + } + else + if(Key('#')) { + String n = lex.GetText(); + CppItem& im = Item(context.nameing, context.nesting, n); + im.kind = MACRO; + im.name.Clear(); + const char *s = n; + while(*s && iscid(*s)) + im.name.Cat(*s++); + s = strchr(n, '('); + if(s) { + s++; + String p; + for(;;) { + if(iscid(*s)) + p.Cat(*s++); + else { + ScAdd(im.pname, p); + p.Clear(); + if(*s == ')' || *s == '\0') break; + s++; + } + } + } + im.access = context.access; + } + else + if(!Nest(String(), String())) { + if(Key(tk_public)) { + context.access = PUBLIC; + Key(':'); + } + else + if(Key(tk_private)) { + context.access = PRIVATE; + Key(':'); + } + else + if(Key(tk_protected)) { + context.access = PROTECTED; + Key(':'); + } + else { + const char *p = lex.Pos(); + Array r = Declaration(true, true); + bool body = EatBody(); + for(int i = 0; i < r.GetCount(); i++) { + Decl& d = r[i]; + if(context.access != PRIVATE && !d.isfriend || d.isfriend && body) { + CppItem& im = Item(context.nameing, context.nesting, d.natural); + im.name = d.name; + im.header = Purify(d.header); + im.ender = Purify(d.ender); + im.access = context.access; + if(d.function) { + im.kind = d.istructor ? (d.isdestructor ? DESTRUCTOR : CONSTRUCTOR) : + d.isfriend ? INLINEFRIEND : + context.nesting.IsEmpty() ? FUNCTION : + d.s_static ? CLASSFUNCTION : INSTANCEFUNCTION; + for(int i = 0; i < d.param.GetCount(); i++) { + ScAdd(im.param, d.param[i].natural); + ScAdd(im.pname, d.param[i].name); + } + } + else + im.kind = d.type_def ? TYPEDEF : + context.nesting.IsEmpty() ? VARIABLE : + d.s_static ? CLASSVARIABLE : INSTANCEVARIABLE; + } + } + EatBody(); + Key(';'); + } + } + } +} + +void Parser::Do(Stream& in, const Vector& ignore, CppBase& _base, + const String& p, const String& f) throw(Parser::Error) +{ + base = &_base; + file = PreProcess(in); + lex = ~file.text; + lex.Ignore(ignore); + context.nesting.Clear(); + context.nameing = "::"; + context.access = PUBLIC; + context.typenames.Clear(); + package = p; + filename = f; + lpos = 0; + line = 0; + Do(); +} + +void Parse(Stream& s, const Vector& ignore, CppBase& base, + const String& package, const String& file) throw(Parser::Error) +{ + Parser p; + p.Do(s, ignore, base, package, file); +} diff --git a/uppsrc/docpp/Pre.cpp b/archive/uppsrc/docpp/Pre.cpp similarity index 94% rename from uppsrc/docpp/Pre.cpp rename to archive/uppsrc/docpp/Pre.cpp index f253179cb..e0ca652fe 100644 --- a/uppsrc/docpp/Pre.cpp +++ b/archive/uppsrc/docpp/Pre.cpp @@ -1,95 +1,95 @@ -#include "docpp.h" - -String SSpaces(const char *txt) -{ - String r; - while(*txt) - if(*txt == ' ') { - while((byte)*txt <= ' ' && *txt) txt++; - r.Cat(' '); - } - else - r.Cat(*txt++); - return r; -} - -void SLPos(SrcFile& res) -{ - res.linepos.Add(res.text.GetLength()); -} - -SrcFile PreProcess(Stream& in) -{ - SrcFile res; - bool include = true; - while(!in.IsEof()) { - String ln = in.GetLine(); - SLPos(res); - while(*ln.Last() == '\\') { - ln.Trim(ln.GetLength() - 1); - ln.Cat(in.GetLine()); - SLPos(res); - } - const char *rm = ln; - while(*rm == ' ' || *rm == '\t') rm++; - if(*rm == '#') { - if(rm[1] == 'd' && rm[2] == 'e' && rm[3] == 'f' && - rm[4] == 'i' && rm[5] == 'n' && rm[6] == 'e' && !iscid(rm[7])) { - const char *s = rm + 8; - while(*s == ' ') s++; - String macro; - while(iscid(*s)) - macro.Cat(*s++); - if(*s == '(') { - while(*s != ')' && *s) - macro.Cat(*s++); - macro << ')'; - } - res.text << '#' << AsCString(SSpaces(macro)); - } - } - else { - String cmd; - while(*rm) { - if(rm[0] == '/' && rm[1] == '/') { - cmd = rm + 2; - break; - } - if(rm[0] == '/' && rm[1] == '*') { - rm += 2; - for(;;) { - if(*rm == '\0') { - if(in.IsEof()) break; - SLPos(res); - ln = in.GetLine(); - rm = ~ln; - } - if(rm[0] == '*' && rm[1] == '/') { - rm += 2; - break; - } - rm++; - } - if(include) - res.text.Cat(' '); - } - else { - if(include) - res.text.Cat(*rm); - rm++; - } - } - if(include) - res.text << ' '; - if(cmd[0] == '$') { - if(cmd[1] == '-') include = false; - if(cmd[1] == '+') include = true; - if(cmd[1]) { - res.text.Cat(~cmd + 2); - res.text.Cat(' '); - } - } - } - } - return res; -} +#include "docpp.h" + +String SSpaces(const char *txt) +{ + String r; + while(*txt) + if(*txt == ' ') { + while((byte)*txt <= ' ' && *txt) txt++; + r.Cat(' '); + } + else + r.Cat(*txt++); + return r; +} + +void SLPos(SrcFile& res) +{ + res.linepos.Add(res.text.GetLength()); +} + +SrcFile PreProcess(Stream& in) +{ + SrcFile res; + bool include = true; + while(!in.IsEof()) { + String ln = in.GetLine(); + SLPos(res); + while(*ln.Last() == '\\') { + ln.Trim(ln.GetLength() - 1); + ln.Cat(in.GetLine()); + SLPos(res); + } + const char *rm = ln; + while(*rm == ' ' || *rm == '\t') rm++; + if(*rm == '#') { + if(rm[1] == 'd' && rm[2] == 'e' && rm[3] == 'f' && + rm[4] == 'i' && rm[5] == 'n' && rm[6] == 'e' && !iscid(rm[7])) { + const char *s = rm + 8; + while(*s == ' ') s++; + String macro; + while(iscid(*s)) + macro.Cat(*s++); + if(*s == '(') { + while(*s != ')' && *s) + macro.Cat(*s++); + macro << ')'; + } + res.text << '#' << AsCString(SSpaces(macro)); + } + } + else { + String cmd; + while(*rm) { + if(rm[0] == '/' && rm[1] == '/') { + cmd = rm + 2; + break; + } + if(rm[0] == '/' && rm[1] == '*') { + rm += 2; + for(;;) { + if(*rm == '\0') { + if(in.IsEof()) break; + SLPos(res); + ln = in.GetLine(); + rm = ~ln; + } + if(rm[0] == '*' && rm[1] == '/') { + rm += 2; + break; + } + rm++; + } + if(include) + res.text.Cat(' '); + } + else { + if(include) + res.text.Cat(*rm); + rm++; + } + } + if(include) + res.text << ' '; + if(cmd[0] == '$') { + if(cmd[1] == '-') include = false; + if(cmd[1] == '+') include = true; + if(cmd[1]) { + res.text.Cat(~cmd + 2); + res.text.Cat(' '); + } + } + } + } + return res; +} diff --git a/uppsrc/docpp/cpplex.cpp b/archive/uppsrc/docpp/cpplex.cpp similarity index 95% rename from uppsrc/docpp/cpplex.cpp rename to archive/uppsrc/docpp/cpplex.cpp index 089bee890..cdcac4864 100644 --- a/uppsrc/docpp/cpplex.cpp +++ b/archive/uppsrc/docpp/cpplex.cpp @@ -1,324 +1,324 @@ -#include "docpp.h" - -#define case_id \ - case '_':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h': \ - case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q': \ - case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z': \ - case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':case 'H':case 'I': \ - case 'J':case 'K':case 'L':case 'M':case 'N':case 'O':case 'P':case 'Q':case 'R': \ - case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z' - -#define case_nonzero_digit \ - case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9' - - -const char *_CppKeyword[] = { -#define CPPID(x) #x, -#include "keyword.i" -#undef CPPID - NULL -}; - -const char **CppKeyword() { return _CppKeyword; } - -Lex::Lex() -{ - const char **cppk = CppKeyword(); - for(int i = 0; cppk[i]; i++) - id.Add(cppk[i]); - endkey = id.GetCount(); -} - -void Lex::Ignore(const Vector& ig) -{ - for(int i = 0; i < ig.GetCount(); i++) - ignore.Add(id.FindAdd(ig[i])); -} - -int Lex::GetCharacter() -{ - if(*ptr == '\0') return t_eof; - int c = *ptr++; - if(c == '\\') { - c = *ptr++; - switch(c) { - case 'a': return '\a'; - case 'b': return '\b'; - case 't': return '\t'; - case 'v': return '\v'; - case 'n': return '\n'; - case 'r': return '\r'; - case 'f': return '\f'; - case 'x': - c = 0; - if(isxdigit(*ptr)) { - c = (*ptr >= 'A' ? ToUpper(*ptr) - 'A' + 10 : *ptr - '0'); - ptr++; - if(isxdigit(*ptr)) { - c = 16 * c + (*ptr >= 'A' ? ToUpper(*ptr) - 'A' + 10 : *ptr - '0'); - ptr++; - } - } - break; - default: - if(c >= '0' && c <= '7') { - c -= '0'; - if(*ptr >= '0' && *ptr <= '7') - c = 8 * c + *ptr++ - '0'; - if(*ptr >= '0' && *ptr <= '7') - c = 8 * c + *ptr++ - '0'; - } - } - } - return (byte)c; -} - -#pragma optimize("t", on) - -void Lex::Next() -{ - while((byte)*ptr <= ' ') { - if(*ptr == '\0') return; - ptr++; - } - pos = ptr; - int c = (byte)*ptr++; - if(c == '\0') return; - switch(c) { - case_id: { - String x; - x.Reserve(12); - x.Cat(c); - while(iscid(*ptr)) - x.Cat(*ptr++); - int q = id.FindAdd(x); - if(ignore.Find(q) < 0) - AddCode(q + 256); - break; - } - case ':': AddCode(Char(':') ? t_dblcolon : ':'); break; - case '*': AssOp('*', t_mulass); break; - case '/': AssOp('/', t_divass); break; - case '%': AssOp('%', t_modass); break; - case '^': AssOp('^', t_xorass); break; - case '!': AssOp('!', t_neq); break; - case '.': - if(Char('*')) AddCode(t_dot_asteriks); - else - if(*ptr == '.' && ptr[1] == '.') { - AddCode(t_elipsis); - ptr += 2; - } - else - AddCode('.'); - break; - case '+': - if(Char('+')) AddCode(t_inc); - else - AssOp('+', t_addass); - return; - case '-': - if(Char('-')) AddCode(t_dec); - else - if(Char('>')) - AddCode(Char('*') ? t_arrow_asteriks : t_arrow); - else - AssOp('-', t_subass); - break; - case '&': - if(Char('&')) - AddCode(t_and); - else - AssOp('&', t_andass); - break; - case '|': - if(Char('|')) - AddCode(t_or); - else - AssOp('|', t_orass); - break; - case '=': - AssOp('=', t_eq); - break; - case '<': - if(Char('<')) - AssOp(t_shl, t_shlass); - else - AssOp('<', t_le); - break; - case '>': - if(Char('>')) - AssOp(t_shr, t_shrass); - else - AssOp('>', t_ge); - break; - case '0': { - dword w = 0; - if(Char('x') || Char('X')) { - for(;;) { - int d; - if(*ptr >= '0' && *ptr <= '9') - d = *ptr - '0'; - else - if(*ptr >= 'A' && *ptr <= 'F') - d = *ptr - 'A' + 10; - else - if(*ptr >= 'a' && *ptr <= 'f') - d = *ptr - 'a' + 10; - else - break; - if(w >= 0x8000000u - d) { - AddCode(te_integeroverflow); - return; - } - w = w * 16 + d - '0'; - ptr++; - } - } - else - while(*ptr >= '0' && *ptr <= '7') { - int d = *ptr++ - '0'; - if(w >= 0x1000000u - d) { - AddCode(te_integeroverflow); - return; - } - w = w * 8 + d - '0'; - } - Term& tm = term.AddTail(); - tm.code = t_integer; - tm.ptr = pos; - tm.number = w; - } - break; - case_nonzero_digit: { - double w = c - '0'; - bool fp = false; - while(*ptr >= '0' && *ptr <= '9') - w = w * 10 + *ptr++ - '0'; - if(*ptr == '.') { // TO BE Completed !!! - fp = true; - ptr++; - double x = 0.1; - while(*ptr >= '0' && *ptr <= '9') { - w += x * (*ptr++ - '0'); - x /= 10; - } - } - Term& tm = term.AddTail(); - if(fp || w < INT_MIN || w > INT_MAX) - tm.code = t_double; - else - tm.code = t_integer; - tm.ptr = pos; - tm.number = w; - } - break; - case '\'': { - Term& tm = term.AddTail(); - tm.code = t_character; - tm.ptr = pos; - tm.text = String(GetCharacter(), 1); - if(*ptr == '\'') - ptr++; - else - tm.code = te_badcharacter; - } - break; - case '\"': { - Term& tm = term.AddTail(); - tm.code = t_string; - tm.ptr = pos; - for(;;) { - while(*ptr != '\"') { - if((byte)*ptr < ' ') { - tm.code = te_badstring; - return; - } - tm.text.Cat(GetCharacter()); - } - ptr++; - while(*ptr && (byte)*ptr <= ' ') ptr++; - if(*ptr != '\"') break; - ptr++; - } - } - break; - default: - AddCode(c); - return; - } -} - -#pragma optimize("t", off) - -bool Lex::Prepare(int pos) { - while(term.GetCount() <= pos) { - if(*ptr == '\0') return false; - Next(); - } -#ifdef _DEBUG - pp = term[0].ptr; -#endif - return true; -} - -int Lex::Code(int pos) -{ - if(!Prepare(pos)) return t_eof; - return term[pos].code; -} - -bool Lex::IsId(int pos) -{ - return Code(pos) >= endkey + 256; -} - -String Lex::Id(int pos) -{ - ASSERT(IsId(pos)); - return id[Code(pos) - 256]; -} - -void Lex::Get(int n) -{ - while(n--) { - if(term.GetCount()) - term.DropHead(); - if(term.GetCount() == 0) - Next(); - } -} - -int Lex::Int(int pos) -{ - Prepare(pos); - ASSERT(term[pos].code == t_integer); - return (int)term[pos].number; -} - -double Lex::Double(int pos) -{ - Prepare(pos); - ASSERT(term[pos].code == t_double); - return term[pos].number; -} - -String Lex::Text(int pos) -{ - Prepare(pos); - ASSERT(term[pos].code == t_string); - return term[pos].text; -} - -int Lex::Chr(int pos) -{ - Prepare(pos); - ASSERT(term[pos].code == t_character); - return (byte)*term[pos].text; -} - -const char *Lex::Pos(int pos) -{ - Prepare(pos); - return pos < term.GetCount() ? term[pos].ptr : ptr; -} +#include "docpp.h" + +#define case_id \ + case '_':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h': \ + case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q': \ + case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z': \ + case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':case 'H':case 'I': \ + case 'J':case 'K':case 'L':case 'M':case 'N':case 'O':case 'P':case 'Q':case 'R': \ + case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z' + +#define case_nonzero_digit \ + case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9' + + +const char *_CppKeyword[] = { +#define CPPID(x) #x, +#include "keyword.i" +#undef CPPID + NULL +}; + +const char **CppKeyword() { return _CppKeyword; } + +Lex::Lex() +{ + const char **cppk = CppKeyword(); + for(int i = 0; cppk[i]; i++) + id.Add(cppk[i]); + endkey = id.GetCount(); +} + +void Lex::Ignore(const Vector& ig) +{ + for(int i = 0; i < ig.GetCount(); i++) + ignore.Add(id.FindAdd(ig[i])); +} + +int Lex::GetCharacter() +{ + if(*ptr == '\0') return t_eof; + int c = *ptr++; + if(c == '\\') { + c = *ptr++; + switch(c) { + case 'a': return '\a'; + case 'b': return '\b'; + case 't': return '\t'; + case 'v': return '\v'; + case 'n': return '\n'; + case 'r': return '\r'; + case 'f': return '\f'; + case 'x': + c = 0; + if(isxdigit(*ptr)) { + c = (*ptr >= 'A' ? ToUpper(*ptr) - 'A' + 10 : *ptr - '0'); + ptr++; + if(isxdigit(*ptr)) { + c = 16 * c + (*ptr >= 'A' ? ToUpper(*ptr) - 'A' + 10 : *ptr - '0'); + ptr++; + } + } + break; + default: + if(c >= '0' && c <= '7') { + c -= '0'; + if(*ptr >= '0' && *ptr <= '7') + c = 8 * c + *ptr++ - '0'; + if(*ptr >= '0' && *ptr <= '7') + c = 8 * c + *ptr++ - '0'; + } + } + } + return (byte)c; +} + +#pragma optimize("t", on) + +void Lex::Next() +{ + while((byte)*ptr <= ' ') { + if(*ptr == '\0') return; + ptr++; + } + pos = ptr; + int c = (byte)*ptr++; + if(c == '\0') return; + switch(c) { + case_id: { + String x; + x.Reserve(12); + x.Cat(c); + while(iscid(*ptr)) + x.Cat(*ptr++); + int q = id.FindAdd(x); + if(ignore.Find(q) < 0) + AddCode(q + 256); + break; + } + case ':': AddCode(Char(':') ? t_dblcolon : ':'); break; + case '*': AssOp('*', t_mulass); break; + case '/': AssOp('/', t_divass); break; + case '%': AssOp('%', t_modass); break; + case '^': AssOp('^', t_xorass); break; + case '!': AssOp('!', t_neq); break; + case '.': + if(Char('*')) AddCode(t_dot_asteriks); + else + if(*ptr == '.' && ptr[1] == '.') { + AddCode(t_elipsis); + ptr += 2; + } + else + AddCode('.'); + break; + case '+': + if(Char('+')) AddCode(t_inc); + else + AssOp('+', t_addass); + return; + case '-': + if(Char('-')) AddCode(t_dec); + else + if(Char('>')) + AddCode(Char('*') ? t_arrow_asteriks : t_arrow); + else + AssOp('-', t_subass); + break; + case '&': + if(Char('&')) + AddCode(t_and); + else + AssOp('&', t_andass); + break; + case '|': + if(Char('|')) + AddCode(t_or); + else + AssOp('|', t_orass); + break; + case '=': + AssOp('=', t_eq); + break; + case '<': + if(Char('<')) + AssOp(t_shl, t_shlass); + else + AssOp('<', t_le); + break; + case '>': + if(Char('>')) + AssOp(t_shr, t_shrass); + else + AssOp('>', t_ge); + break; + case '0': { + dword w = 0; + if(Char('x') || Char('X')) { + for(;;) { + int d; + if(*ptr >= '0' && *ptr <= '9') + d = *ptr - '0'; + else + if(*ptr >= 'A' && *ptr <= 'F') + d = *ptr - 'A' + 10; + else + if(*ptr >= 'a' && *ptr <= 'f') + d = *ptr - 'a' + 10; + else + break; + if(w >= 0x8000000u - d) { + AddCode(te_integeroverflow); + return; + } + w = w * 16 + d - '0'; + ptr++; + } + } + else + while(*ptr >= '0' && *ptr <= '7') { + int d = *ptr++ - '0'; + if(w >= 0x1000000u - d) { + AddCode(te_integeroverflow); + return; + } + w = w * 8 + d - '0'; + } + Term& tm = term.AddTail(); + tm.code = t_integer; + tm.ptr = pos; + tm.number = w; + } + break; + case_nonzero_digit: { + double w = c - '0'; + bool fp = false; + while(*ptr >= '0' && *ptr <= '9') + w = w * 10 + *ptr++ - '0'; + if(*ptr == '.') { // TO BE Completed !!! + fp = true; + ptr++; + double x = 0.1; + while(*ptr >= '0' && *ptr <= '9') { + w += x * (*ptr++ - '0'); + x /= 10; + } + } + Term& tm = term.AddTail(); + if(fp || w < INT_MIN || w > INT_MAX) + tm.code = t_double; + else + tm.code = t_integer; + tm.ptr = pos; + tm.number = w; + } + break; + case '\'': { + Term& tm = term.AddTail(); + tm.code = t_character; + tm.ptr = pos; + tm.text = String(GetCharacter(), 1); + if(*ptr == '\'') + ptr++; + else + tm.code = te_badcharacter; + } + break; + case '\"': { + Term& tm = term.AddTail(); + tm.code = t_string; + tm.ptr = pos; + for(;;) { + while(*ptr != '\"') { + if((byte)*ptr < ' ') { + tm.code = te_badstring; + return; + } + tm.text.Cat(GetCharacter()); + } + ptr++; + while(*ptr && (byte)*ptr <= ' ') ptr++; + if(*ptr != '\"') break; + ptr++; + } + } + break; + default: + AddCode(c); + return; + } +} + +#pragma optimize("t", off) + +bool Lex::Prepare(int pos) { + while(term.GetCount() <= pos) { + if(*ptr == '\0') return false; + Next(); + } +#ifdef _DEBUG + pp = term[0].ptr; +#endif + return true; +} + +int Lex::Code(int pos) +{ + if(!Prepare(pos)) return t_eof; + return term[pos].code; +} + +bool Lex::IsId(int pos) +{ + return Code(pos) >= endkey + 256; +} + +String Lex::Id(int pos) +{ + ASSERT(IsId(pos)); + return id[Code(pos) - 256]; +} + +void Lex::Get(int n) +{ + while(n--) { + if(term.GetCount()) + term.DropHead(); + if(term.GetCount() == 0) + Next(); + } +} + +int Lex::Int(int pos) +{ + Prepare(pos); + ASSERT(term[pos].code == t_integer); + return (int)term[pos].number; +} + +double Lex::Double(int pos) +{ + Prepare(pos); + ASSERT(term[pos].code == t_double); + return term[pos].number; +} + +String Lex::Text(int pos) +{ + Prepare(pos); + ASSERT(term[pos].code == t_string); + return term[pos].text; +} + +int Lex::Chr(int pos) +{ + Prepare(pos); + ASSERT(term[pos].code == t_character); + return (byte)*term[pos].text; +} + +const char *Lex::Pos(int pos) +{ + Prepare(pos); + return pos < term.GetCount() ? term[pos].ptr : ptr; +} diff --git a/uppsrc/docpp/docpp.h b/archive/uppsrc/docpp/docpp.h similarity index 95% rename from uppsrc/docpp/docpp.h rename to archive/uppsrc/docpp/docpp.h index c27a72845..1d8c9811b 100644 --- a/uppsrc/docpp/docpp.h +++ b/archive/uppsrc/docpp/docpp.h @@ -1,250 +1,250 @@ -#ifndef DOCPP_H -#define DOCPP_H - -#include - -enum { - Tmarker_before_first = 255, -#define CPPID(x) tk_##x, -#include "keyword.i" -#undef CPPID -}; - -enum { - t_eof, - t_string = -200, - t_integer, - t_double, - t_character, - t_dblcolon, - t_mulass, - t_divass, - t_modass, - t_xorass, - t_neq, - t_dot_asteriks, - t_elipsis, - t_inc, - t_addass, - t_dec, - t_arrow_asteriks, - t_arrow, - t_subass, - t_and, - t_andass, - t_or, - t_orass, - t_eq, - t_shl, - t_shlass, - t_le, - t_shr, - t_shrass, - t_ge, - te_integeroverflow, - te_badcharacter, - te_badstring, -}; - -const char **CppKeyword(); - -class Lex { -#ifdef _DEBUG - const char *pp; -#endif - const char *ptr; - const char *pos; - - Index id; - Index ignore; - int endkey; - - struct Term : Moveable{ - const char *ptr; - int code; - String text; - double number; - }; - - BiVector term; - - bool Char(int c) { if(*ptr == c) { ptr++; return true; } else return false; } - void AddCode(int code) { Term& tm = term.AddTail(); tm.code = code; tm.ptr = pos; } - void AssOp(int noass, int ass) { AddCode(Char('=') ? ass : noass); } - void Next(); - bool Prepare(int pos); - int GetCharacter(); - -public: - int Code(int pos = 0); - bool IsId(int pos = 0); - String Id(int pos = 0); - int Int(int pos = 0); - double Double(int pos = 0); - int Chr(int pos = 0); - String Text(int pos = 0); - - void Get(int n = 1); - int GetCode() { int q = Code(); Get(); return q; } - String GetId() { String q = Id(); Get(); return q; } - int GetInt() { int q = Int(); Get(); return q; } - double GetDouble() { double q = Double(); Get(); return q; } - int GetChr() { int q = Chr(); Get(); return q; } - String GetText() { String q = Text(); Get(); return q; } - - const char *Pos(int pos = 0); - int operator[](int pos) { return Code(pos); } - operator int() { return Code(0); } - void operator++() { Get(); } - - void operator=(const char *s) { ptr = s; term.Clear(); } - void Ignore(const Vector& ignore); - - Lex(); -}; - -struct SrcFile { - String text; - Vector linepos; -}; - -SrcFile PreProcess(Stream& in); - - -enum Kind { - MACRO, ENUM, TYPEDEF, VARIABLE, - STRUCT, FUNCTION, - INSTANCEFUNCTION, INSTANCEVARIABLE, - CLASSFUNCTION, CLASSVARIABLE, - CONSTRUCTOR, DESTRUCTOR, - STRUCTTEMPLATE, FUNCTIONTEMPLATE, - INSTANCEFUNCTIONTEMPLATE, CLASSFUNCTIONTEMPLATE, - INLINEFRIEND, - OTHER -}; - -enum { - PRIVATE, PROTECTED, PUBLIC -}; - -struct CppItem { - String package; - - int kind; - String name; - int access; - String tparam; - String header; - String param; - String ender; - String pname; - String tname; - - String file; - int line; - - CppItem() { line = 0; } -}; - -typedef ArrayMap CppNest; -typedef ArrayMap CppNamespace; -typedef ArrayMap CppBase; - -class Parser { - struct Context { - String nameing; - String nesting; - Index typenames; - int access; - - void operator<<=(const Context& t); - - String Dump() const; - }; - - struct Decla { - bool s_static:1; - bool s_extern:1; - bool s_register:1; - bool s_auto:1; - bool s_mutable:1; - bool s_explicit:1; - bool s_virtual:1; - String name; - bool function:1; - bool type_def:1; - bool isfriend:1; - bool istemplate:1; - bool istructor:1; - bool isdestructor:1; - bool isptr:1; - bool nofn:1; - - String header; - String ender; - String template_params; - String tnames; - String natural; - - Decla(); - }; - - struct Decl : Decla { - Array param; - }; - - SrcFile file; - Lex lex; - String package, filename; - Context context; - - int lpos, line; - - CppBase *base; - - int RPtr(); - - bool Key(int code); - bool EatBody(); - - void Cv(); - String SimpleType(); - void Qualifier(); - void ParamList(Decl& d); - void Declarator(Decl& d, const char *p); - void EatInitializers(); - Decl Type(); - Array Declaration(bool l0 = false, bool more = false); - void Do(); - void Elipsis(Decl& d); - Decl& Finish(Decl& d, const char *p); - bool Nest(const String& tp, const String& tn); - - String TemplateParams(String& pnames); - String TemplateParams(); - String TemplatePnames(); - String Name(); - String Constant(); - String ReadOper(); - - int GetLine(const char *pos); - void Line(); - void Check(bool b, const char *err); - void CheckKey(int c); - - CppItem& Item(const String& nameing, const String& nesting, const String& item); - -public: - struct Error : public String { Error() {}; Error(const char *s) : String(s) {} }; - - void ThrowError(const String& e); - - void Do(Stream& s, const Vector& ignore, CppBase& base, - const String& package, const String& file) - throw(Parser::Error); -}; - -void Parse(Stream& s, const Vector& ignore, CppBase& base, - const String& package, const String& file) throw(Parser::Error); - -#endif +#ifndef DOCPP_H +#define DOCPP_H + +#include + +enum { + Tmarker_before_first = 255, +#define CPPID(x) tk_##x, +#include "keyword.i" +#undef CPPID +}; + +enum { + t_eof, + t_string = -200, + t_integer, + t_double, + t_character, + t_dblcolon, + t_mulass, + t_divass, + t_modass, + t_xorass, + t_neq, + t_dot_asteriks, + t_elipsis, + t_inc, + t_addass, + t_dec, + t_arrow_asteriks, + t_arrow, + t_subass, + t_and, + t_andass, + t_or, + t_orass, + t_eq, + t_shl, + t_shlass, + t_le, + t_shr, + t_shrass, + t_ge, + te_integeroverflow, + te_badcharacter, + te_badstring, +}; + +const char **CppKeyword(); + +class Lex { +#ifdef _DEBUG + const char *pp; +#endif + const char *ptr; + const char *pos; + + Index id; + Index ignore; + int endkey; + + struct Term : Moveable{ + const char *ptr; + int code; + String text; + double number; + }; + + BiVector term; + + bool Char(int c) { if(*ptr == c) { ptr++; return true; } else return false; } + void AddCode(int code) { Term& tm = term.AddTail(); tm.code = code; tm.ptr = pos; } + void AssOp(int noass, int ass) { AddCode(Char('=') ? ass : noass); } + void Next(); + bool Prepare(int pos); + int GetCharacter(); + +public: + int Code(int pos = 0); + bool IsId(int pos = 0); + String Id(int pos = 0); + int Int(int pos = 0); + double Double(int pos = 0); + int Chr(int pos = 0); + String Text(int pos = 0); + + void Get(int n = 1); + int GetCode() { int q = Code(); Get(); return q; } + String GetId() { String q = Id(); Get(); return q; } + int GetInt() { int q = Int(); Get(); return q; } + double GetDouble() { double q = Double(); Get(); return q; } + int GetChr() { int q = Chr(); Get(); return q; } + String GetText() { String q = Text(); Get(); return q; } + + const char *Pos(int pos = 0); + int operator[](int pos) { return Code(pos); } + operator int() { return Code(0); } + void operator++() { Get(); } + + void operator=(const char *s) { ptr = s; term.Clear(); } + void Ignore(const Vector& ignore); + + Lex(); +}; + +struct SrcFile { + String text; + Vector linepos; +}; + +SrcFile PreProcess(Stream& in); + + +enum Kind { + MACRO, ENUM, TYPEDEF, VARIABLE, + STRUCT, FUNCTION, + INSTANCEFUNCTION, INSTANCEVARIABLE, + CLASSFUNCTION, CLASSVARIABLE, + CONSTRUCTOR, DESTRUCTOR, + STRUCTTEMPLATE, FUNCTIONTEMPLATE, + INSTANCEFUNCTIONTEMPLATE, CLASSFUNCTIONTEMPLATE, + INLINEFRIEND, + OTHER +}; + +enum { + PRIVATE, PROTECTED, PUBLIC +}; + +struct CppItem { + String package; + + int kind; + String name; + int access; + String tparam; + String header; + String param; + String ender; + String pname; + String tname; + + String file; + int line; + + CppItem() { line = 0; } +}; + +typedef ArrayMap CppNest; +typedef ArrayMap CppNamespace; +typedef ArrayMap CppBase; + +class Parser { + struct Context { + String nameing; + String nesting; + Index typenames; + int access; + + void operator<<=(const Context& t); + + String Dump() const; + }; + + struct Decla { + bool s_static:1; + bool s_extern:1; + bool s_register:1; + bool s_auto:1; + bool s_mutable:1; + bool s_explicit:1; + bool s_virtual:1; + String name; + bool function:1; + bool type_def:1; + bool isfriend:1; + bool istemplate:1; + bool istructor:1; + bool isdestructor:1; + bool isptr:1; + bool nofn:1; + + String header; + String ender; + String template_params; + String tnames; + String natural; + + Decla(); + }; + + struct Decl : Decla { + Array param; + }; + + SrcFile file; + Lex lex; + String package, filename; + Context context; + + int lpos, line; + + CppBase *base; + + int RPtr(); + + bool Key(int code); + bool EatBody(); + + void Cv(); + String SimpleType(); + void Qualifier(); + void ParamList(Decl& d); + void Declarator(Decl& d, const char *p); + void EatInitializers(); + Decl Type(); + Array Declaration(bool l0 = false, bool more = false); + void Do(); + void Elipsis(Decl& d); + Decl& Finish(Decl& d, const char *p); + bool Nest(const String& tp, const String& tn); + + String TemplateParams(String& pnames); + String TemplateParams(); + String TemplatePnames(); + String Name(); + String Constant(); + String ReadOper(); + + int GetLine(const char *pos); + void Line(); + void Check(bool b, const char *err); + void CheckKey(int c); + + CppItem& Item(const String& nameing, const String& nesting, const String& item); + +public: + struct Error : public String { Error() {}; Error(const char *s) : String(s) {} }; + + void ThrowError(const String& e); + + void Do(Stream& s, const Vector& ignore, CppBase& base, + const String& package, const String& file) + throw(Parser::Error); +}; + +void Parse(Stream& s, const Vector& ignore, CppBase& base, + const String& package, const String& file) throw(Parser::Error); + +#endif diff --git a/uppsrc/docpp/docpp.upp b/archive/uppsrc/docpp/docpp.upp similarity index 90% rename from uppsrc/docpp/docpp.upp rename to archive/uppsrc/docpp/docpp.upp index f172a5de7..c98d5bbec 100644 --- a/uppsrc/docpp/docpp.upp +++ b/archive/uppsrc/docpp/docpp.upp @@ -1,12 +1,12 @@ -uses - RichEdit; - -file - docpp.h, - keyword.i, - Pre.cpp, - cpplex.cpp, - Parser.cpp, - Info readonly separator, - Copying; - +uses + RichEdit; + +file + docpp.h, + keyword.i, + Pre.cpp, + cpplex.cpp, + Parser.cpp, + Info readonly separator, + Copying; + diff --git a/uppsrc/docpp/keyword.i b/archive/uppsrc/docpp/keyword.i similarity index 93% rename from uppsrc/docpp/keyword.i rename to archive/uppsrc/docpp/keyword.i index 2baa815a5..cc9d72bff 100644 --- a/uppsrc/docpp/keyword.i +++ b/archive/uppsrc/docpp/keyword.i @@ -1,80 +1,80 @@ -#pragma BLITZ_APPROVE - -CPPID(__asm) -CPPID(else) -CPPID(struct) -CPPID(enum) -CPPID(switch) -CPPID(auto) -CPPID(__except) -CPPID(template) -CPPID(explicit) -CPPID(this) -CPPID(bool) -CPPID(extern) -CPPID(mutable) -CPPID(thread) -CPPID(break) -CPPID(false) -CPPID(throw) -CPPID(case) -CPPID(__fastcall) -CPPID(namespace) -CPPID(true) -CPPID(catch) -CPPID(__finally) -CPPID(new) -CPPID(try) -CPPID(__cdecl) -CPPID(float) -CPPID(__try) -CPPID(char) -CPPID(for) -CPPID(operator) -CPPID(typedef) -CPPID(class) -CPPID(friend) -CPPID(private) -CPPID(typeid) -CPPID(const) -CPPID(goto) -CPPID(protected) -CPPID(typename) -CPPID(const_cast) -CPPID(if) -CPPID(public) -CPPID(union) -CPPID(continue) -CPPID(inline) -CPPID(register) -CPPID(unsigned) -CPPID(__declspec) -CPPID(__inline) -CPPID(reinterpret_cast) -CPPID(using) -CPPID(default) -CPPID(int) -CPPID(return) -CPPID(delete) -CPPID(__int8) -CPPID(short) -CPPID(__uuidof) -CPPID(dllexport) -CPPID(__int16) -CPPID(signed) -CPPID(virtual) -CPPID(dllimport) -CPPID(__int32) -CPPID(sizeof) -CPPID(void) -CPPID(do) -CPPID(__int64) -CPPID(static) -CPPID(volatile) -CPPID(double) -CPPID(__leave) -CPPID(static_cast) -CPPID(dynamic_cast) -CPPID(long) -CPPID(__stdcall) -CPPID(while) +#pragma BLITZ_APPROVE + +CPPID(__asm) +CPPID(else) +CPPID(struct) +CPPID(enum) +CPPID(switch) +CPPID(auto) +CPPID(__except) +CPPID(template) +CPPID(explicit) +CPPID(this) +CPPID(bool) +CPPID(extern) +CPPID(mutable) +CPPID(thread) +CPPID(break) +CPPID(false) +CPPID(throw) +CPPID(case) +CPPID(__fastcall) +CPPID(namespace) +CPPID(true) +CPPID(catch) +CPPID(__finally) +CPPID(new) +CPPID(try) +CPPID(__cdecl) +CPPID(float) +CPPID(__try) +CPPID(char) +CPPID(for) +CPPID(operator) +CPPID(typedef) +CPPID(class) +CPPID(friend) +CPPID(private) +CPPID(typeid) +CPPID(const) +CPPID(goto) +CPPID(protected) +CPPID(typename) +CPPID(const_cast) +CPPID(if) +CPPID(public) +CPPID(union) +CPPID(continue) +CPPID(inline) +CPPID(register) +CPPID(unsigned) +CPPID(__declspec) +CPPID(__inline) +CPPID(reinterpret_cast) +CPPID(using) +CPPID(default) +CPPID(int) +CPPID(return) +CPPID(delete) +CPPID(__int8) +CPPID(short) +CPPID(__uuidof) +CPPID(dllexport) +CPPID(__int16) +CPPID(signed) +CPPID(virtual) +CPPID(dllimport) +CPPID(__int32) +CPPID(sizeof) +CPPID(void) +CPPID(do) +CPPID(__int64) +CPPID(static) +CPPID(volatile) +CPPID(double) +CPPID(__leave) +CPPID(static_cast) +CPPID(dynamic_cast) +CPPID(long) +CPPID(__stdcall) +CPPID(while) diff --git a/benchmarks/Sort/Sort.cpp b/benchmarks/Sort/Sort.cpp index 4af52ca5f..ec19c808c 100644 --- a/benchmarks/Sort/Sort.cpp +++ b/benchmarks/Sort/Sort.cpp @@ -8,9 +8,10 @@ using namespace Upp; CONSOLE_APP_MAIN { -// StdLogSetup(LOG_COUT|LOG_FILE); - for(int i = 0; i < 1000; i++) { - Vector w = AliceWords(); + StdLogSetup(LOG_COUT|LOG_FILE); + RDUMP(AliceWords().GetCount()); + for(int i = 0; i < 300; i++) { + Vector w = AliceWords(); { std::vector x; for(auto s : w) @@ -22,8 +23,30 @@ CONSOLE_APP_MAIN RTIMING("Sort Vector"); Sort(w); } + #if 0 ONCELOCK { RDUMPC(w); } + #endif + } + + for(int i = 0; i < 300; i++) { + Vector w; + for(int i = 0; i < 40000; i++) + w.Add(Random()); + { + std::vector x(w.begin(), w.end()); + RTIMING("std::sort std::vector"); + std::sort(x.begin(), x.end()); + } + { + RTIMING("Sort Vector"); + Sort(w); + } + #if 0 + ONCELOCK { + RDUMPC(w); + } + #endif } } diff --git a/configure_makefile b/configure_makefile index e4b2a8257..118148b8b 100755 --- a/configure_makefile +++ b/configure_makefile @@ -31,7 +31,23 @@ fi if [[ "$uname" == 'OpenBSD' ]]; then echo Configuring $1 for OpenBSD - sed -i.bak 's/-DflagPOSIX -DflagLINUX/-DflagPOSIX -DflagBSD -DflagFREEBSD/' $1 + sed -i.bak 's/-DflagPOSIX -DflagLINUX/-DflagPOSIX -DflagBSD -DflagOPENBSD/' $1 + sed -i.bak 's/-Wl,--gc-sections $(LINKOPTIONS)/$(LINKOPTIONS)/' $1 + sed -i.bak 's#LIBPATH =#LIBPATH = -L"/usr/local/lib"#' $1 + sed -i.bak 's#-I./ -I$(UPPOUT)#-I/usr/local/include -I./ -I$(UPPOUT)#' $1 + sed -i.bak 's/GCC-Gcc-Gui-Linux-Main-Posix-Shared/GCC-Bsd-Gcc-Gui-Main-Openbsd-Posix-Shared/' $1 + sed -i.bak 's/GCC-Gcc-Gui-Linux-Posix-Shared/GCC-Bsd-Gcc-Gui-Openbsd-Posix-Shared/' $1 + sed -i.bak 's/GCC-Gcc-Linux-Main-Posix-Shared/GCC-Bsd-Gcc-Main-Openbsd-Posix-Shared/' $1 + sed -i.bak 's/GCC-Gcc-Linux-Posix-Shared/GCC-Bsd-Gcc-Openbsd-Posix-Shared/' $1 + sed -i.bak 's/$(LIBPATH) -Wl,-O,2 $(LDFLAGS)/$(LIBPATH) $(LDFLAGS)/' $1 + sed -i.bak 's/-ldl /-lexecinfo /' $1 + sed -i.bak 's/-lrt / /' $1 + rm $1.bak +fi + +if [[ "$uname" == 'NetBSD' ]]; then + echo Configuring $1 for OpenBSD + sed -i.bak 's/-DflagPOSIX -DflagLINUX/-DflagPOSIX -DflagBSD -DflagNETBSD/' $1 sed -i.bak 's/-Wl,--gc-sections $(LINKOPTIONS)/$(LINKOPTIONS)/' $1 sed -i.bak 's#LIBPATH =#LIBPATH = -L"/usr/local/lib"#' $1 sed -i.bak 's#-I./ -I$(UPPOUT)#-I/usr/local/include -I./ -I$(UPPOUT)#' $1 diff --git a/uppbox/uppweb/Resources/Images/TheIDE.png b/uppbox/uppweb/Resources/Images/TheIDE.png new file mode 100644 index 0000000000000000000000000000000000000000..b3ec8ae5c6972047ab291f9bcbbca39fde12f003 GIT binary patch literal 177761 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

&`{Q$48HxA{(^XgFN=L@no(l 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 fVeyhbGKcQ!C&B#Q)z{+7xfXKv4|Bqq8