#help_index "DolDoc/Output;StdOut/DolDoc"
U0 DirFileDoc(CDoc *doc, CDirEntry *tmpde)
{
    while (tmpde)
    {
        if (tmpde->attr & RS_ATTR_DIR)
        {
            tmpde->user_data = DocPrint(doc, "$TR,\"%s\",U=0x%X$", tmpde->name, tmpde);
            DocPrint(doc, "\n$ID,+2$");
            if (tmpde->sub)
                DirFileDoc(doc, tmpde->sub);
            DocPrint(doc, "$ID,-2$");
        }
        else
        {
            tmpde->user_data = DocPrint(doc, "$MU,\"%s\",U=0x%X$", tmpde->name, tmpde);
            DocPrint(doc, "\n");
        }
        tmpde = tmpde->next;
    }
}

#help_index "File/Cmd Line (Typically);Cmd Line (Typically)"

#define FM_NORMAL           0
#define FM_PICK_FILE        1
#define FM_PICK_DIR         2

class CFMUncollapsedList
{
    CFMUncollapsedList  *next;
    U8                  *name;
};

CFMUncollapsedList *FMCollectUncollapsedList(CDoc *doc)
{
    CDocEntry           *doc_e = doc->head.next;
    CFMUncollapsedList  *res = NULL, *tmpc;
    CDirEntry           *tmpde;

    while (doc_e != doc)
    {
        if (doc_e->type_u8 == DOCT_TREE)
        {
            if (!(doc_e->de_flags & DOCEF_CHECKED_COLLAPSED))
            {
                if (tmpde = doc_e->user_data)
                {
                    tmpc = MAlloc(sizeof(CFMUncollapsedList));
                    tmpc->next = res;
                    res = tmpc;
                    tmpc->name = StrNew(tmpde->full_name);
                }
            }
        }
        doc_e = doc_e->next;
    }

    return res;
}

U0 FMMarkUncollapsed(CDoc *doc, CFMUncollapsedList *tmpc, U8 *cur_entry, U8 *next_entry)
{
    CDocEntry           *doc_e = doc->head.next;
    CFMUncollapsedList  *tmpc1;
    CDirEntry           *tmpde;

    while (doc_e != doc)
    {
        if (doc_e->type_u8 == DOCT_TREE)
        {
            tmpde = doc_e->user_data;
            tmpc1 = tmpc;
            while (tmpc1)
            {
                if (!StrCompare(tmpc1->name, tmpde->full_name))
                {
                    doc_e->de_flags &= ~DOCEF_CHECKED_COLLAPSED;
                    break;
                }
                tmpc1 = tmpc1->next;
            }
            if (cur_entry)
            {
                if (!StrNCompare(cur_entry, tmpde->full_name, StrLen(tmpde->full_name)))
                {
                    doc->cur_entry = doc_e;
                    if (StrLen(tmpde->full_name) == StrLen(cur_entry))
                        cur_entry = NULL;
                }
                else if (next_entry)
                {
                    if (!StrNCompare(next_entry, tmpde->full_name, StrLen(tmpde->full_name)))
                    {
                        doc->cur_entry = doc_e;
                        if (StrLen(tmpde->full_name) == StrLen(next_entry))
                            cur_entry = NULL;
                    }
                }
            }
        }
        else if (doc_e->type_u8 == DOCT_MENU_VAL)
        {
            tmpde = doc_e->user_data;
            if (cur_entry)
            {
                if (!StrNCompare(cur_entry, tmpde->full_name, StrLen(tmpde->full_name)))
                {
                    doc->cur_entry = doc_e;
                    if (StrLen(tmpde->full_name) == StrLen(cur_entry))
                        cur_entry = NULL;
                }
                else if (next_entry)
                {
                    if (!StrNCompare(next_entry, tmpde->full_name, StrLen(tmpde->full_name)))
                    {
                        doc->cur_entry = doc_e;
                        if (StrLen(tmpde->full_name) == StrLen(next_entry))
                            cur_entry = NULL;
                    }
                }
            }
        }
        doc_e = doc_e->next;
    }
}

