#help_index "DolDoc/Clip"

sys_clip_doc = DocNew;

public U0 ClipDel()
{//Delete everything on clip.
    DocReset(sys_clip_doc, TRUE);
}

public U0 ClipCopy(CDoc *doc)
{//Copy DOCET_SEL flagged entries to clip.
    CDoc        *doc2 = sys_clip_doc;
    Bool         unlock_doc = DocLock(doc), unlock_doc2 = DocLock(doc2);
    CDocEntry   *doc_e = doc->head.next, *doc_ne;

    ClipDel;
    while (doc_e != doc)
    {
        if (doc_e->type & DOCET_SEL)
        {
            doc_e->type &= ~DOCET_SEL;
            if (!Bt(doldoc.type_flags_data, doc_e->type_u8))
            {
                doc_ne = DocEntryCopy(doc2, doc_e);
                QueueInsert(doc_ne, doc2->head.last);
            }
        }
        doc_e = doc_e->next;
    }
    if (unlock_doc2)
        DocUnlock(doc2);
    if (unlock_doc)
        DocUnlock(doc);
}

public U0 ClipCut(CDoc *doc)
{//Remove sel entries and place on clip.
    CDoc        *doc2 = sys_clip_doc;
    Bool         unlock_doc = DocLock(doc), unlock_doc2 = DocLock(doc2);
    CDocEntry   *doc_e = doc->head.next, *doc_e1, *doc_ne, *doc_e2 = NULL;

    ClipDel;
    while (doc_e != doc)
    {
        doc_e1 = doc_e->next;
        if (doc_e->type & DOCET_SEL)
        {
            doc_e->type &= ~DOCET_SEL;
            if (!Bt(doldoc.type_flags_data, doc_e->type_u8))
            {
                doc_ne = DocEntryCopy(doc2, doc_e);
                QueueInsert(doc_ne, doc2->head.last);
            }
            if (doc_e == doc->cur_entry || doc_e == doc_e2)
                doc_e2 = doc_e->next;
            DocEntryDel(doc, doc_e);
        }
        doc_e = doc_e1;
    }
    if (doc_e2)
    {
        doc->cur_entry  = doc_e2;
        doc->cur_col    = doc_e2->min_col;
    }
    DocRemSoftNewLines(doc, NULL);
    if (unlock_doc2)
        DocUnlock(doc2);
    if (unlock_doc)
        DocUnlock(doc);
}

public U0 ClipPaste(CDoc *doc)
{//Insert copy of clip at insert pt,  cur_entry.
    CDoc        *doc2 = sys_clip_doc;
    Bool         unlock_doc = DocLock(doc), unlock_doc2 = DocLock(doc2);
    CDocEntry   *doc_ce = doc->cur_entry, *doc_e;

    if (doc_ce->type_u8 == DOCT_DATA)
    {
        doc_e = doc2->head.next;
        while (doc_e != doc2)
        {
            if (doc_e->de_flags & DOCEF_TAG)
                DocPrintPartial(doc, "%s", doc_e->tag);
            doc_e = doc_e->next;
        }
    }
    else
        DocInsDoc(doc, doc2);
    if (unlock_doc2)
        DocUnlock(doc2);
    if (unlock_doc)
        DocUnlock(doc);
}

public U0 DocCut(CDoc *doc, CDocEntry *start, CDocEntry *end)
{//Del start to end entry,  including end points.
    Bool         unlock_doc = DocLock(doc);
    CDocEntry   *doc_e1;

    if (start != doc && (start->last != end || end == doc))
        do
        {
            doc_e1 = start->next;
            if (start == doc->cur_entry)
            {
                doc->cur_entry  = start->next;
                doc->cur_col    = doc->cur_entry->min_col;
            }
            DocEntryDel(doc, start);
            if (start == end)
                break;
            start = doc_e1;
        }
        while (start != doc);

    DocRemSoftNewLines(doc, NULL);
    if (unlock_doc)
        DocUnlock(doc);
}

public CDoc *DocCopy(CDoc *doc, CDocEntry *start, CDocEntry *end)
{//Copies start to end entry,  including end points.
    CDoc        *doc2 = DocNew;
    Bool         unlock_doc = DocLock(doc);
    CDocEntry   *doc_ne;

    if (start != doc && (start->last != end || end == doc))
        do
        {
            if (!Bt(doldoc.type_flags_data, start->type_u8))
            {
                doc_ne = DocEntryCopy(doc2, start);
                QueueInsert(doc_ne, doc2->head.last);
            }
            if (start == end)
                break;
            start = start->next;
        }
        while (start != doc);

    if (unlock_doc)
        DocUnlock(doc);
    return doc2;
}