#help_index "DolDoc/Tree" public Bool DocTreeFind(CDoc *haystack_doc, U8 *needle_path, CDocEntry **_tree_entry=NULL, CDocEntry **_start_indent=NULL, CDocEntry **_end_indent=NULL) {//Find tree widget start and end. I64 i = 0, k = 0; U8 *st1 = StrNew(needle_path), *st2 = MAlloc(StrLen(needle_path) + 1); Bool res = FALSE, unlock_doc = DocLock(haystack_doc); CDocEntry *doc_e = haystack_doc->head.next; if (_tree_entry) *_tree_entry = haystack_doc; if (_start_indent) *_start_indent = haystack_doc; if (_end_indent) *_end_indent = haystack_doc; while (*st1 && doc_e != haystack_doc) { StrFirstRemove(st1, "/", st2); if (*st2) { while (doc_e != haystack_doc) { if (doc_e->type_u8 == DOCT_INDENT) i += doc_e->attr; else if (i == k && doc_e->de_flags & DOCEF_TREE && !StrCompare(doc_e->tag + 3, st2)) { if (*st1) break; else { if (_tree_entry) *_tree_entry = doc_e; i = 0; while (doc_e != haystack_doc && doc_e->type_u8 != DOCT_INDENT) doc_e = doc_e->next; if (doc_e != haystack_doc) { i = doc_e->attr; if (_start_indent) *_start_indent = doc_e; doc_e = doc_e->next; while (doc_e != haystack_doc && i > 0) { if (doc_e->type_u8 == DOCT_INDENT) { i += doc_e->attr; if (i <= 0) { if (_end_indent) *_end_indent = doc_e; res = TRUE; break; } } doc_e = doc_e->next; } } goto ft_done; } } doc_e = doc_e->next; } k += 2; } } ft_done: if (unlock_doc) DocUnlock(haystack_doc); Free(st1); Free(st2); return res; } public Bool DocTreeFFind(U8 *name, U8 *path) {//Find tree widget in file. CDoc *doc = DocRead(name); Bool res = DocTreeFind(doc, path); DocDel(doc); return res; } public Bool DocTreeMake(CDoc *doc, U8 *path) {//Make tree widget. I64 i = 0, j = I64_MIN, k = 0; U8 *st1 = StrNew(path), *st2 = MAlloc(StrLen(path) + 1), *st3 = StrNew(path); Bool res = TRUE, unlock_doc = DocLock(doc); CDocEntry *doc_e = doc->head.next; doc->cur_entry = doc; doc->cur_col = 0; while (*st1 && doc_e != doc) { StrFirstRemove(st1, "/", st2); if (*st2) { while (doc_e != doc) { if (doc_e->type_u8 == DOCT_INDENT) { i += doc_e->attr; if (i == j) { doc->cur_entry = doc_e; doc->cur_col = 0; goto mt_done; } } else if (i == k && doc_e->de_flags & DOCEF_TREE && !StrCompare(doc_e->tag + 3, st2)) { Free(st3); st3 = StrNew(st1); j = i; if (!*st1) res = FALSE; else break; } doc_e = doc_e->next; } k += 2; } } mt_done: if (res) { while (*st3) { StrFirstRemove(st3, "/", st2); if (*st2) { DocPrint(doc, "$TR+C,\"%s\"$\n$ID,2$", st2); doc->cur_entry = DocPrint(doc, "$ID,-2$"); doc->cur_col = 0; } } } if (unlock_doc) DocUnlock(doc); Free(st1); Free(st2); Free(st3); return res; } Bool DocTreeWriteJoin(CDoc *doc, U8 *path, Bool write, U8 *format, I64 argc, I64 *argv) {//Rewrite doc tree branch. CDocEntry *tree_branch, *start_indent, *end_indent; U8 *buf = StrPrintJoin(NULL, format, argc, argv); Bool res, unlock_doc = DocLock(doc); if (res = DocTreeFind(doc, path, &tree_branch, &start_indent, &end_indent)) { DocCut(doc, start_indent->next, end_indent->last); doc->cur_entry = start_indent->next; doc->cur_col = doc->cur_entry->min_col; } else DocTreeMake(doc, path); DocPrint(doc, "%s", buf); if (write && DriveIsWritable(*doc->filename.name)) DocWrite(doc); if (unlock_doc) DocUnlock(doc); Free(buf); return res; } Bool DocTreeAppendJoin(CDoc *doc, U8 *path, Bool write, U8 *format, I64 argc, I64 *argv) {//Append to doc tree branch. CDocEntry *tree_branch, *start_indent, *end_indent; U8 *buf = StrPrintJoin(NULL, format, argc, argv); Bool res, unlock_doc = DocLock(doc); if (res = DocTreeFind(doc, path, &tree_branch, &start_indent, &end_indent)) { doc->cur_entry = end_indent; doc->cur_col = doc->cur_entry->min_col; } else DocTreeMake(doc, path); DocPrint(doc, "%s", buf); if (write && DriveIsWritable(*doc->filename.name)) DocWrite(doc); if (unlock_doc) DocUnlock(doc); Free(buf); return res; } public Bool DocTreeWrite(CDoc *doc, U8 *path, Bool write=TRUE, U8 *format, ...) {//Rewrite doc tree branch. return DocTreeWriteJoin(doc, path, write, format, argc, argv); } public Bool DocTreeAppend(CDoc *doc, U8 *path, Bool write=TRUE, U8 *format, ...) {//Append to doc tree branch. return DocTreeAppendJoin(doc, path, write, format, argc, argv); } public Bool DocTreeFWrite(U8 *name, U8 *path, U8 *format, ...) {//Rewrite doc tree branch in file. CDoc *doc = DocRead(name); Bool res = DocTreeWriteJoin(doc, path, TRUE, format, argc, argv); DocDel(doc); return res; } public Bool DocTreeFAppend(U8 *name, U8 *path, U8 *format, ...) {//Append to doc tree branch in file. CDoc *doc = DocRead(name); Bool res = DocTreeAppendJoin(doc, path, TRUE, format, argc, argv); DocDel(doc); return res; } #help_index "DolDoc/Compiler;Compiler" public I64 ExeDoc(CDoc *doc, I64 ccf_flags=0) {//JIT Compile and execute a document. I64 res; Bool okay = TRUE, unlock_doc=DocLock(doc); CCompCtrl *cc = CompCtrlNew(, ccf_flags | CCF_DONT_FREE_BUF); if (Fs->last_cc != &Fs->next_cc) cc->opts = Fs->last_cc->opts; QueueInsert(cc, Fs->last_cc); LexAttachDoc(cc,, doc); try { Lex(cc); res = ExeCmdLine(cc); } catch { if (Fs->except_ch == 'Compiler' || Fs->except_ch == 'Break') { Fs->catch_except = TRUE; okay = FALSE; res = 0; } } QueueRemove(cc); if (okay) CompCtrlDel(cc); //TODO: can crash if (unlock_doc) DocUnlock(doc); return res; } #help_index "DolDoc/Tree;DolDoc/Compiler;Compiler" public I64 DocTreeExe(CDoc *doc, U8 *path) {//Execute doc tree branch. CDoc *doc2; Bool unlock_doc = DocLock(doc); CDocEntry *tree_branch, *start_indent, *end_indent; I64 res = 0; if (DocTreeFind(doc, path, &tree_branch, &start_indent, &end_indent)) { doc2=DocCopy(doc, tree_branch, end_indent); res=ExeDoc(doc2); DocDel(doc2); } if (unlock_doc) DocUnlock(doc); return res; } public I64 DocTreeFExe(U8 *name, U8 *path) {//Execute doc tree branch in file. I64 res; CDoc *doc = DocRead(name); res = DocTreeExe(doc, path); DocDel(doc); return res; }