U0 FMDelUncollapsedList(CFMUncollapsedList *tmpc)
{
    CFMUncollapsedList *tmpc1;

    while (tmpc)
    {
        tmpc1 = tmpc->next;
        Free(tmpc->name);
        Free(tmpc);
        tmpc = tmpc1;
    }
}

CDirEntry *FMRebuildDocDrive(U8 drv_let, CDoc *doc, CDirEntry **_head, Bool init)
{
    CDirEntry   *tmpde, *tmpde1;
    U8          *st;

    tmpde = CAlloc(sizeof(CDirEntry));
    tmpde->full_name = MStrPrint("%C:/", drv_let);
    tmpde->attr = RS_ATTR_DIR;
    st = MStrPrint("%c:/*", drv_let);
    if (init)
        tmpde->sub = tmpde1 = FilesFind(st, FUF_RECURSE);
    else
        tmpde1 = NULL;
    Free(st);
    tmpde->user_data = DocPrint(doc, "$TR,\"%s\",U=0x%X$", tmpde->full_name, tmpde);
    tmpde->next = *_head;
    *_head = tmpde;
    DocPrint(doc, "\n$ID,+2$");
    DocBottom(doc);
    if (init)
    {
        DirFileDoc(doc, tmpde1);
        while (tmpde1)
        {
            tmpde1->parent = tmpde;
            tmpde1 = tmpde1->next;
        }
    }
    DocPrint(doc, "$ID,-2$");

    return tmpde;
}

#define DEF2_PROCESSED                  1
#define DEF2_NOT_INITIALIZED        2

U0 FMRebuildDoc(CDoc **_doc, CDirEntry **_head, I64 mode)
{
    CDrive              *drive;
    I64                  i;
    CDoc                *doc = *_doc, *doc2 = sys_clip_doc, *parent_doc;
    CFMUncollapsedList  *tmpc = NULL;
    U8                  *cur_entry = NULL, *next_entry = NULL;
    CDocEntry           *doc_ce;
    CDirEntry           *tmpde, *tmpde1, *cur_tree_entry;

    if (!doc)
        parent_doc = DocPut;
    else
    {
        parent_doc = doc->parent_doc;
        Fs->put_doc = Fs->display_doc = NULL;
        DocUnlock(doc);
        Refresh;
        DocLock(doc);
        cur_tree_entry = NULL;
        doc_ce = doc->cur_entry;
        if (doc_ce->type_u8 == DOCT_TREE || doc_ce->type_u8 == DOCT_MENU_VAL)
            cur_tree_entry = doc_ce->user_data;
        if (cur_tree_entry)
            cur_entry = StrNew(cur_tree_entry->full_name);
        tmpde = NULL;
        if (doc_ce != doc)
            doc_ce = doc_ce->next;
        while (doc_ce != doc)
        {
            if (doc_ce->type_u8 == DOCT_TREE || doc_ce->type_u8 == DOCT_MENU_VAL)
                tmpde = doc_ce->user_data;
            else
                tmpde = NULL;
            if (tmpde)
            {
                tmpde1 = tmpde->parent;
                while (tmpde1)
                {
                    if (tmpde1 == cur_tree_entry)
                    {
                        tmpde = NULL;
                        break;
                    }
                    else
                        tmpde1 = tmpde1->parent;
                }
                if (tmpde)
                    break;
            }
            doc_ce = doc_ce->next;
        }
        if (tmpde)
            next_entry = StrNew(tmpde->full_name);

        tmpc = FMCollectUncollapsedList(doc);
        DocDel(doc);
    }
    if (*_head)
    {
        DirTreeDel(*_head);
        *_head = NULL;
    }
    doc = DocNew;
    doc->desc = 'FileMan';
    doc->parent_doc = parent_doc;
    doc->flags |= DOCF_FORM;
    switch (mode)
    {
        case FM_NORMAL:
            DocPrint(doc,"$PURPLE$File Manager\n\n"
                        "$LK,\"Click for Help\",A=\"FI:::/Doc/FileMgr.DD\"$\n\n");
            break;

        case FM_PICK_FILE:
            DocPrint(doc, "$PURPLE$Pick file and press <ESC>\n\n");
            doc->flags |= DOCF_SIZE_MIN;
            break;

        case FM_PICK_DIR:
            DocPrint(doc, "$PURPLE$Pick directory and press <ESC>\n\n");
            doc->flags |= DOCF_SIZE_MIN;
            break;
    }
    DocPrint(doc, "$LTBLUE$");
    for (i = 0; i < DRIVES_NUM; i++)
    {
        drive = &blkdev.drvs[i];
        if (drive->bd->type == BDT_ATAPI)
        {
            if (drive->bd->flags & BDF_INITIALIZED)
                tmpde = FMRebuildDocDrive(Drive2Letter(drive), doc, _head, TRUE);
            else
            {
                tmpde = FMRebuildDocDrive(Drive2Letter(drive), doc, _head, FALSE);
                tmpde->user_data2 |= DEF2_NOT_INITIALIZED;
            }
        }
        else if (drive->fs_type == FSt_REDSEA || drive->fs_type == FSt_FAT32)
            FMRebuildDocDrive(Drive2Letter(drive), doc, _head, TRUE);
    }
    DocTop(doc);
    FMMarkUncollapsed(doc, tmpc, cur_entry, next_entry);
    DocCenter(doc);
    DocReset(doc2, TRUE);
    FMDelUncollapsedList(tmpc);
    Free(cur_entry);
    Free(next_entry);
    *_doc = doc;
    DocLock(doc);
    Fs->put_doc = Fs->display_doc=doc;
}

