mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 06:45:39 -06:00
Improved theide T++ (help) browser
git-svn-id: svn://ultimatepp.org/upp/trunk@454 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
028a3d7697
commit
e6c2027cf5
15 changed files with 536 additions and 270 deletions
|
|
@ -1,12 +1,121 @@
|
|||
TITLE("Heap implementation")
|
||||
COMPRESSED
|
||||
120,156,149,88,107,143,219,54,22,253,43,4,210,166,158,68,51,213,211,150,199,221,96,147,110,131,45,138,164,64,211,162,31,6,193,154,150,105,155,59,146,232,21,169,113,156,197,230,183,239,185,36,245,242,78,18,108,48,200,140,68,242,62,206,125,29,234,46,102,223,124,19,6,225,147,240,43,255,110,255,38,118,188,45,205,251,59,153,166,249,138,199,217,234,254,151,95,151,171,103,127,157,205,211,43,146,18,65,74,178,136,146,60,75,162,52,158,227,191,40,137,226,44,78,210,40,143,151,105,158,36,121,120,91,148,92,235,247,119,101,156,231,43,58,20,7,241,147,120,145,197,209,34,205,211,60,74,22,121,140,179,113,24,198,225,34,206,162,52,201,227,236,118,43,116,241,254,142,231,201,234,217,111,115,28,74,72,19,132,135,209,60,78,23,105,28,38,97,156,66,85,148,231,105,180,200,242,100,57,159,223,22,252,104,164,170,189,46,25,69,113,180,218,68,139,21,108,254,244,233,211,77,148,134,206,130,20,194,162,48,133,169,17,222,133,105,188,136,178,101,184,204,242,40,15,19,
|
||||
8,207,22,97,118,123,228,13,175,62,239,122,246,85,215,23,225,173,52,2,34,158,61,143,162,5,142,204,131,249,147,40,93,192,209,60,73,179,124,17,66,121,28,199,73,18,71,73,188,92,198,217,60,91,220,30,4,223,138,6,46,164,209,220,26,187,8,22,79,178,44,75,177,63,77,179,69,158,198,9,98,147,38,41,160,72,163,101,150,46,179,248,182,22,218,136,237,250,218,193,230,220,239,13,39,187,73,82,30,228,79,230,233,124,25,1,253,116,185,72,195,229,60,90,36,4,94,4,216,231,73,26,47,179,94,146,143,218,191,255,241,159,111,127,122,123,253,199,59,118,167,147,21,251,187,224,71,38,171,99,41,42,81,27,78,104,63,125,127,167,195,21,251,99,253,124,253,156,29,236,186,102,91,249,32,183,98,203,100,109,20,75,88,193,141,216,171,70,10,205,54,92,227,189,170,153,57,8,182,41,85,113,207,180,252,40,216,250,154,233,138,151,101,192,42,177,149,109,197,120,189,101,27,185,191,241,242,233,215,124,197,222,209,30,119,78,251,149,87,246,129,253,176,254,11,3,
|
||||
132,108,115,54,66,223,176,119,109,113,240,251,24,111,4,139,252,10,107,84,91,195,180,128,105,69,54,96,9,246,98,245,168,180,150,155,82,88,115,180,91,186,97,47,139,66,53,91,89,239,25,28,81,109,195,26,161,5,111,138,67,208,9,239,244,54,226,72,107,181,177,158,85,252,159,240,215,156,153,218,117,27,91,109,1,97,63,18,82,223,59,188,248,241,88,202,194,226,168,217,236,197,50,255,150,14,12,46,94,141,221,15,167,238,91,183,240,168,8,93,43,57,253,229,21,59,242,61,185,239,197,151,39,126,214,76,124,56,138,194,104,114,97,47,12,144,61,3,228,74,53,103,182,107,84,101,237,213,103,132,189,178,18,120,41,247,53,4,206,204,1,200,224,231,216,40,23,205,205,153,29,75,110,118,170,169,152,134,72,185,147,5,123,119,214,47,201,136,223,248,201,198,12,207,175,27,33,232,113,215,214,133,117,237,210,141,159,56,130,211,91,107,19,6,65,119,126,192,72,13,188,203,113,118,220,176,223,41,28,80,44,134,152,213,138,213,194,31,48,180,66,126,29,69,179,190,
|
||||
118,7,101,77,134,90,108,87,120,128,127,124,59,126,9,0,55,170,117,225,58,29,84,175,16,162,173,60,11,41,45,38,177,79,29,87,155,140,187,51,27,177,151,117,77,169,129,144,117,206,144,165,178,223,105,229,0,64,133,58,192,163,177,25,199,74,169,13,157,217,1,166,46,150,94,21,137,8,216,86,181,72,196,245,117,41,235,251,238,176,102,48,124,92,52,36,11,150,72,131,234,170,97,204,200,104,159,20,138,12,104,218,194,180,48,34,128,118,195,75,86,183,213,6,166,12,105,233,53,119,14,216,24,14,155,46,108,236,221,156,198,243,101,175,240,94,136,163,158,120,217,11,150,218,89,76,105,91,40,234,33,70,148,103,87,22,51,4,115,164,234,138,116,161,38,133,235,51,108,166,106,209,63,32,196,163,212,184,98,250,117,139,154,224,77,195,109,181,145,94,120,219,82,18,77,144,132,154,14,203,27,246,179,233,131,195,27,35,129,152,183,196,103,100,205,244,159,170,185,31,25,161,199,42,140,54,22,168,182,190,56,68,169,111,77,248,44,66,188,68,232,112,74,187,92,53,
|
||||
135,134,242,178,64,69,8,146,173,71,21,14,51,41,56,0,206,46,195,169,35,229,16,229,163,139,8,165,132,160,90,194,65,106,112,61,42,182,166,236,33,96,235,156,191,98,39,105,14,148,240,27,65,208,64,45,57,189,21,67,11,153,245,15,40,15,108,248,87,43,9,161,66,105,131,157,90,52,192,73,126,116,171,14,223,2,61,14,117,91,98,209,86,250,21,76,222,77,74,212,217,196,31,184,44,57,117,87,159,110,206,223,157,197,163,211,24,244,62,92,246,54,130,250,8,203,237,56,25,142,35,153,84,93,8,54,171,4,175,125,118,77,173,132,13,170,238,66,107,247,82,246,64,205,160,181,175,128,147,106,52,21,147,22,206,139,190,27,140,33,34,75,122,247,120,73,177,59,143,2,50,246,110,236,78,223,103,189,225,56,63,150,74,145,161,236,113,125,111,234,130,120,176,21,240,255,187,56,14,230,163,78,78,51,244,173,58,57,11,187,144,78,199,60,196,25,196,144,212,29,212,41,96,123,9,187,92,207,154,118,183,174,249,218,7,42,135,192,254,229,59,226,184,33,56,44,
|
||||
225,16,134,148,27,66,68,4,212,4,249,130,6,207,13,123,67,253,189,27,57,148,183,1,89,97,91,245,80,47,100,162,104,42,89,211,116,223,136,130,3,18,38,119,236,36,216,125,141,221,248,125,224,15,98,124,36,160,151,212,63,75,165,238,187,198,174,13,90,194,101,83,199,224,105,164,179,202,218,92,242,102,79,78,31,112,184,167,29,93,182,219,228,181,163,23,243,178,160,180,113,146,249,118,139,130,242,18,68,189,213,54,242,44,39,184,14,226,3,155,65,122,238,69,117,99,152,80,234,201,75,37,181,127,127,5,211,15,178,156,120,163,199,154,251,51,254,0,57,1,173,21,191,39,118,3,150,7,184,41,194,196,188,252,105,76,65,61,24,185,126,74,134,81,17,215,31,69,163,172,236,23,112,53,32,76,215,79,237,154,93,120,4,87,107,245,37,174,143,14,204,142,148,84,20,97,154,206,23,105,249,243,110,84,171,223,79,27,84,139,188,166,134,6,113,190,226,72,13,53,54,202,243,123,88,101,57,15,102,227,22,3,228,118,42,248,207,131,232,39,37,217,52,201,138,157,
|
||||
164,50,113,35,192,14,50,106,167,7,81,208,16,153,204,97,219,41,208,230,250,6,23,140,102,192,248,148,119,115,24,114,22,70,225,138,136,219,173,162,58,26,36,118,45,78,67,5,168,13,170,142,210,224,146,169,205,92,3,30,177,47,116,173,183,202,8,63,100,31,153,200,159,157,234,67,125,194,157,199,170,254,214,247,60,74,1,115,82,158,43,75,204,65,162,244,84,137,99,137,158,143,52,130,168,243,64,163,156,79,157,158,215,132,112,48,234,165,190,251,245,179,250,17,150,4,86,15,153,53,170,155,98,224,181,245,156,66,214,210,15,114,123,100,182,87,198,161,230,2,66,108,200,66,135,202,57,170,198,122,247,56,20,99,198,82,138,157,233,114,108,215,199,149,178,187,226,53,246,88,82,188,254,142,150,214,223,17,171,38,132,81,81,198,78,243,157,22,246,36,238,82,200,38,186,145,12,234,72,155,107,46,118,98,82,172,221,126,252,245,34,137,131,201,214,81,34,184,184,131,246,205,116,187,49,13,47,108,246,78,111,83,87,158,134,74,127,235,48,148,160,74,110,93,26,120,
|
||||
210,108,217,37,229,252,103,120,40,218,1,146,19,73,107,21,80,86,218,141,143,208,63,91,74,180,136,141,193,215,201,35,153,37,235,162,177,105,70,141,9,0,72,227,90,205,137,69,1,61,184,113,231,83,166,47,227,74,61,116,165,224,88,31,113,127,42,210,78,6,9,0,109,1,199,178,110,124,158,242,58,162,221,91,68,130,173,18,155,43,23,238,249,171,231,27,119,47,245,50,166,151,79,234,139,54,43,126,96,243,44,11,211,238,22,250,242,136,203,211,7,137,11,7,181,63,109,214,215,59,57,46,206,46,64,190,167,232,33,211,223,184,11,26,69,190,217,243,26,65,181,133,52,39,147,139,67,91,67,233,236,34,39,166,189,192,222,177,6,138,49,64,233,39,177,157,60,32,178,110,234,122,94,211,143,96,220,101,31,164,106,125,8,190,66,247,81,239,83,250,125,25,124,18,72,52,187,104,49,54,29,65,69,45,147,170,45,182,55,114,211,118,84,166,114,92,19,55,86,116,236,154,234,185,191,104,151,234,212,15,220,48,205,109,205,251,203,252,136,24,19,238,52,253,205,73,
|
||||
136,110,35,124,115,87,189,36,11,195,48,112,167,8,177,145,26,40,221,55,234,164,189,168,254,160,161,220,6,35,192,68,181,99,12,54,62,240,178,21,30,96,91,212,22,52,130,150,224,148,48,232,67,87,71,61,44,227,46,246,197,57,20,116,2,122,246,51,253,100,210,71,203,137,38,6,100,191,71,96,135,229,45,228,150,13,173,155,42,86,22,125,186,176,169,226,36,208,160,163,249,63,106,48,179,62,57,175,0,131,224,166,67,218,95,2,182,254,26,254,74,238,247,162,25,179,13,255,165,231,139,29,97,200,247,74,52,123,247,113,197,174,118,105,105,13,238,83,14,251,106,241,97,98,31,70,37,110,247,255,195,88,187,105,87,161,191,194,172,129,99,218,50,233,172,36,176,208,43,20,120,113,119,241,183,252,91,59,130,213,221,164,65,122,218,210,226,215,95,185,105,223,219,95,127,239,184,212,240,105,68,11,43,0,92,249,216,13,146,49,15,187,228,214,190,131,0,189,233,167,171,215,195,24,219,56,100,45,232,163,22,50,6,207,242,181,179,187,59,142,191,186,32,188,91,196,
|
||||
168,160,194,241,113,126,144,141,65,23,244,159,121,198,215,221,209,7,144,209,247,143,9,105,255,194,103,14,207,92,236,29,150,152,36,189,118,103,163,249,250,218,241,205,182,238,96,234,134,73,163,10,16,202,27,123,27,112,5,213,8,211,54,8,196,212,78,100,58,36,249,123,132,27,214,29,144,239,255,11,93,173,175,92,
|
||||
topic "Heap implementation";
|
||||
[2 $$0,0#00000000000000000000000000000000:Default]
|
||||
[i448;a25;kKO9;*@(64)2 $$1,0#37138531426314131252341829483380:class]
|
||||
[l288;2 $$2,2#27521748481378242620020725143825:desc]
|
||||
[a83;*R6 $$3,0#31310162474203024125188417583966:caption]
|
||||
[l288;i1121;b17;O9;~~~.1408;2 $$4,0#10431211400427159095818037425705:param]
|
||||
[i448;a25;kKO9;*@(64)2 $$5,0#37138531426314131252341829483370:item]
|
||||
[*+117 $$6,6#14700283458701402223321329925657:header]
|
||||
[l416;2 $$7,7#55548704457842300043401641954952:nested`-desc]
|
||||
[l288;i448;a25;kO9;*2 $$8,8#64691275497409617375831514634295:nested`-class]
|
||||
[{_}%EN-US
|
||||
[s3; Heap implementation&]
|
||||
[s0; U`+`+ heap is divided into 3 categories based on the block size
|
||||
`- small, medium and big.&]
|
||||
[s0; &]
|
||||
[s6; Small blocks&]
|
||||
[s0; Blocks <`= 256 bytes. Such blocks are 16 bytes rounded, so there
|
||||
is 16 possible sizes there. According to our research, blocks
|
||||
<`= 256 represent the majority of blocks used in C`+`+/U`+`+
|
||||
applications (>98% of all blocks).&]
|
||||
[s0; &]
|
||||
[s0; Small blocks are allocated in 4KB pages. U`+`+ always expects
|
||||
to get any memory from the system 4KB aligned (this is provided
|
||||
by platform specific SysAllocRaw and SysFreeRaw functions).&]
|
||||
[s0; &]
|
||||
[s0; Each 4KB pages is dedicated to single block size. Therefore
|
||||
there is no need to store any per`-block information; instead
|
||||
informations about the whole block is stored in the 32 bytes
|
||||
header at the beginning of 4KB page. This header stores pointer
|
||||
to the list of free blocks in the page, double`-link pointers
|
||||
for the block so that it can be stored in allocator structures,
|
||||
total number of blocks in the 4KB page and number of free blocks
|
||||
in 4KB page.&]
|
||||
[s0; &]
|
||||
[s0; Allocator keeps the list of 4KB page is that are completely
|
||||
used (no free blocks) in 16 element (one element per block size)
|
||||
sFull array of lists, using double`-linked pointers. It stores
|
||||
partially used pages in sWork 16 elements array of litst and
|
||||
unused pages in sFree list.&]
|
||||
[s0; &]
|
||||
[s0; Allocator also uses per`-thread cache of small blocks. In this
|
||||
cache, up to 32 blocks for each of 16 block sizes is cached (linked)
|
||||
without being really deallocated (deallocation requires costly
|
||||
serialization using critical section). If there is no block available
|
||||
in the cache for allocation, 16 blocks are allocated and put
|
||||
into the cache at once (means that serialization is only used
|
||||
once per 16 allocations in the worst case). If block is deallocated
|
||||
and there is already 32 blocks in the cache, 16 blocks from the
|
||||
cache are deallocated within single serialization event (means
|
||||
that serialization is only used once per 16 deallocations in
|
||||
the worst case).&]
|
||||
[s0; &]
|
||||
[s0; Now the critical implementation detail is how, given the pointer
|
||||
to the block in the Free, the header of 4KB page and that way
|
||||
the size of block is decided. More specifically, how is small
|
||||
block determined, because if we know we have small block, we
|
||||
can look at the start of 4KB page. The trick is that larger than
|
||||
256 bytes block are always placed at the address that ends with
|
||||
8 in hex (is 8 bytes aligned and 16 bytes misaligned), while
|
||||
small blocks are always 16 bytes aligned. That makes test simple
|
||||
`- blocks whose address `& 8 is nonzero are >256, if `&8 is zero
|
||||
we have small block and can look at the beginning of 4KB page
|
||||
to get more info.&]
|
||||
[s0; &]
|
||||
[s0; If allocation/deallocation runs out of cache, the real work
|
||||
has to be done:&]
|
||||
[s0; &]
|
||||
[s0; When allocating small block, first sWork list is checked for
|
||||
the block. If no available, sFree list is checked to get free
|
||||
block, if even that is empty, new block is obtained from the
|
||||
system (using SysAllocRaw). Note that allocator keeps the number
|
||||
of free blocks in the header. Implementation detail: there are
|
||||
two possibilities how free blocks can be recorded in the block
|
||||
header. First, there is a single`-linked list of free blocks.
|
||||
Second, for blocks that are initially free (got from sFree or
|
||||
system), portion of free blocks in the 4KB page is left out of
|
||||
free list and managed by `'free`' member `- the offset of last
|
||||
such free block in page. If this offset is >32, free block is
|
||||
obtained using it (subtracting the block size). This is used
|
||||
to avoid the need to link all free blocks in the page when getting
|
||||
new free page.&]
|
||||
[s0; &]
|
||||
[s0; When freeing, number of free blocks in 4KB page is incremented.
|
||||
If it is now 1, it means block has to be moved from sFull to
|
||||
sWork. If it now equals the total number of blocks in page, 4KB
|
||||
page moves to sFree.&]
|
||||
[s0; &]
|
||||
[s0; &]
|
||||
[s6; Medium blocks &]
|
||||
[s0; Blocks >256 and < 65504 bytes. Approximate best`-fit allocator
|
||||
is used for these blocks. Memory is organized in 64KB chunks
|
||||
(obtained using SysAllocRaw). Each allocated block has header
|
||||
with its size and the size of previous block.&]
|
||||
[s0; &]
|
||||
[s0; Allocator keeps an array of lists of free blocks of particular
|
||||
sizes. Size distribution is mostly exponential, blocks lower
|
||||
than 2048 are rounded up to 32 bytes, between 2048 and about
|
||||
35000, rounding exponentially grows up to 2048 and then stays
|
||||
at this value. Each such size has its index in the array of free
|
||||
blocks.&]
|
||||
[s0; &]
|
||||
[s0; When allocating, index is decided based on the size and array
|
||||
is searched starting with that index to obtain the smallest free
|
||||
block (best`-fit) greater than required size. Bigger blocks are
|
||||
divided.&]
|
||||
[s0; &]
|
||||
[s0; When freeing, allocator merges the freed block with previous
|
||||
or next free block if any.&]
|
||||
[s0; &]
|
||||
[s0; Note that master header of 64KB blocks and all operations are
|
||||
designed so that resulting pointers are NOT 16 byte aligned (see
|
||||
description of small blocks).&]
|
||||
[s0; &]
|
||||
[s0; &]
|
||||
[s6; Big blocks&]
|
||||
[s0; For blocks bigger than 65504 bytes, allocator simply uses SysAllocRaw
|
||||
to directly obtain virtual memory. It stores information about
|
||||
the block in the header at the beginning of block, also makeing
|
||||
block 16`-bytes unaligned in the process. Free then returns virtual
|
||||
memory back to the system.&]
|
||||
[s0; ]
|
||||
|
|
@ -15,7 +15,7 @@ void HelpWindow::FinishText(RichText& text)
|
|||
|
||||
bool HelpWindow::GoTo0(const String& link)
|
||||
{
|
||||
if(IsNull(link))
|
||||
if(IsNull(link) || current_link == link)
|
||||
return false;
|
||||
Topic t = AcquireTopic(link);
|
||||
SetBar();
|
||||
|
|
@ -28,6 +28,7 @@ bool HelpWindow::GoTo0(const String& link)
|
|||
view.Pick(txt, zoom);
|
||||
view.GotoLabel(label, true);
|
||||
tree.FindSetCursor(topic);
|
||||
current_link = link;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -139,7 +140,6 @@ bool HelpWindow::Key(dword key, int count)
|
|||
|
||||
void HelpWindow::ClearTree()
|
||||
{
|
||||
tree_view.Zoom(1);
|
||||
tree.Clear();
|
||||
}
|
||||
|
||||
|
|
@ -178,6 +178,19 @@ void HelpWindow::TreeCursor()
|
|||
GoTo(~tree);
|
||||
}
|
||||
|
||||
void HelpWindow::CurrentOrHome()
|
||||
{
|
||||
if(~tree != current_link) {
|
||||
if(tree.FindSetCursor(current_link))
|
||||
return;
|
||||
for(int i = 0; i < tree.GetLineCount(); i++) {
|
||||
Value k = tree.Get(tree.GetItemAtLine(i));
|
||||
if(!IsNull(k) && tree.FindSetCursor(k))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HelpWindow::HelpWindow()
|
||||
{
|
||||
tree_view.Horz(tree, view);
|
||||
|
|
@ -194,10 +207,11 @@ HelpWindow::HelpWindow()
|
|||
SetZoom();
|
||||
view.Margins(Rect(12, 12, 2, 2));
|
||||
SetRect(Ctrl::GetWorkArea().Deflated(80));
|
||||
tree <<= THISBACK(TreeCursor);
|
||||
tree.WhenSel = THISBACK(TreeCursor);
|
||||
tree.NoRoot();
|
||||
Icon(CtrlImg::help());
|
||||
SetBar();
|
||||
tree.BackPaint();
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ private:
|
|||
Index<String> tree_ndx;
|
||||
String topic;
|
||||
String label;
|
||||
String current_link;
|
||||
|
||||
bool GoTo0(const String& link);
|
||||
void Back();
|
||||
|
|
@ -189,9 +190,11 @@ public:
|
|||
void SortTree(int id = 0);
|
||||
void FinishTree();
|
||||
void OpenDeep(int id = 0);
|
||||
void CurrentOrHome();
|
||||
|
||||
String GetCurrent() const { return topic; }
|
||||
String GetCurrentLabel() const { return label; }
|
||||
String GetCurrentLink() const { return current_link; }
|
||||
|
||||
typedef HelpWindow CLASSNAME;
|
||||
|
||||
|
|
|
|||
|
|
@ -276,10 +276,10 @@ void RichTextView::GotoLabel(const String& lbl, bool dohighlight)
|
|||
sb = f[i].py.y;
|
||||
if(dohighlight)
|
||||
highlight = f[i].pos;
|
||||
Refresh();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void RichTextView::Clear()
|
||||
|
|
|
|||
|
|
@ -367,6 +367,16 @@ void TreeCtrl::ReLine(int itemi, int level, Size& sz)
|
|||
RemoveCtrls(m.child[i]);
|
||||
}
|
||||
|
||||
void TreeCtrl::SyncAfterSync(Ptr<Ctrl> restorefocus)
|
||||
{
|
||||
if(treesize != sb.GetTotal()) {
|
||||
sb.SetTotal(treesize);
|
||||
Refresh();
|
||||
}
|
||||
SyncCtrls(true, restorefocus);
|
||||
SyncInfo();
|
||||
}
|
||||
|
||||
void TreeCtrl::SyncTree()
|
||||
{
|
||||
if(!dirty)
|
||||
|
|
@ -389,16 +399,11 @@ void TreeCtrl::SyncTree()
|
|||
ReLine(0, 0, treesize);
|
||||
treesize.cy = max(0, treesize.cy);
|
||||
treesize.cx += levelcx;
|
||||
if(treesize != sb.GetTotal()) {
|
||||
sb.SetTotal(treesize);
|
||||
Refresh();
|
||||
}
|
||||
cursor = -1;
|
||||
dirty = false;
|
||||
if(cursorid >= 0)
|
||||
SetCursor(cursorid, false, false, false);
|
||||
SyncCtrls(true, restorefocus);
|
||||
PostCallback(PTEBACK(SyncInfo));
|
||||
PostCallback(PTEBACK1(SyncAfterSync, restorefocus));
|
||||
}
|
||||
|
||||
void TreeCtrl::SyncCtrls(bool add, Ctrl *restorefocus)
|
||||
|
|
@ -591,7 +596,7 @@ void TreeCtrl::SetCursorLine(int i, bool sc, bool sel, bool cb)
|
|||
return;
|
||||
if(cb) {
|
||||
WhenCursor();
|
||||
if (!multiselect) WhenSel();
|
||||
if(!multiselect) WhenSel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ private:
|
|||
void GatherSel(int id, Vector<int>& sel) const;
|
||||
void DoClick(Point p, dword flags, bool down);
|
||||
void SyncInfo();
|
||||
void SyncAfterSync(Ptr<Ctrl> restorefocus);
|
||||
|
||||
protected:
|
||||
virtual void SetOption(int id);
|
||||
|
|
|
|||
99
uppsrc/ide/About.cpp
Normal file
99
uppsrc/ide/About.cpp
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
#include "ide.h"
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#include "shellapi.h"
|
||||
#endif
|
||||
|
||||
#define TOPICFILE <ide/app.tpp/all.i>
|
||||
#include <Core/topic_group.h>
|
||||
|
||||
Size MakeLogo(Ctrl& parent, Array<Ctrl>& ctrl)
|
||||
{
|
||||
Image logo = IdeImg::logo();
|
||||
Size isz = logo.GetSize();
|
||||
ImageCtrl& l = ctrl.Create<ImageCtrl>();
|
||||
Label& v = ctrl.Create<Label>();
|
||||
Label& v1 = ctrl.Create<Label>();
|
||||
l.SetImage(logo);
|
||||
Size sz = Size(isz.cx, isz.cy + 80);
|
||||
v = IDE_VERSION;
|
||||
v.LeftPos(300, 100).TopPos(90, 40);
|
||||
if(sizeof(void *) == 8) {
|
||||
v = IDE_VERSION " (64 bit)";
|
||||
v.RightPos(3, Ctrl::MINSIZE).TopPos(90, 40);
|
||||
}
|
||||
l.Add(v);
|
||||
v.SetFont(Arial(20));
|
||||
v.SetInk(Blend(Gray, Blue));
|
||||
v1 = Format("%d`KB", MemoryUsedKb());
|
||||
v1.LeftPos(300, 100).BottomPos(20, 12);
|
||||
v1.SetFont(Arial(10));
|
||||
l.Add(v1);
|
||||
parent.Add(ctrl.Create<StaticRect>().Color(White).SizePos());
|
||||
parent.Add(l.TopPos(0, isz.cy).LeftPos(0, isz.cx));
|
||||
parent.Add(ctrl.Create<StaticRect>().Color(Blue).LeftPos(2, isz.cx - 4).TopPos(isz.cy, 1));
|
||||
RichTextView& w = ctrl.Create<RichTextView>();
|
||||
w.SetQTF(GetTopic("ide/app/Sponsor$en-us"));
|
||||
w.PageWidth(2900);
|
||||
w.NoSb();
|
||||
w.SetFrame(NullFrame());
|
||||
parent.Add(w.TopPos(isz.cy + 3, 99).LeftPos(0, isz.cx));
|
||||
return sz;
|
||||
}
|
||||
|
||||
struct Splash : Ctrl {
|
||||
Array<Ctrl> ctrl;
|
||||
|
||||
Splash() {
|
||||
SetRect(GetWorkArea().CenterRect(MakeLogo(*this, ctrl) + 2));
|
||||
SetFrame(BlackFrame());
|
||||
}
|
||||
};
|
||||
|
||||
void HideSplash()
|
||||
{
|
||||
if(Single<Splash>().IsOpen())
|
||||
Single<Splash>().Close();
|
||||
}
|
||||
|
||||
void ShowSplash()
|
||||
{
|
||||
Single<Splash>().PopUp(NULL, false, false);
|
||||
SetTimeCallback(750, callback(HideSplash));
|
||||
}
|
||||
|
||||
bool IsSplashOpen()
|
||||
{
|
||||
return Single<Splash>().IsOpen();
|
||||
}
|
||||
|
||||
struct AboutDlg : TopWindow {
|
||||
Array<Ctrl> ctrl;
|
||||
RichTextView about;
|
||||
|
||||
typedef AboutDlg CLASSNAME;
|
||||
|
||||
virtual bool Key(dword key, int) {
|
||||
if(key == K_ALT_M)
|
||||
MemoryProfileInfo();
|
||||
return false;
|
||||
}
|
||||
|
||||
AboutDlg() {
|
||||
Size isz = MakeLogo(*this, ctrl);
|
||||
SetRect(0, 0, 1000, isz.cy);
|
||||
about.SetQTF(GetTopic("ide/app/About$en-us"), Zoom(130, 1024));
|
||||
about.SetZoom(Zoom(1, 1));
|
||||
about.RightPos(0, 1000 - isz.cx).VSizePos();
|
||||
about.HMargins(4);
|
||||
about.SetFrame(NullFrame());
|
||||
Background(PaintRect(ColorDisplay(), SColorPaper()));
|
||||
Add(about);
|
||||
Title("About TheIDE");
|
||||
}
|
||||
};
|
||||
|
||||
void Ide::About()
|
||||
{
|
||||
AboutDlg().Execute();
|
||||
}
|
||||
|
|
@ -217,17 +217,21 @@ struct TopicInfo : Moveable<TopicInfo> {
|
|||
Vector<int> words;
|
||||
};
|
||||
|
||||
String GetTopicPath(const TopicLink& link);
|
||||
String GetTopicPath(const String& link);
|
||||
|
||||
void SyncRefs();
|
||||
void SyncTopicFile(const RichText& text, const String& link, const String& path,
|
||||
const String& title);
|
||||
void SyncTopicFile(const String& link, const String& path);
|
||||
void SyncTopicFile(const String& link);
|
||||
String GetTopicTitle(const String& link);
|
||||
void InvalidateTopicInfoPath(const String& path);
|
||||
|
||||
Vector<String> GetRefLinks(const String& ref);
|
||||
|
||||
int TopicWordIndex(const String& w);
|
||||
|
||||
bool MatchTopicLink(const String& link, const Vector<int>& query);
|
||||
int MatchWord(const Vector<int>& w, const String& pattern);
|
||||
bool MatchTopicLink(const String& link, const Vector<String>& query);
|
||||
|
||||
#define LAYOUTFILE <ide/Browser/Topic.lay>
|
||||
#include <CtrlCore/lay.h>
|
||||
|
|
@ -296,6 +300,7 @@ protected:
|
|||
static String lasttemplate;
|
||||
static int lastlang;
|
||||
static bool allfonts;
|
||||
static int serial;
|
||||
|
||||
struct FileInfo {
|
||||
Time time;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,20 @@ bool ParseTopicFileName(const String& fn, String& topic, int& lang)
|
|||
return lang;
|
||||
}
|
||||
|
||||
String GetTopicPath(const TopicLink& tl)
|
||||
{
|
||||
if(IsNull(tl.package))
|
||||
return Null;
|
||||
return AppendFileName(
|
||||
AppendFileName(PackageDirectory(tl.package), tl.group + ".tpp"),
|
||||
tl.topic + ".tpp");
|
||||
}
|
||||
|
||||
String GetTopicPath(const String& link)
|
||||
{
|
||||
return GetTopicPath(ParseTopicLink(link));
|
||||
}
|
||||
|
||||
Topic ReadTopic(const char *text)
|
||||
{
|
||||
Topic topic;
|
||||
|
|
|
|||
|
|
@ -109,11 +109,11 @@ void TopicEditor::Load(const String& fn)
|
|||
title.ClearModify();
|
||||
}
|
||||
|
||||
int sSerial = 0;
|
||||
int TopicEditor::serial;
|
||||
|
||||
int TopicEditor::GetSerial()
|
||||
{
|
||||
return sSerial;
|
||||
return serial;
|
||||
}
|
||||
|
||||
void TopicEditor::SaveTopic()
|
||||
|
|
@ -141,7 +141,7 @@ void TopicEditor::SaveTopic()
|
|||
return;
|
||||
String r = WriteTopic((String)~title, editor.Get());
|
||||
if(LoadFile(topicpath) != r) {
|
||||
sSerial++;
|
||||
serial++;
|
||||
SaveFile(topicpath, r);
|
||||
if(FileExists(AppendFileName(grouppath, "all.i")))
|
||||
SaveFile(ForceExt(topicpath, ".tppi"), WriteTopicI((String)~title, editor.Get()));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include "Browser.h"
|
||||
|
||||
#define LLOG(x) // DLOG(x)
|
||||
|
||||
Index<String>& ref_link()
|
||||
{
|
||||
static Index<String> x;
|
||||
|
|
@ -58,25 +60,24 @@ struct ScanTopicIterator : RichText::Iterator {
|
|||
Index<int> words;
|
||||
Index<String> ref;
|
||||
|
||||
virtual bool operator()(int pos, const RichPara& para)
|
||||
virtual bool operator()(int pos, const RichPara& para)// A++ bug here....
|
||||
{
|
||||
if(!IsNull(para.format.label)) {
|
||||
AddLinkRef(link, para.format.label);
|
||||
ref.FindAdd(para.format.label);
|
||||
}
|
||||
|
||||
for(int i = 0; i < para.part.GetCount(); i++)
|
||||
if(para.part[i].IsText()) {
|
||||
const wchar *s = para.part[i].text;
|
||||
for(;;) {
|
||||
while(!IsLetter(*s) && *s)
|
||||
while(!IsLetter(*s) && !IsDigit(*s) && *s)
|
||||
s++;
|
||||
if(*s == '\0')
|
||||
break;
|
||||
WStringBuffer wb;
|
||||
while(IsLetter(*s))
|
||||
wb.Cat(ToLower(*s++));
|
||||
words.FindAdd(TopicWordIndex(FromUnicode(wb)));
|
||||
StringBuffer sb;
|
||||
while(IsLetter(*s) || IsDigit(*s))
|
||||
sb.Cat(ToAscii(ToLower(*s++)));
|
||||
words.FindAdd(TopicWordIndex(sb));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -95,6 +96,8 @@ String TopicCacheName(const char *path)
|
|||
return AppendFileName(cfg, ForceExt(Filter(path, NoSlashDot), ".tdx"));
|
||||
}
|
||||
|
||||
const char *tdx_version = "tdx version 2.0";
|
||||
|
||||
void SyncTopicFile(const RichText& text, const String& link, const String& path, const String& title)
|
||||
{
|
||||
ClearLinkRef(link);
|
||||
|
|
@ -103,25 +106,28 @@ void SyncTopicFile(const RichText& text, const String& link, const String& path,
|
|||
sti.link = link;
|
||||
text.Iterate(sti);
|
||||
|
||||
TopicInfo& ti = topic_info().GetAdd(link);
|
||||
TopicInfo& ti = topic_info().GetPut(link);
|
||||
ti.title = title;
|
||||
ti.path = path;
|
||||
ti.time = FileGetTime(path);
|
||||
ti.words = sti.words.PickKeys();
|
||||
Sort(ti.words);
|
||||
|
||||
FileOut out(TopicCacheName(path));
|
||||
out << tdx_version << "\n";
|
||||
out << title << '\n';
|
||||
for(int i = 0; i < sti.ref.GetCount(); i++)
|
||||
out << sti.ref[i] << '\n';
|
||||
out << '\n';
|
||||
const Index<String>& ws = TopicWords();
|
||||
for(int i = 0; i < ti.words.GetCount(); i++)
|
||||
out << TopicIndexWord(ti.words[i]) << '\n';
|
||||
out << ws[ti.words[i]] << '\n';
|
||||
}
|
||||
|
||||
void SyncTopicFile(const String& link, const String& path)
|
||||
void SyncTopicFile(const String& link)
|
||||
{
|
||||
TopicInfo& ti = topic_info().GetAdd(link);
|
||||
String path = GetTopicPath(link);
|
||||
LLOG("SyncTopicFile " << link << " path: " << path);
|
||||
TopicInfo& ti = topic_info().GetPut(link);
|
||||
Time tm = FileGetTime(path);
|
||||
if(ti.path == ":ide:" || ti.path == path && ti.time == tm)
|
||||
return;
|
||||
|
|
@ -129,29 +135,42 @@ void SyncTopicFile(const String& link, const String& path)
|
|||
if(FileGetTime(fn) > tm) {
|
||||
ClearLinkRef(link);
|
||||
FileIn in(fn);
|
||||
ti.title = in.GetLine();
|
||||
ti.words.Clear();
|
||||
ti.path = path;
|
||||
ti.time = tm;
|
||||
while(!in.IsEof()) {
|
||||
String x = in.GetLine();
|
||||
if(IsNull(x))
|
||||
break;
|
||||
AddLinkRef(link, x);
|
||||
if(in) {
|
||||
String s = in.GetLine();
|
||||
if(s == tdx_version) {
|
||||
ti.title = in.GetLine();
|
||||
ti.words.Clear();
|
||||
ti.path = path;
|
||||
ti.time = tm;
|
||||
while(!in.IsEof()) {
|
||||
String x = in.GetLine();
|
||||
if(IsNull(x))
|
||||
break;
|
||||
AddLinkRef(link, x);
|
||||
}
|
||||
while(!in.IsEof()) {
|
||||
String x = in.GetLine();
|
||||
if(IsNull(x))
|
||||
break;
|
||||
ti.words.Add(TopicWordIndex(x));
|
||||
}
|
||||
Sort(ti.words);
|
||||
return;
|
||||
}
|
||||
}
|
||||
while(!in.IsEof()) {
|
||||
String x = in.GetLine();
|
||||
if(IsNull(x))
|
||||
break;
|
||||
ti.words.Add(TopicWordIndex(x));
|
||||
}
|
||||
Sort(ti.words);
|
||||
return;
|
||||
}
|
||||
Topic tp = ReadTopic(LoadFile(path));
|
||||
SyncTopicFile(ParseQTF(tp.text), link, path, tp.title);
|
||||
}
|
||||
|
||||
void InvalidateTopicInfoPath(const String& path)
|
||||
{
|
||||
VectorMap<String, TopicInfo>& t = topic_info();
|
||||
for(int i = 0; i < t.GetCount(); i++)
|
||||
if(t[i].path == path)
|
||||
t.Unlink(i);
|
||||
}
|
||||
|
||||
void SyncRefsDir(const char *dir, const String& rel, Progress& pi)
|
||||
{
|
||||
for(FindFile pff(AppendFileName(dir, "*.*")); pff; pff.Next()) {
|
||||
|
|
@ -171,7 +190,7 @@ void SyncRefsDir(const char *dir, const String& rel, Progress& pi)
|
|||
tl.topic = GetFileTitle(ft.GetName());
|
||||
String link = TopicLinkString(tl);
|
||||
pi.SetText("Indexing topic " + tl.topic);
|
||||
SyncTopicFile(link, path);
|
||||
SyncTopicFile(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -203,18 +222,32 @@ Vector<String> GetRefLinks(const String& ref)
|
|||
|
||||
String GetTopicTitle(const String& link)
|
||||
{
|
||||
SyncTopicFile(link);
|
||||
int q = topic_info().Find(link);
|
||||
return q >= 0 ? topic_info()[q].title : Null;
|
||||
}
|
||||
|
||||
bool MatchTopicLink(const String& link, const Vector<int>& query)
|
||||
int MatchWord(const Vector<int>& w, const String& pattern)
|
||||
{
|
||||
const Index<String>& ws = TopicWords();
|
||||
for(int i = 0; i < w.GetCount(); i++) {
|
||||
String wrd = ws[w[i]];
|
||||
if(wrd.GetCount() >= pattern.GetCount() && memcmp(wrd, pattern, pattern.GetCount()) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool MatchTopicLink(const String& link, const Vector<String>& query)
|
||||
{
|
||||
// TIMING("MatchTopicLink"); _DBG_
|
||||
SyncTopicFile(link);
|
||||
int q = topic_info().Find(link);
|
||||
if(q < 0)
|
||||
return false;
|
||||
TopicInfo& f = topic_info()[q];
|
||||
for(int i = 0; i < query.GetCount(); i++)
|
||||
if(FindIndex(f.words, query[i]) < 0)
|
||||
if(MatchWord(f.words, query[i]) < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,6 +253,7 @@ void TopicEditor::NewTopic()
|
|||
SaveInc();
|
||||
topic.FindSetCursor(GetFileTitle(fn));
|
||||
editor.SetFocus();
|
||||
serial++;
|
||||
}
|
||||
|
||||
void TopicEditor::RenameTopic()
|
||||
|
|
@ -275,11 +276,14 @@ void TopicEditor::RenameTopic()
|
|||
}
|
||||
Flush();
|
||||
FileMove(p, np);
|
||||
InvalidateTopicInfoPath(p);
|
||||
InvalidateTopicInfoPath(np);
|
||||
Open(grouppath);
|
||||
Load(np);
|
||||
SaveInc();
|
||||
topic.FindSetCursor(GetFileTitle(np));
|
||||
editor.SetFocus();
|
||||
serial++;
|
||||
}
|
||||
|
||||
void TopicEditor::RemoveTopic()
|
||||
|
|
@ -296,6 +300,7 @@ void TopicEditor::RemoveTopic()
|
|||
topic.SetCursor(q);
|
||||
if(q >= 0)
|
||||
editor.SetFocus();
|
||||
InvalidateTopicInfoPath(p);
|
||||
}
|
||||
|
||||
void TopicEditor::SaveAsTemplate()
|
||||
|
|
|
|||
|
|
@ -1,103 +1,5 @@
|
|||
#include "ide.h"
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#include "shellapi.h"
|
||||
#endif
|
||||
|
||||
#define TOPICFILE <ide/app.tpp/all.i>
|
||||
#include <Core/topic_group.h>
|
||||
|
||||
Size MakeLogo(Ctrl& parent, Array<Ctrl>& ctrl)
|
||||
{
|
||||
Image logo = IdeImg::logo();
|
||||
Size isz = logo.GetSize();
|
||||
ImageCtrl& l = ctrl.Create<ImageCtrl>();
|
||||
Label& v = ctrl.Create<Label>();
|
||||
Label& v1 = ctrl.Create<Label>();
|
||||
l.SetImage(logo);
|
||||
Size sz = Size(isz.cx, isz.cy + 80);
|
||||
v = IDE_VERSION;
|
||||
v.LeftPos(300, 100).TopPos(90, 40);
|
||||
if(sizeof(void *) == 8) {
|
||||
v = IDE_VERSION " (64 bit)";
|
||||
v.RightPos(3, Ctrl::MINSIZE).TopPos(90, 40);
|
||||
}
|
||||
l.Add(v);
|
||||
v.SetFont(Arial(20));
|
||||
v.SetInk(Blend(Gray, Blue));
|
||||
v1 = Format("%d`KB", MemoryUsedKb());
|
||||
v1.LeftPos(300, 100).BottomPos(20, 12);
|
||||
v1.SetFont(Arial(10));
|
||||
l.Add(v1);
|
||||
parent.Add(ctrl.Create<StaticRect>().Color(White).SizePos());
|
||||
parent.Add(l.TopPos(0, isz.cy).LeftPos(0, isz.cx));
|
||||
parent.Add(ctrl.Create<StaticRect>().Color(Blue).LeftPos(2, isz.cx - 4).TopPos(isz.cy, 1));
|
||||
RichTextView& w = ctrl.Create<RichTextView>();
|
||||
w.SetQTF(GetTopic("ide/app/Sponsor$en-us"));
|
||||
w.PageWidth(2900);
|
||||
w.NoSb();
|
||||
w.SetFrame(NullFrame());
|
||||
parent.Add(w.TopPos(isz.cy + 3, 99).LeftPos(0, isz.cx));
|
||||
return sz;
|
||||
}
|
||||
|
||||
struct Splash : Ctrl {
|
||||
Array<Ctrl> ctrl;
|
||||
|
||||
Splash() {
|
||||
SetRect(GetWorkArea().CenterRect(MakeLogo(*this, ctrl) + 2));
|
||||
SetFrame(BlackFrame());
|
||||
}
|
||||
};
|
||||
|
||||
void HideSplash()
|
||||
{
|
||||
if(Single<Splash>().IsOpen())
|
||||
Single<Splash>().Close();
|
||||
}
|
||||
|
||||
void ShowSplash()
|
||||
{
|
||||
Single<Splash>().PopUp(NULL, false, false);
|
||||
SetTimeCallback(750, callback(HideSplash));
|
||||
}
|
||||
|
||||
bool IsSplashOpen()
|
||||
{
|
||||
return Single<Splash>().IsOpen();
|
||||
}
|
||||
|
||||
struct AboutDlg : TopWindow {
|
||||
Array<Ctrl> ctrl;
|
||||
RichTextView about;
|
||||
|
||||
typedef AboutDlg CLASSNAME;
|
||||
|
||||
virtual bool Key(dword key, int) {
|
||||
if(key == K_ALT_M)
|
||||
MemoryProfileInfo();
|
||||
return false;
|
||||
}
|
||||
|
||||
AboutDlg() {
|
||||
Size isz = MakeLogo(*this, ctrl);
|
||||
SetRect(0, 0, 1000, isz.cy);
|
||||
about.SetQTF(GetTopic("ide/app/About$en-us"), Zoom(130, 1024));
|
||||
about.SetZoom(Zoom(1, 1));
|
||||
about.RightPos(0, 1000 - isz.cx).VSizePos();
|
||||
about.HMargins(4);
|
||||
about.SetFrame(NullFrame());
|
||||
Background(PaintRect(ColorDisplay(), SColorPaper()));
|
||||
Add(about);
|
||||
Title("About TheIDE");
|
||||
}
|
||||
};
|
||||
|
||||
void Ide::About()
|
||||
{
|
||||
AboutDlg().Execute();
|
||||
}
|
||||
|
||||
struct GatherLinksIterator : RichText::Iterator {
|
||||
Index<String> link;
|
||||
|
||||
|
|
@ -130,89 +32,119 @@ void GatherLinks(Index<String>& link, const char *topic)
|
|||
|
||||
Index<String> TopicCtrl::idelink;
|
||||
|
||||
void TopicCtrl::ScanDirForTpp(const char *dir, Index<String>& li, Vector<int>& sdx,
|
||||
const String& lng,
|
||||
VectorMap<String, VectorMap<String, Vector<String> > >& map,
|
||||
const String& rel)
|
||||
void TopicCtrl::ScanDirForTpp(const char *dir, const String& rel,
|
||||
Index<String>& donepackage, Index<String>& lang_list)
|
||||
{
|
||||
TopicLink tl;
|
||||
for(FindFile pff(AppendFileName(dir, "*.*")); pff; pff.Next()) {
|
||||
if(pff.IsFolder() && *pff.GetName() != '.') {
|
||||
String pdir = AppendFileName(dir, pff.GetName());
|
||||
tl.package = rel + pff.GetName();
|
||||
for(FindFile ff(AppendFileName(pdir, "*.tpp")); ff; ff.Next())
|
||||
if(ff.IsFolder()) {
|
||||
tl.group = GetFileTitle(ff.GetName());
|
||||
String dir = AppendFileName(pdir, ff.GetName());
|
||||
for(FindFile ft(AppendFileName(dir, "*.tpp")); ft; ft.Next())
|
||||
if(ft.IsFile()) {
|
||||
tl.topic = GetFileTitle(ft.GetName());
|
||||
int q = tl.topic.ReverseFind('$');
|
||||
String l;
|
||||
if(q >= 0) {
|
||||
l = ToUpper(tl.topic.Mid(q + 1));
|
||||
li.FindAdd(l);
|
||||
if(donepackage.Find(tl.package) < 0) {
|
||||
donepackage.Add(tl.package);
|
||||
for(FindFile ff(AppendFileName(pdir, "*.tpp")); ff; ff.Next())
|
||||
if(ff.IsFolder()) {
|
||||
tl.group = GetFileTitle(ff.GetName());
|
||||
String dir = AppendFileName(pdir, ff.GetName());
|
||||
for(FindFile ft(AppendFileName(dir, "*.tpp")); ft; ft.Next())
|
||||
if(ft.IsFile()) {
|
||||
tl.topic = GetFileTitle(ft.GetName());
|
||||
int q = tl.topic.ReverseFind('$');
|
||||
String l;
|
||||
if(q >= 0) {
|
||||
l = ToUpper(tl.topic.Mid(q + 1));
|
||||
lang_list.FindAdd(l);
|
||||
}
|
||||
map.GetAdd(tl.package).GetAdd(tl.group).FindAdd(tl.topic);
|
||||
}
|
||||
String link = TopicLinkString(tl);
|
||||
if(idelink.Find(link) < 0 && MatchTopicLink(link, sdx) &&
|
||||
(lng == "All" || lng == l)) {
|
||||
map.GetAdd(tl.package).GetAdd(tl.group).Add(tl.topic);
|
||||
}
|
||||
}
|
||||
}
|
||||
ScanDirForTpp(pdir, li, sdx, lng, map, tl.package + '/');
|
||||
}
|
||||
}
|
||||
ScanDirForTpp(pdir, tl.package + '/', donepackage, lang_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int map_serial, topic_serial;
|
||||
|
||||
void TopicCtrl::LoadMap()
|
||||
{
|
||||
map.Clear();
|
||||
lang_list.Clear();
|
||||
Vector<String> upp = GetUppDirs();
|
||||
Index<String> donepackage, lang_list;
|
||||
for(int i = 0; i < upp.GetCount(); i++)
|
||||
ScanDirForTpp(upp[i], String(), donepackage, lang_list);
|
||||
Vector<String> l = lang_list.PickKeys();
|
||||
Sort(l);
|
||||
String lng = ~lang;
|
||||
lang.Clear();
|
||||
lang.Add("All");
|
||||
for(int i = 0; i < l.GetCount(); i++)
|
||||
lang.Add(l[i]);
|
||||
if(lng.GetCount() && lang.Find(lng))
|
||||
lang <<= lng;
|
||||
else
|
||||
if(lang.Find("EN-US"))
|
||||
lang <<= "EN-US";
|
||||
else
|
||||
if(lang.GetCount())
|
||||
lang.SetIndex(0);
|
||||
}
|
||||
|
||||
const char *sTopicHome = "\3topic://ide/app/index$en-us";
|
||||
|
||||
void TopicCtrl::SyncDocTree()
|
||||
{
|
||||
if(map_serial != topic_serial) {
|
||||
LoadMap();
|
||||
map_serial = topic_serial;
|
||||
}
|
||||
|
||||
Vector<String> ss = Split((String)~search, ' ');
|
||||
Vector<int> sdx;
|
||||
Vector<String> sdx;
|
||||
for(int i = 0; i < ss.GetCount(); i++)
|
||||
sdx.Add(TopicWordIndex(ToUtf8(ToLower(FromUtf8(ss[i])))));
|
||||
sdx.Add(ToUtf8(ToLower(FromUtf8(ss[i]))));
|
||||
|
||||
ClearTree();
|
||||
|
||||
String hdx = "topic://ide/app/index$en-us";
|
||||
String hdx = sTopicHome + 1;
|
||||
if(idelink.GetCount() == 0)
|
||||
GatherLinks(idelink, hdx);
|
||||
int ide = AddTree(0, IdeImg::Package(), "\3" + hdx, "TheIDE help");
|
||||
for(int i = 0; i < idelink.GetCount(); i++)
|
||||
if(idelink[i] != hdx && MatchTopicLink(idelink[i], sdx))
|
||||
int ide;
|
||||
bool idefirst = true;
|
||||
if(MatchTopicLink(hdx, sdx)) {
|
||||
ide = AddTree(0, IdeImg::Package(), "\3" + hdx, "TheIDE help");
|
||||
idefirst = false;
|
||||
}
|
||||
for(int i = 0; i < idelink.GetCount(); i++) {
|
||||
if(idelink[i] != hdx && MatchTopicLink(idelink[i], sdx)) {
|
||||
if(idefirst) {
|
||||
ide = AddTree(0, IdeImg::Package(), "\3" + hdx, "TheIDE help");
|
||||
idefirst = false;
|
||||
}
|
||||
AddTree(ide, TopicImg::Topic(), "\3" + idelink[i], GetTopic(idelink[i]).title);
|
||||
}
|
||||
}
|
||||
|
||||
Index<String> used;
|
||||
const Workspace& wspc = GetIdeWorkspace();
|
||||
for(int i = 0; i < wspc.GetCount(); i++)
|
||||
used.Add(wspc[i]);
|
||||
|
||||
VectorMap<String, VectorMap<String, Vector<String> > > map;
|
||||
Vector<String> upp = GetUppDirs();
|
||||
int usid;
|
||||
bool usedfirst = true;
|
||||
int otid;
|
||||
bool otherfirst = true;
|
||||
|
||||
String lng = ~lang;
|
||||
lang.Clear();
|
||||
lang.Add("All");
|
||||
Index<String> li;
|
||||
for(int i = 0; i < upp.GetCount(); i++)
|
||||
ScanDirForTpp(upp[i], li, sdx, lng, map, String());
|
||||
Vector<String> sli = li.PickKeys();
|
||||
Sort(sli);
|
||||
for(int i = 0; i < sli.GetCount(); i++)
|
||||
lang.Add(sli[i]);
|
||||
if(lang.Find(lng))
|
||||
lang <<= lng;
|
||||
|
||||
int usid = AddTree(0, IdeImg::Package(), Null, "Used packages");
|
||||
int otid = AddTree(0, IdeImg::Package(), Null, "Other packages");
|
||||
|
||||
for(int i = 0; i < map.GetCount(); i++) {
|
||||
TopicLink tl;
|
||||
tl.package = map.GetKey(i);
|
||||
int pid = AddTree(used.Find(tl.package) >= 0 ? usid : otid,
|
||||
TopicImg::Package(), Null, tl.package);
|
||||
VectorMap<String, Vector<String> >& package = map[i];
|
||||
for(int i = 0; i < package.GetCount(); i++) {
|
||||
tl.group = package.GetKey(i);
|
||||
bool packagefirst = true;
|
||||
int pid;
|
||||
VectorMap<String, Index<String> >& group = map[i];
|
||||
for(int i = 0; i < group.GetCount(); i++) {
|
||||
tl.group = group.GetKey(i);
|
||||
if(all || tl.group == "src" || tl.group == "srcdoc" || tl.group == "srcimp") {
|
||||
String n = tl.group;
|
||||
if(n == "src")
|
||||
|
|
@ -221,23 +153,59 @@ void TopicCtrl::SyncDocTree()
|
|||
n = "Documents";
|
||||
if(n == "srcimp")
|
||||
n = "Implementation";
|
||||
int gid = AddTree(pid, Null, "\1" + tl.group, n);
|
||||
Vector<String> group = package[i];
|
||||
for(int i = 0; i < group.GetCount(); i++) {
|
||||
tl.topic = group[i];
|
||||
String p = TopicLinkString(tl);
|
||||
String t = GetTopicTitle(p);
|
||||
AddTree(gid, TopicImg::Topic(), p, t);
|
||||
int gid;
|
||||
bool groupfirst = true;
|
||||
const Index<String>& topic = group[i];
|
||||
for(int i = 0; i < topic.GetCount(); i++) {
|
||||
tl.topic = topic[i];
|
||||
int q = tl.topic.ReverseFind('$');
|
||||
String l;
|
||||
if(q >= 0)
|
||||
l = ToUpper(tl.topic.Mid(q + 1));
|
||||
String link = TopicLinkString(tl);
|
||||
if(idelink.Find(link) < 0 && MatchTopicLink(link, sdx) && (lng == "All" || lng == l)) {
|
||||
int pd;
|
||||
if(used.Find(tl.package) >= 0) {
|
||||
if(usedfirst) {
|
||||
usid = AddTree(0, IdeImg::Package(), Null, "Used packages");
|
||||
usedfirst = false;
|
||||
}
|
||||
pd = usid;
|
||||
}
|
||||
else {
|
||||
if(otherfirst) {
|
||||
otid = AddTree(0, IdeImg::Package(), Null, "Other packages");
|
||||
otherfirst = false;
|
||||
}
|
||||
pd = otid;
|
||||
}
|
||||
if(packagefirst) {
|
||||
pid = AddTree(pd, TopicImg::Package(), Null, tl.package);
|
||||
packagefirst = false;
|
||||
}
|
||||
if(groupfirst) {
|
||||
gid = AddTree(pid, Null, Null, n);
|
||||
groupfirst = false;
|
||||
}
|
||||
String p = TopicLinkString(tl);
|
||||
String t = GetTopicTitle(p);
|
||||
AddTree(gid, TopicImg::Topic(), p, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SortTree(ide);
|
||||
SortTree(usid);
|
||||
SortTree(otid);
|
||||
if(!idefirst)
|
||||
SortTree(ide);
|
||||
if(!usedfirst)
|
||||
SortTree(usid);
|
||||
if(!otherfirst)
|
||||
SortTree(otid);
|
||||
FinishTree();
|
||||
if(sdx.GetCount())
|
||||
if(sdx.GetCount()) {
|
||||
OpenDeep();
|
||||
CurrentOrHome();
|
||||
}
|
||||
}
|
||||
|
||||
Vector<String> GetTypeRefLinks(const String& t, String &label)
|
||||
|
|
@ -262,22 +230,19 @@ Topic TopicCtrl::AcquireTopic(const String& t)
|
|||
internal = (byte)*topic < 32;
|
||||
if(*topic == '\3')
|
||||
return GetTopic(topic.Mid(1));
|
||||
if(*topic == '\1') {
|
||||
/* if(*topic == '\1') {
|
||||
Topic t;
|
||||
t.title = "Summary";
|
||||
String group = topic.Mid(1);
|
||||
const Workspace& wspc = GetIdeWorkspace();
|
||||
for(int i = 0; i < wspc.GetCount(); i++) {
|
||||
String package = wspc[i];
|
||||
String path = AppendFileName(AppendFileName(PackageDirectory(wspc[i]), group + ".tpp"), "index$en-us.tpp");
|
||||
if(FileExists(path)) {
|
||||
t.text << "[R5* " << wspc[i] << "]&" << ReadTopic(LoadFile(path)).text << "&&&";
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
if(*topic == '\2')
|
||||
topic = topic.Mid(1);
|
||||
int q = group.Find('\2');
|
||||
String package = group.Mid(q + 1);
|
||||
group.Trim(q);
|
||||
String path = AppendFileName(AppendFileName(PackageDirectory(package), group + ".tpp"),
|
||||
"index$en-us.tpp");
|
||||
if(FileExists(path))
|
||||
return ReadTopic(LoadFile(path));
|
||||
return Topic();
|
||||
}*/
|
||||
if(topic[0] == ':' && topic[1] == ':') {
|
||||
String lbl;
|
||||
Vector<String> link = GetTypeRefLinks(topic, lbl);
|
||||
|
|
@ -451,21 +416,16 @@ void TopicCtrl::SShow()
|
|||
|
||||
void TopicCtrl::Search()
|
||||
{
|
||||
if(issearch) {
|
||||
search <<= Null;
|
||||
issearch = false;
|
||||
}
|
||||
else {
|
||||
search.AddHistory(20);
|
||||
issearch = true;
|
||||
}
|
||||
int l, h;
|
||||
search.GetSelection(l, h);
|
||||
SyncDocTree();
|
||||
SetBar();
|
||||
search.SetFocus();
|
||||
search.SetSelection(l, h);
|
||||
}
|
||||
|
||||
void TopicCtrl::SearchWord(const String& s)
|
||||
{
|
||||
issearch = false;
|
||||
search <<= s;
|
||||
Search();
|
||||
}
|
||||
|
|
@ -499,6 +459,11 @@ bool TopicCtrl::Key(dword key, int count)
|
|||
return HelpWindow::Key(key, count);
|
||||
}
|
||||
|
||||
void TopicCtrl::FocusSearch()
|
||||
{
|
||||
search.SetFocus();
|
||||
}
|
||||
|
||||
void TopicCtrl::BarEx(Bar& bar)
|
||||
{
|
||||
bar.Gap();
|
||||
|
|
@ -506,12 +471,10 @@ void TopicCtrl::BarEx(Bar& bar)
|
|||
bar.Add("All topics", IdeImg::HelpAll(), THISBACK(All))
|
||||
.Check(all);
|
||||
bar.Gap(HorzLayoutZoom(30));
|
||||
bar.Add(search_label, HorzLayoutZoom(50));
|
||||
bar.Add(search, HorzLayoutZoom(300));
|
||||
bar.Add("Full text search", IdeImg::HelpSearch(), THISBACK(Search))
|
||||
.Check(issearch);
|
||||
bar.Add("Highlight search keywords in topic", IdeImg::ShowWords(), THISBACK(ShowWords))
|
||||
.Check(showwords);
|
||||
bar.AddKey(K_CTRL_F, THISBACK(FocusSearch));
|
||||
/* bar.Add("Highlight search keywords in topic", IdeImg::ShowWords(), THISBACK(ShowWords))
|
||||
.Check(showwords);*/
|
||||
bar.Add(!internal && GetCurrent().StartsWith("topic:"),
|
||||
IdeImg::show(), THISBACK(SShow));
|
||||
bar.GapRight();
|
||||
|
|
@ -522,9 +485,12 @@ void TopicCtrl::BarEx(Bar& bar)
|
|||
|
||||
void TopicCtrl::Serialize(Stream& s)
|
||||
{
|
||||
int version = 2;
|
||||
int version = 3;
|
||||
s / version;
|
||||
search.SerializeList(s);
|
||||
if(version < 3) {
|
||||
WithDropChoice<EditString> dummy;
|
||||
dummy.SerializeList(s);
|
||||
}
|
||||
if(version >= 1)
|
||||
s % showwords;
|
||||
if(version >= 2)
|
||||
|
|
@ -552,10 +518,11 @@ struct HelpModule : public IdeModule {
|
|||
}
|
||||
virtual IdeDesigner *CreateDesigner(Ide *ide, const char *path, byte cs) {
|
||||
if(IsHelpName(path)) {
|
||||
topic_serial++;
|
||||
GetRefLinks("");
|
||||
if(ide->doc.GetCurrent().IsEmpty()) {
|
||||
ide->doc.SyncDocTree();
|
||||
ide->doc.GoTo(Nvl(recent_topic, "\3topic://ide/app/index$en-us"));
|
||||
ide->doc.GoTo(Nvl(recent_topic, sTopicHome));
|
||||
}
|
||||
HelpDes *d = new HelpDes;
|
||||
d->topic = &ide->doc;
|
||||
|
|
@ -572,17 +539,24 @@ INITBLOCK {
|
|||
RegisterIdeModule(Single<HelpModule>());
|
||||
}
|
||||
|
||||
int CharFilterTopicSearch(int c)
|
||||
{
|
||||
if(c == ' ') return c;
|
||||
c = CharFilterDefaultToUpperAscii(c);
|
||||
return IsAlNum(c) ? c : 0;
|
||||
}
|
||||
|
||||
TopicCtrl::TopicCtrl()
|
||||
{
|
||||
Icon(IdeImg::doc());
|
||||
search_label = "Search: ";
|
||||
showwords = issearch = all = false;
|
||||
lang.Add("All");
|
||||
lang.Add("EN-US");
|
||||
lang <<= "EN-US";
|
||||
showwords = true;
|
||||
all = false;
|
||||
lang <<= THISBACK(Lang);
|
||||
lang.Tip("Language"),
|
||||
search.NullText("Search", StdFont().Italic(), SColorDisabled());
|
||||
search.Tip("Full text search");
|
||||
search <<= THISBACK(Search);
|
||||
search.SetFilter(CharFilterTopicSearch);
|
||||
internal = true;
|
||||
}
|
||||
|
||||
|
|
@ -596,7 +570,7 @@ void Ide::ShowTopics()
|
|||
if(doc_serial != TopicEditor::GetSerial()) {
|
||||
GetRefLinks("");
|
||||
doc.SyncDocTree();
|
||||
doc.GoTo("\3topic://ide/app/index$en-us");
|
||||
doc.GoTo(sTopicHome);
|
||||
doc_serial = TopicEditor::GetSerial();
|
||||
}
|
||||
EditFile(HELPNAME);
|
||||
|
|
@ -607,7 +581,7 @@ void Ide::SearchTopics()
|
|||
String s = editor.GetWord();
|
||||
GetRefLinks("");
|
||||
doc.SyncDocTree();
|
||||
doc.GoTo("\3topic://ide/app/index$en-us");
|
||||
doc.GoTo(sTopicHome);
|
||||
EditFile(HELPNAME);
|
||||
if(s.GetLength())
|
||||
doc.SearchWord(s);
|
||||
|
|
|
|||
|
|
@ -262,23 +262,26 @@ public:
|
|||
virtual void FinishText(RichText& text);
|
||||
|
||||
private:
|
||||
EditString search;
|
||||
DropList lang;
|
||||
bool internal;
|
||||
bool showwords, all;
|
||||
|
||||
VectorMap<String, VectorMap<String, Index<String> > > map;
|
||||
Index<String> lang_list;
|
||||
|
||||
static Index<String> idelink;
|
||||
|
||||
void OpenTopic();
|
||||
void Search();
|
||||
void ShowWords();
|
||||
void All();
|
||||
void Lang();
|
||||
void SShow();
|
||||
void ScanDirForTpp(const char *dir, Index<String>& li, Vector<int>& sdx, const String& lng,
|
||||
VectorMap<String, VectorMap<String, Vector<String> > >& map,
|
||||
const String& rel);
|
||||
|
||||
Label search_label;
|
||||
WithDropChoice<EditString> search;
|
||||
DropList lang;
|
||||
bool internal;
|
||||
bool showwords, issearch, all;
|
||||
static Index<String> idelink;
|
||||
|
||||
void ScanDirForTpp(const char *dir, const String& rel, Index<String>& donepackage,
|
||||
Index<String>& lang_list);
|
||||
void LoadMap();
|
||||
void FocusSearch();
|
||||
|
||||
public:
|
||||
Callback WhenTopic;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ file
|
|||
Install.cpp,
|
||||
idebar.cpp,
|
||||
idewin.cpp,
|
||||
About.cpp,
|
||||
Help.cpp,
|
||||
Util.cpp,
|
||||
Macro.cpp,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue