#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;
}