U0 FMRename(CDoc *doc)
{
    CEdFileName  fn;
    CDocEntry   *doc_e = doc->cur_entry;
    CDirEntry   *tmpde = NULL, *parent;

    if (doc_e->type_u8 == DOCT_MENU_VAL)
    {
        tmpde = doc_e->user_data;
        if (parent = tmpde->parent)
        {
            Cd(parent->full_name);
            StrCopy(fn.name, tmpde->name);
            if (DocForm(&fn))
            {
                Silent;
                Move(tmpde->name, fn.name);
                Silent(OFF);
            }
        }
    }
    else if (doc_e->type_u8 == DOCT_TREE)
    {
        tmpde = doc_e->user_data;
        if (parent = tmpde->parent)
        {
            Cd(parent->full_name);
            StrCopy(fn.name, tmpde->name);
            if (DocForm(&fn))
            {
                if (StrCompare(tmpde->name, fn.name))
                {
                    Silent;
                    if (CopyTree(tmpde->name, fn.name))
                        DelTree(tmpde->name);
                    Silent(OFF);
                }
            }
        }
    }
}

U0 FMMkDir(CDoc *doc)
{
    CEdFileName  fn;
    CDocEntry   *doc_e = doc->cur_entry;
    CDirEntry   *tmpde = NULL, *parent;

    *fn.name = 0;
    if (doc_e->type_u8 == DOCT_MENU_VAL)
    {
        tmpde = doc_e->user_data;
        if (parent = tmpde->parent)
        {
            Cd(parent->full_name);
            if (DocForm(&fn))
            {
                Silent;
                DirMake(fn.name);
                Silent(OFF);
            }
        }
    }
    else if (doc_e->type_u8 == DOCT_TREE)
    {
        tmpde = doc_e->user_data;
        Cd(tmpde->full_name);
        if (DocForm(&fn))
        {
            Silent;
            DirMake(fn.name);
            Silent(OFF);
        }
    }
}

