#help_index "DolDoc"

I64 DocCharDist(CDoc *doc, I64 x, I64 y)
{
#assert FONT_WIDTH == FONT_HEIGHT
        return (SqrI64(doc->x - x) + SqrI64(doc->y - y)) * FONT_WIDTH * FONT_WIDTH;
}

U0 DocDelToNum(CDoc *doc, I64 num)
{
        CDocEntry *doc_e = doc->head.next, *doc_e2;

        while (num-- > 0 && doc_e != doc)
        {
                doc_e2 = doc_e->next;
                if (!(doc_e->de_flags & (DOCEF_HOLD | DOCEF_FILTER_SKIP)))
                {
                        if (doc_e == doc->cur_entry)
                        {
                                doc->cur_entry  = doc_e2;
                                doc->cur_col    = doc_e2->min_col;
                        }
                        DocEntryDel(doc, doc_e);
                }
                doc_e = doc_e2;
        }
}

U0 DocDelToEntry(CDoc *doc, CDocEntry *clear_entry, Bool clear_holds)
{
        CDocEntry *doc_e = doc->head.next, *doc_e2;

        while (doc_e != doc)
        {
                doc_e2 = doc_e->next;
                if (!(doc_e->de_flags & (DOCEF_HOLD | DOCEF_FILTER_SKIP)) || clear_holds)
                {
                        if (doc_e == doc->cur_entry)
                        {
                                doc->cur_entry  = doc_e2;
                                doc->cur_col    = doc_e2->min_col;
                        }
                        DocEntryDel(doc, doc_e);
                }
                if (doc_e == clear_entry)
                        break;
                doc_e = doc_e2;
        }
}

U0 DocBorderListDraw(CDoc *doc)
{
        CTask   *win_task = doc->win_task;
        I64              i, y = -1, attr = win_task->border_attr << 8;
        U64              ch;
        CDoc    *tmpl = doc;
        CD3I64   saved_scroll;

        while (tmpl && tmpl->doc_signature == DOC_SIGNATURE_VAL)
        {
                y += (Bsr(tmpl->desc) + 7) >> 3 + 1; //StrLen+1
                tmpl = tmpl->parent_doc;
        }
        tmpl = doc;
        if (y > win_task->win_height)
                y = win_task->win_height;
        WinScrollNull(win_task, &saved_scroll);
        while (tmpl && tmpl->doc_signature == DOC_SIGNATURE_VAL)
        {
                ch = tmpl->desc;
                i = (Bsr(ch) + 7) >> 3;         //StrLen
                ch = EndianU64(ch << ((8 - i) << 3));
                attr = win_task->border_attr << 8;
                while (i-- && y > 0)
                {
                        TextChar(win_task, TRUE, -1, --y, attr + ch & 0xFF);
                        ch >>= 8;
                }
                y--;
                tmpl = tmpl->parent_doc;
        }
        WinScrollRestore(win_task, &saved_scroll);
}

public U0 DocTop(CDoc *doc=NULL)
{//Move cursor, cur_entry, to top.
        Bool unlock;

        if (!doc && !(doc = DocPut))
                return;
        unlock = DocLock(doc);
        doc->cur_entry          = doc->head.next;
        doc->cur_col            = doc->cur_entry->min_col;
        doc->x                          = 0;
        doc->y                          = 0;
        doc->line_start_col     = 0;
        doc->top_line_num       = 0;

        DocFormFwd(doc);
        DocRecalc(doc);
        if (unlock)
                DocUnlock(doc);
}

public U0 DocCenter(CDoc *doc=NULL, I64 recalc_flags=RECALCt_NORMAL)
{//Center win on doc cursor, cur_entry.
        Bool   unlock;
        CTask *task;

        if (!doc && !(doc = DocPut))
                return;
        unlock = DocLock(doc);
        task = doc->win_task;
        DocRecalc(doc, recalc_flags);
        if (!(doc->flags & DOCF_BORDER_DOC))
                doc->top_line_num = doc->y - (task->win_height + 1) >> 1;
        if (unlock)
                DocUnlock(doc);
}