U0 FMDelete(CDoc *doc)
{
    U8          *st;
    CDocEntry   *doc_ce = doc->cur_entry;
    CDirEntry   *tmpde;

    if (doc_ce->type_u8 == DOCT_MENU_VAL)
    {
        tmpde = doc_ce->user_data;
        Silent;
        st = MStrPrint("Delete: %s", tmpde->full_name);
        if (PopUpCancelOk(st))
            Del(tmpde->full_name);
        Free(st);
        Silent(OFF);
    }
    else if (doc_ce->type_u8 == DOCT_TREE)
    {
        tmpde = doc_ce->user_data;
        Silent;
        st = MStrPrint("Delete: %s", tmpde->full_name);
        if (PopUpCancelOk(st))
            DelTree(tmpde->full_name);
        Free(st);
        Silent(OFF);
    }
}

U0 FMChangeDisk(CDoc *doc)
{
    CDocEntry *doc_ce = doc->cur_entry;
    CDirEntry *tmpde;

    if (doc_ce->type_u8 == DOCT_TREE || doc_ce->type_u8 == DOCT_MENU_VAL)
        tmpde = doc_ce->user_data;
    else
        tmpde = NULL;
    if (tmpde)
    {
        while (tmpde->parent)
            tmpde = tmpde->parent;
        Silent;
        DiskChange(*tmpde->full_name);
        Silent(OFF);
    }
}

U0 FMMountISO(CDoc *doc)
{
    CDocEntry *doc_ce = doc->cur_entry;
    CDirEntry *tmpde;

    if (doc_ce->type_u8 == DOCT_MENU_VAL && (tmpde = doc_ce->user_data))
        MountFile(tmpde->full_name);
}

U0 FMUnmount(CDoc *doc)
{
    CDocEntry   *doc_ce = doc->cur_entry;
    CDirEntry   *tmpde;
    I64          drv_let;

    if (doc_ce->type_u8 == DOCT_TREE || doc_ce->type_u8 == DOCT_MENU_VAL)
        tmpde = doc_ce->user_data;
    else
        tmpde = NULL;
    if (tmpde)
    {
        while (tmpde->parent)
            tmpde = tmpde->parent;
        drv_let = *tmpde->full_name;
        if (Letter2BlkDev(drv_let) != Letter2BlkDev(':'))
            Unmount(drv_let);
    }
}

U0 FMFormatDrive(CDoc *doc)
{
    CDocEntry *doc_ce = doc->cur_entry;
    CDirEntry *tmpde;

    U8 *st = NULL;
    if (doc_ce->type_u8 == DOCT_TREE || doc_ce->type_u8 == DOCT_MENU_VAL)
        tmpde = doc_ce->user_data;
    else
        tmpde = NULL;
    if (tmpde)
    {
        while (tmpde->parent)
            tmpde = tmpde->parent;
        st = MStrPrint("Format Drive '%c'?\nAre You Sure?\n", *tmpde->full_name);
        if (PopUpCancelOk(st))
        {
            Silent;
            Format(*tmpde->full_name,, FALSE);
            Silent(OFF);
        }
    }
    Free(st);
}

U0 FMMakeISO(CDoc *doc)
{
    CDocEntry *doc_ce = doc->cur_entry;
    CDirEntry *tmpde;

    if (doc_ce->type_u8 == DOCT_TREE || doc_ce->type_u8 == DOCT_MENU_VAL)
        tmpde = doc_ce->user_data;
    else
        tmpde = NULL;
    if (tmpde)
    {
        if (doc_ce->type_u8 == DOCT_MENU_VAL)
            tmpde = tmpde->parent;
        if (tmpde && *tmpde->full_name)
        {
            Silent;
            RedSeaISO(, tmpde->full_name);
            Silent(OFF);
        }
    }
}

U0 FMBurnISO(CDoc *doc)
{
    CDocEntry *doc_ce = doc->cur_entry;
    CDirEntry *tmpde;

    if (doc_ce->type_u8 == DOCT_TREE || doc_ce->type_u8 == DOCT_MENU_VAL)
        tmpde = doc_ce->user_data;
    else
        tmpde = NULL;
    if (tmpde)
    {
        while (tmpde->parent)
            tmpde = tmpde->parent;
        Silent;
        DVDImageWrite(*tmpde->full_name);
        Silent(OFF);
    }
}

U0 FMCopy(CDoc *doc)
{
    CDoc        *doc2 = sys_clip_doc;
    U8          *st;
    CDocEntry   *doc_ce = doc->cur_entry, *doc_e;
    CDirEntry   *tmpde, *tmpde1 = NULL, *tmpde2;
    Bool         unlock_doc2 = DocLock(doc2);

    doc_e = doc2->head.next;
    tmpde1 = doc_ce->user_data;
    if (doc_ce->type_u8 == DOCT_MENU_VAL)
        tmpde1 = tmpde1->parent;
    else if (doc_ce->type_u8 != DOCT_TREE)
        tmpde1 = NULL;
    if (tmpde1)
    {
        while (doc_e != doc2)
        {
            if (doc_e->type_u8 == DOCT_MENU_VAL)
            {
                tmpde = doc_e->user_data;
                tmpde->user_data2 |= DEF2_PROCESSED;
                tmpde2 = tmpde->parent;
                if (!tmpde2 || !(tmpde2->user_data2 & DEF2_PROCESSED))
                {
                    Silent;
                    Copy(tmpde->full_name, tmpde1->full_name);
                    Silent(OFF);
                }
            }
            else if (doc_e->type_u8 == DOCT_TREE)
            {
                tmpde = doc_e->user_data;
                tmpde->user_data2 |= DEF2_PROCESSED;
                tmpde2 = tmpde->parent;
                if (!tmpde2 || !(tmpde2->user_data2 & DEF2_PROCESSED))
                {
                    Silent;
                    if (*tmpde1->name)
                        st = MStrPrint("%s/%s", tmpde1->full_name, tmpde->name);
                    else
                        st = MStrPrint("%s%s", tmpde1->full_name, tmpde->name);
                    CopyTree(tmpde->full_name, st);
                    Free(st);
                    Silent(OFF);
                }
            }
            doc_e = doc_e->next;
        }
    }
    if (unlock_doc2)
        DocUnlock(doc2);
}

#define FMR_INCLUDE             0
#define FMR_SYSTEM_INCLUDE      1
#define FMR_DELETE              2
#define FMR_RENAME              3
#define FMR_MKDIR               4
#define FMR_PASTE               5
#define FMR_CHG_DISK            6
#define FMR_FORMAT              7
#define FMR_MOUNT_REDSEA_ISO_C  8
#define FMR_UNMOUNT             9
#define FMR_MAKE_REDSEA_ISO_C   10
#define FMR_BURN_ISO            11
#define FMR_HELP                12