public U0 DocBottom(CDoc *doc=NULL)
{//Move cursor, cur_entry, to bottom.
        Bool unlock;

        if (!doc && !(doc = DocPut))
                return;
        unlock = DocLock(doc);
        doc->cur_entry  = doc;
        doc->cur_col    = 0;
        DocRecalc(doc);
        if (unlock)
                DocUnlock(doc);
}

public U0 DocClear(CDoc *doc=NULL, Bool clear_holds=FALSE)
{//Clear all doc entries, except +H, hold entries.
        Bool unlock;
        if (!doc && !(doc = DocPut))
                return;
        unlock = DocLock(doc);
        DocBottom(doc);
        if (clear_holds)
                DocPrint(doc, "$CL+H$");
        else
                DocPrint(doc, "$CL$");
        DocRecalc(doc);
        if (unlock)
                DocUnlock(doc);
}

public Bool DocCursor(Bool show=OFF, CDoc *doc=NULL)
{//Show or hide cursor.
        if (!doc && !(doc = DocPut))
                return FALSE;
        return !LBEqual(&doc->flags, DOCf_HIDE_CURSOR, !show);
}

public Bool DocHighlightCursor(Bool show=OFF, CDoc *doc=NULL)
{//Highlight or Don't highlight cursor.
        if (!doc && !(doc = DocPut))
                return FALSE;
        return !LBEqual(&doc->flags, DOCf_DONT_HIGHLIGHT_CURSOR, !show);
}

public Bool DocScroll(Bool val=OFF, CDoc *doc=NULL)
{//Turn scroll bars OFF/ON.
        if (!doc && !(doc = DocPut))
                return FALSE;
        return !LBEqual(&doc->flags, DOCf_NO_SCROLL_BARS, !val);
}

public U0 DocCollapse(Bool collapse=TRUE, CDoc *doc=NULL)
{//Collapse or uncollapse all tree widgets.
        CDocEntry       *doc_e;
        Bool             unlock;

        if (!doc && !(doc = DocPut))
                return;
        unlock = DocLock(doc);
        doc_e = doc->head.next;
        while (doc_e != doc)
        {
                if (doc_e->de_flags & DOCEF_TREE)
                        BEqual(&doc_e->de_flags, DOCEf_CHECKED_COLLAPSED, collapse);
                doc_e = doc_e->next;
        }
        DocRecalc(doc);
        if (unlock)
                DocUnlock(doc);
}

#help_index "DolDoc/Cmd Line (Typically);Cmd Line (Typically)"
public I64 DocMax(I64 i=I64_MAX)
{//Set max document entries. (Cmd line buffer size.)
//Adjusts the size of the cmd line buf.
        //Normally, the cmd line deletes entries
        //when more are added and the old scroll up.
        //See max_entries.
        I64   res;
        CDoc *doc;

        if (doc = DocPut)
        {
                res = doc->max_entries;
                doc->max_entries = i;
                return res;
        }
        else
                return 0;
}

#help_index "DolDoc/Task;StdOut/Task"
U0 DocUpdateTaskDocs(CTask *task)
{//This is called from GrUpdateTaskWin() by the winmgr at 60fps.
        CDoc *doc;
        CD3I64 saved_scroll;

        if (task->border_src == BDS_CUR_DRIVE && task->cur_dv)
                task->border_attr = DriveTextAttrGet(Drive2Letter(task->cur_dv));
        if (task->title_src == TTS_TASK_NAME)
                StrCopy(task->task_title, task->task_name);
        if ((doc = DocDisplay(task)) && !(doc->flags & DOCF_DONT_SHOW))
        {
                if (task->border_src == BDS_ED_FILENAME_DRIVE)
                        task->border_attr = DriveTextAttrGet(*doc->filename.name);
                if (task->title_src == TTS_ED_FILENAME)
                        MemCopy(task->task_title, doc->filename.name, STR_LEN - 1);
                DocRecalc(doc, RECALCt_TO_SCREEN | RECALCF_HAS_CURSOR);
        }
        if ((doc = DocBorder(task)) && !(doc->flags & DOCF_DONT_SHOW))
        {
                WinScrollNull(task, &saved_scroll);
                DocRecalc(doc, RECALCt_TO_SCREEN);
                WinScrollRestore(task, &saved_scroll);
        }
}