I64 PopUpFMRight(U8 *header=NULL, U8 *footer=NULL)
{
    I64   i;
    CDoc *doc = DocNew;

    if (header)
        DocPrint(doc, "%s",header);

    DocPrint(doc,   "$CM+LX,1,1$$BT,\"INCLUDE                 \",LE=FMR_INCLUDE$"
                    "$CM+LX,29,0$$BT,\"SYSTEM INCLUDE          \",LE=FMR_SYSTEM_INCLUDE$"
                    "$CM+LX,1,3 $$BT,\"DELETE                  \",LE=FMR_DELETE$"
                    "$CM+LX,29,0$$BT,\"RENAME                  \",LE=FMR_RENAME$"
                    "$CM+LX,1,3 $$BT,\"MAKE DIRECTORY          \",LE=FMR_MKDIR$"
                    "$CM+LX,29,0$$BT,\"PASTE CLIP FILES        \",LE=FMR_PASTE$"
                    "$CM+LX,1,3 $$BT,\"CHANGE DISK(MOUNT IT)   \",LE=FMR_CHG_DISK$"
                    "$CM+LX,29,0$$BT,\"FORMAT                  \",LE=FMR_FORMAT$"
                    "$CM+LX,1,3 $$BT,\"MOUNT ISO.C FILE        \",LE=FMR_MOUNT_REDSEA_ISO_C$"
                    "$CM+LX,29,0$$BT,\"UNMOUNT                 \",LE=FMR_UNMOUNT$"
                    "$CM+LX,1,3 $$BT,\"MAKE ISO.C (CD/DVD) FILE\",LE=FMR_MAKE_REDSEA_ISO_C$"
                    "$CM+LX,29,0$$BT,\"BURN ISO (CD/DVD) FILE  \",LE=FMR_BURN_ISO$"
                    "$CM+LX,1,3 $$BT,\"HELP                    \",LE=FMR_HELP$"
                    "$CM+LX,29,0$$BT,\"CANCEL                  \",LE=DOCM_CANCEL$\n");

    if (footer)
        DocPrint(doc, "%s", footer);
    i = PopUpMenu(doc);
    DocDel(doc);

    return i;
}

U0 FMRightClick()
{
    switch (PopUpFMRight)
    {
        case FMR_INCLUDE:
            Message(MESSAGE_KEY_DOWN, 0, 0x3F0000003F);
            break;

        case FMR_SYSTEM_INCLUDE:
            Message(MESSAGE_KEY_DOWN, 0, 0x23F0000023F);
            break;

        case FMR_DELETE:
            Message(MESSAGE_KEY_DOWN, CH_CTRLY, 0);
            break;

        case FMR_RENAME:
            Message(MESSAGE_KEY_DOWN, 'r', 0);
            break;

        case FMR_MKDIR:
            Message(MESSAGE_KEY_DOWN, 'd', 0);
            break;

        case FMR_PASTE:
            Message(MESSAGE_KEY_DOWN, 0, SC_INS + SCF_SHIFT);
            break;

        case FMR_CHG_DISK:
            Message(MESSAGE_KEY_DOWN, 'c', 0);
            break;

        case FMR_FORMAT:
            Message(MESSAGE_KEY_DOWN, 'f', 0);
            break;

        case FMR_MOUNT_REDSEA_ISO_C:
            Message(MESSAGE_KEY_DOWN, 'i', 0);
            break;

        case FMR_UNMOUNT:
            Message(MESSAGE_KEY_DOWN, 'u', 0);
            break;

        case FMR_MAKE_REDSEA_ISO_C:
            Message(MESSAGE_KEY_DOWN, 'm', 0);
            break;

        case FMR_BURN_ISO:
            Message(MESSAGE_KEY_DOWN, 'B', 0);
            break;

        case FMR_HELP:
            Message(MESSAGE_KEY_DOWN, CH_CTRLM, 0x43200000432);
            break;
    }
}

U8 *fm_mouse_str = NULL;
U0 (*fp_old_final_screen_update)(CDC *dc);

U0 FMFinalScreenUpdate(CDC *dc)
{
    if (fm_mouse_str)
    {
        dc->color = LTRED;
        GrPrint(dc, mouse.pos.x, mouse.pos.y, "%s", fm_mouse_str);
    }
    (*fp_old_final_screen_update)(dc);
}

public U8 *FileMgr(I64 mode=FM_NORMAL, CTask *mem_task=NULL)
{//File manager. Also, used to choose files and dirs.
    CDirEntry   *head = NULL, *tmpde, *tmpde1, *tmpde2;
    I64          sc, ch, arg1, arg2, message_code;
    CDoc        *doc = NULL, *old_put_doc = DocPut, *old_display_doc = DocDisplay;
    U8          *res = NULL, *st, *st2, *old_cur_dir = DirCur;
    CDocEntry   *doc_ce = NULL, *doc_e;
    Bool         okay;

    SettingsPush; //See SettingsPush
    fp_old_final_screen_update = gr.fp_final_screen_update;
    MenuFilePush("::/Doc/FileMgrPullDown.DD");
    FMRebuildDoc(&doc, &head, mode);
    if (tmpde1 = Cd2DirEntry(head, old_cur_dir))
        doc->cur_entry = tmpde1->user_data;
    while (tmpde1)
    {
        if (tmpde1->attr & RS_ATTR_DIR)
            tmpde1->user_data(CDocEntry *)->de_flags &= ~DOCEF_CHECKED_COLLAPSED;
        tmpde1 = tmpde1->parent;
    }
    do
    {
        DocUnlock(doc);

        do message_code = MessageGet(&arg1, &arg2,
                            1 << MESSAGE_KEY_DOWN | 1 << MESSAGE_MS_L_DOWN | 1 << MESSAGE_MS_L_UP | 1 << MESSAGE_MS_R_UP);
        while (Fs != sys_focus_task);

        DocLock(doc);
        switch (message_code)
        {
            case MESSAGE_MS_R_UP:
                DocUnlock(doc);
                FMRightClick;
                DocLock(doc);
                break;

            case MESSAGE_MS_L_DOWN:
                doc_ce = doc->cur_entry;
                fm_mouse_str = doc_ce->tag;
                gr.fp_final_screen_update = &FMFinalScreenUpdate;
                break;

            case MESSAGE_MS_L_UP:
                if (doc_ce)
                {
                    gr.fp_final_screen_update = fp_old_final_screen_update;
                    if (WinCursorPosSet(Fs, arg1 + Fs->pix_left + Fs->scroll_x, arg2 + Fs->pix_top + Fs->scroll_y, TRUE))
                    {
                        doc_e = doc->cur_entry;
                        if (doc_e != doc_ce)
                        {
                            st2 = NULL;
                            if (doc_e->type_u8 == DOCT_MENU_VAL)
                            {
                                tmpde1 = doc_e->user_data;
                                if (tmpde1 = tmpde1->parent)
                                    st2 = StrNew(tmpde1->full_name);
                            }
                            else if (doc_e->type_u8 == DOCT_TREE)
                            {
                                tmpde1 = doc_e->user_data;
                                st2 = StrNew(tmpde1->full_name);
                            }
                            if (st2 && doc_ce->type_u8 == DOCT_MENU_VAL)
                            {
                                tmpde = doc_ce->user_data;
                                Silent;
                                Move(tmpde->full_name, st2);
                                Silent(OFF);
                                FMRebuildDoc(&doc, &head, mode);
                            }
                            else if (st2 && doc_ce->type_u8 == DOCT_TREE)
                            {
                                tmpde = doc_ce->user_data;
                                okay = TRUE;
                                tmpde2 = tmpde1;
                                while (tmpde2)
                                {
                                    if (tmpde2 != tmpde)
                                        tmpde2 = tmpde2->parent;
                                    else
                                    {
                                        okay = FALSE;
                                        break;
                                    }
                                }
                                if (okay)
                                {
                                    if (*tmpde1->name)
                                        st = MStrPrint("%s/%s", tmpde1->full_name, tmpde->name);
                                    else
                                        st = MStrPrint("%s%s", tmpde1->full_name, tmpde->name);
                                    if (StrCompare(tmpde->full_name, st))
                                    {
                                        Silent;
                                        CopyTree(tmpde->full_name, st);
                                        DelTree(tmpde->full_name);
                                        Silent(OFF);
                                        FMRebuildDoc(&doc, &head, mode);
                                    }
                                    Free(st);
                                }
                            }
                            Free(st2);
                            FlushMessages;
                        }
                        else
                            if (doc_e->type_u8 == DOCT_MENU_VAL)
                            {
                                DocUnlock(doc);
                                Ed(doc_e->user_data(CDirEntry *)->full_name);
                                DocLock(doc);
                            }
                        doc_ce = NULL;
                    }
                }
                break;

            case MESSAGE_KEY_DOWN:
                doc_ce = NULL;
                ch = arg1;
                sc = arg2;
                if (sc.u8[0] == SC_DELETE && !(sc & (SCF_SHIFT | SCF_CTRL)))
                    ch = CH_CTRLY;
                if (ch && sc & SCF_ALT)
                    goto fm_regular_key;
                switch (ch)
                {
                    case '\n':
                        DocUnlock(doc);
                        FMRightClick;
                        DocLock(doc);
                        break;
                    start:
                        DocUnlock(doc);
                        case CH_CTRLV:
                            FMCopy(doc);
                            break;

                        case 'r':
                            FMRename(doc);
                            break;

                        case 'd':
                            FMMkDir(doc);
                            break;

                        case CH_CTRLY:
                            FMDelete(doc);
                            break;

                        case 'c':
                            FMChangeDisk(doc);
                            break;

                        case 'i':
                            FMMountISO(doc);
                            break;

                        case 'u':
                            FMUnmount(doc);
                            break;

                        case 'm':
                            FMMakeISO(doc);
                            break;

                        case 'B':
                            FMBurnISO(doc);
                            break;

                        case 'f':
                            FMFormatDrive(doc);
                            break;
                    end:
                        FMRebuildDoc(&doc, &head, mode);
                        break;

                    case CH_SHIFT_ESC:
                        break;

                    case CH_SPACE:
                        if (doc->cur_entry->type_u8 == DOCT_MENU_VAL)
                        {
                            DocUnlock(doc);
                            Ed(doc->cur_entry->user_data(CDirEntry *)->full_name);
                            DocLock(doc);
                        }
                        else
                            goto fm_regular_key;
                        break;

                    case CH_ESC:
                        doc_ce = doc->cur_entry;
                        tmpde = doc_ce->user_data;
                        if (mode == FM_PICK_FILE && doc_ce->type_u8 == DOCT_MENU_VAL)
                            res = StrNew(tmpde->full_name, mem_task);
                        else if (mode == FM_PICK_DIR)
                        {
                            if (doc_ce->type_u8 == DOCT_TREE)
                                res = StrNew(tmpde->full_name, mem_task);
                            else if (doc_ce->type_u8 == DOCT_MENU_VAL && (tmpde = tmpde->parent))
                                res = StrNew(tmpde->full_name, mem_task);
                        }
                        break;

                    default:
                        if (sc.u8[0] == SC_INS && sc & SCF_SHIFT && !(sc & SCF_CTRL))
                        {
                            FMCopy(doc);
                            FMRebuildDoc(&doc, &head, mode);
                        }
                        else if (sc.u8[0] == SC_F5)
                        {
                            if (doc->cur_entry->type_u8 == DOCT_MENU_VAL)
                            {
                                tmpde = doc->cur_entry->user_data;
                                DocUnlock(doc);
                                if (sc & SCF_SHIFT)
                                    SysFile(tmpde->full_name);
                                else
                                    PopUpFile(tmpde->full_name);
                                DocLock(doc);
                            }
                        }
                        else
                        {
fm_regular_key:
                            DocUnlock(doc);
                            PutKey(ch, sc);
                            DocLock(doc);
                        }
                }
                break;
        }
    }
    while (ch != CH_ESC && ch != CH_SHIFT_ESC);

    gr.fp_final_screen_update = fp_old_final_screen_update;
    Fs->put_doc = old_put_doc;
    Fs->display_doc = old_display_doc;
    SettingsPop;
    DocDel(doc);
    DirTreeDel(head);
    Cd(old_cur_dir);
    Free(old_cur_dir);
    if (mode != FM_NORMAL && !res)
        res = StrNew("", mem_task);
    MenuPop;

    return res;
}