/*

Directory Opus 4
Original GPL release version 4.12
Copyright 1993-2000 Jonathan Potter

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

All users of Directory Opus 4 (including versions distributed
under the GPL) are entitled to upgrade to the latest version of
Directory Opus version 5 at a reduced price. Please see
http://www.gpsoft.com.au for more information.

The release of Directory Opus 4 under the GPL in NO WAY affects
the existing commercial status of Directory Opus 5.

*/

#include "dopus.h"
#include <proto/inovamusic.h>
#include "view.h"

dofilefunction(function,flags,sourcedir,destdir,act,inact,rexx)
int function,flags;
char *sourcedir,*destdir;
int act,inact,rexx;
{
    int askeach=0,a,b,special=0,candoicon=1,old,specflags,noshow=0,err;
    int sourcewild=0,destwild=0,firstset=0,breakout,rexarg,protstuff[2];
    int pt=1,okayflag,show,lastfile,flag,exist,byte,count,data,mask=0,temp;
    int globflag,noremove,doicons=0,total,value=0,progtype,blocksize,retval=0;
    ULONG class;
    USHORT code;
    struct Directory *file,*tempfile,*nextfile,filebuf,dummyfile;
    char *sourcename,*destname,*oldiconname,*newiconname;
    char *buf,*buf1,*buf2,*namebuf,*srename,*drename,*ptr,*database;
    static char tbuf[256],titlebuf[32];
    struct DOpusDateTime datetime;
    struct DOpusRemember *funckey;
    struct dopusfiletype *type;
    struct dopusfuncpar par;
    struct DirectoryWindow *swindow,*dwindow;
    struct InfoData __aligned infodata;
    struct FileInfoBlock __aligned fileinfo;
    struct DOpusArgsList arglist;
    struct ViewData *viewdata=NULL;
    BPTR filelock;
    static int entry_depth;
    char progress_copy=0,prog_indicator=0;

    if (act>-1) swindow=dopus_curwin[act];
    else swindow=NULL;
    if (inact>-1) dwindow=dopus_curwin[inact];
    else dwindow=NULL;

    data=rexarg=0; funckey=NULL;
    specflags=flags&~255; flags&=255;

    if (config->iconflags&ICONFLAG_DOUNTOICONS || func_external_file[0]) doicons=1;

    switch (function) {
        case FUNC_PLAYST:
            if (!MUSICBase) return(0);
        case FUNC_PLAY:
        case FUNC_LOOPPLAY:
            if (MUSICBase) FlushModule();
            break;
    }

    /* Find the first file to work upon; if only one file specified,
     use that */

    if (status_flags&STATUS_GLOBALFILE)                     /* kludge */
        flags=FUNCFLAGS_FILES;

    total=-1;

    if (func_single_entry) {
        file=func_single_entry;
        globflag=1;
    }
    else if (swindow) {
        globflag=0;
        if (flags&FUNCFLAGS_DIRS) {
            file=checkdirtot(swindow);                             /* First dir */
            total=swindow->dirsel;
            progtype=1;
        }
        if (flags&FUNCFLAGS_DEVS && !file) {
            file=checkdevtot(swindow);                             /*    or dev */
            total=swindow->dirsel;
            progtype=1;
        }
        if (flags&FUNCFLAGS_FILES) {
            file=checktot(swindow);                                /* First file */
            total=swindow->filesel;
            progtype=0;
        }
        if (flags==0 || flags&FUNCFLAGS_ANYTHING) {
            file=checkalltot(swindow);
            total=swindow->filesel+swindow->dirsel;                /* Anything   */
            progtype=2;
        }
        if (!file && flags&FUNCFLAGS_ANYTHING) {
            file=checkdevtot(swindow);
            total=swindow->dirsel;
            progtype=1;
        }

      /* Name may be in ARexx */

        if (rexx && (tempfile=findfile(swindow,rexx_args[0],NULL))) {
            ++rexarg;
            file=tempfile;
            func_single_entry=file;
            strcpy(func_single_file,file->name);
            globflag=1;
        }
    }

    if (!file) return(0);            /* No files selected, return */

    if (!(database=LAllocRemember(&funckey,3000,MEMF_CLEAR))) return(0);
    sourcename=database; destname=database+300;
    oldiconname=database+600; newiconname=database+900;
    buf=database+1200; buf1=database+1500; buf2=database+1800;
    namebuf=database+2100; srename=database+2400; drename=database+2700;

    if (swindow) scrdata_old_offset_store=swindow->offset; /* Store directory offset for auto-scroll */
    else scrdata_old_offset_store=-1;

    status_justabort=count=0; namebuf[0]=0;

    /* Bump entry depth to check for recursion */

    ++entry_depth;

    /* Do initial setting up functions */

    switch (function) {
        case FUNC_READ:
        case FUNC_HEXREAD:
        case FUNC_ANSIREAD:
        case FUNC_SMARTREAD:
            if (!globflag &&
                !(viewdata=LAllocRemember(&funckey,sizeof(struct ViewData),MEMF_CLEAR)))
                goto endfunction;
        case FUNC_LOOPPLAY:
        case FUNC_SHOW:
            total=-1;
        case FUNC_PLAY:
            candoicon=0;
            break;
        case FUNC_DELETE:
            askeach=1;
            if (config->deleteflags&DELETE_ASK && !globflag) {
                /* Ask for confirmation before commencing delete */
                displaydirgiven(act,file,0);
                if (!(a=simplerequest(globstring[STR_REALLY_DELETE],
                    globstring[STR_DELETE],str_cancelstring,globstring[STR_ALL],NULL))) {
                    endfollow(act);
                    myabort();
                    goto endfunction;
                }
                if (a==2) askeach=0;
            }
            glob_unprotect_all=0;
            break;
        case FUNC_RENAME:
            if (rexx) {
                if (rexx_argcount<2) goto endfunction;
                strcpy(srename,rexx_args[0]);
                strcpy(drename,rexx_args[1]);
                if (strchr(srename,'*')) sourcewild=1;
                if (strchr(drename,'*')) destwild=1;
                else {
                    strcpy(namebuf,drename);
                    firstset=1;
                }
            }
            else while (file) {
                if (file->selected) {
                    strcpy(srename,file->name); strcpy(drename,file->name);
                    displaydirgiven(act,file,0);
                    if (!(a=getrenamedata(srename,drename)) ||
                        !srename[0] || !drename[0]) {
                        endfollow(act);
                        myabort();
                        goto endfunction;
                    }
                    if (a==1) {
                        if (strchr(srename,'*')) sourcewild=1;
                        if (strchr(drename,'*')) destwild=1;
                        else {
                            strcpy(namebuf,drename);
                            firstset=1;
                            total=-1;
                        }
                        break;
                    }
                }
                ++value;
                file=file->next;
            }
            if (!file) {
                endfollow(act);
                goto endfunction;
            }
            askeach=1;
            break;
        case FUNC_MOVE:
            if (destdir[0] && !(checksame(sourcedir,destdir,1))) goto endfunction;
        case FUNC_MOVEAS:
            if (!(checkdest(inact))) goto endfunction;
            if (!(config->existflags&REPLACE_ALWAYS)) askeach=1;
            progress_copy=1;
            break;
        case FUNC_COPY:
            if (destdir[0] && !(checksame(sourcedir,destdir,1))) goto endfunction;
        case FUNC_COPYAS:
            if (!(checkdest(inact))) goto endfunction;
            if (!(config->existflags&REPLACE_ALWAYS)) askeach=1;
            progress_copy=1;
            if (!(specflags&FUNCFLAGS_COPYISCLONE) && config->copyflags&COPY_CHECK) {
                old=scrdata_old_offset_store;
                if (!globflag) {
                    a=0;
                    tempfile=file;
                    while (tempfile) {
                        if (tempfile->selected && tempfile->type>=ENTRY_DIRECTORY &&
                            tempfile->size==-1) {
                            a=1;
                            break;
                        }
                        tempfile=tempfile->next;
                    }
                    if (!a || simplerequest(globstring[STR_SIZES_NOT_KNOWN],
                        globstring[STR_YES],globstring[STR_NO],NULL)) {
                        if (status_justabort ||
                            (!(dofilefunction(FUNC_BYTE,FUNCFLAGS_BYTEISCHECKFIT,
                                sourcedir,destdir,act,inact,0)) &&
                            !(simplerequest(globstring[STR_ENTRIES_MAY_NOT_FIT],
                            globstring[STR_CONTINUE],str_cancelstring,NULL)))) {
                            myabort();
                            goto endfunction;
                        }
                    }
                }
                scrdata_old_offset_store=old;
            }
            break;
        case FUNC_HUNT:
            if (rexx && rexx_argcount>0) strcpy(str_hunt_name,rexx_args[rexarg]);
            else if (!(whatsit(globstring[STR_ENTER_HUNT_PATTERN],80,str_hunt_name,NULL)) ||
                !str_hunt_name[0]) {
                myabort();
                goto endfunction;
            }
            LParsePatternI(str_hunt_name,str_hunt_name_parsed);
            CopyMem(str_hunt_name_parsed,buf2,170);
            candoicon=0;
            break;
        case FUNC_PRINT:
            if (globflag) {
                StrCombine(sourcename,sourcedir,file->name,256);
                arglist.single_file=sourcename;
                arglist.file_list=NULL;
                arglist.last_select=NULL;
            }
            else {
                arglist.single_file=NULL;
                arglist.file_window=act;
                arglist.file_list=(APTR)file;
            }
            dopus_print(rexx,&arglist,0,str_arexx_portname,NULL);
            goto endfunction;
            break;
        case FUNC_COMMENT:
            candoicon=0;
        case FUNC_DATESTAMP:
        case FUNC_PROTECT:
            askeach=1;
            break;
        case FUNC_ENCRYPT:
            if (!(checkdest(inact)) || !(checksame(sourcedir,destdir,1)))
                goto endfunction;
            if (!(config->existflags&REPLACE_ALWAYS)) askeach=1;
            if (rexx && rexx_argcount>0) strcpy(buf2,rexx_args[rexarg]);
            else if (!(whatsit(globstring[STR_ENTER_PASSWORD],20,buf2,NULL)) ||
                !buf2[0]) {
                myabort();
                goto endfunction;
            }
            if (buf2[0]=='-') {
                data=0;
                strcpy(buf2,&buf2[1]);
            }
            else data=1;
            candoicon=0;
            progress_copy=1;
            break;
        case FUNC_SEARCH:
            if (rexx && rexx_argcount>0) strcpy(str_search_string,rexx_args[rexarg]);
            else {
                if (!(get_search_data(str_search_string,&search_flags,Window,scr_font[FONT_REQUEST]))) {
                    myabort();
                    goto endfunction;
                }
            }
            candoicon=0;
            askeach=1;
            break;
        case FUNC_RUN:
            candoicon=0;
            break;
        case FUNC_ADDICON:
            askeach=1;
            candoicon=0;
            break;
        case FUNC_ICONINFO:
            candoicon=0;
            total=-1;
            break;
        case FUNC_AUTO:
        case FUNC_AUTO2:
        case FUNC_AUTO3:
        case FUNC_AUTO4:
            dostatustext(globstring[STR_INTERROGATING_FILES]);
            candoicon=0;
            total=-1;
            break;
        case FUNC_BYTE:
            candoicon=0;
            special=2;
            count=1;
            main_proc->pr_WindowPtr=(APTR)-1;
            if (filelock=Lock(destdir,ACCESS_READ)) {
                Info(filelock,&infodata);
                UnLock(filelock);
                blocksize=infodata.id_BytesPerBlock;
            }
            else blocksize=512;
            if (config->errorflags&ERROR_ENABLE_DOS) main_proc->pr_WindowPtr=(APTR)Window;
            total=-1;
            break;
    }

    if (!(config->dynamicflags&UPDATE_PROGRESSIND_COPY)) progress_copy=0;

    endnotifies();

    if (config->dynamicflags&UPDATE_PROGRESSINDICATOR &&
        (progress_copy || total>1)) {
        char *title=NULL;
        int x;

        for (x=0;;x++) {
            if (!commandlist[x].name) break;
            if (commandlist[x].function==function &&
                !(commandlist[x].flags&RCL_SYNONYM)) {
                title=commandlist[x].name;
                break;
            }
        }

        if (title) StrCombine(titlebuf,title,"...",32);
        else strcpy(titlebuf,"Directory Opus");

        if (total>1) dotaskmsg(hotkeymsg_port,PROGRESS_OPEN,value,total,titlebuf,progress_copy);
        else dotaskmsg(hotkeymsg_port,PROGRESS_OPEN,1,1,titlebuf,progress_copy);
        prog_indicator=1;
    }

    while (file) {
        if (status_haveaborted) {
            myabort();
            break;
        }
        nextfile=file->next;

        if (!file->selected && !globflag) {
            file=nextfile;
            continue;
        }

        if (doicons && candoicon && !(isicon(file->name))) {
            StrCombine(oldiconname,file->name,".info",256);
            StrCombine(buf1,sourcedir,oldiconname,256);
            if (!(CheckExist(buf1,NULL))) oldiconname[0]=0;
        }
        else oldiconname[0]=0;

        if (prog_indicator) {
            if (progtype==1 && file->type>=ENTRY_DEVICE) ++value;
            else if (progtype==0 && file->type<=ENTRY_FILE) ++value;
            else if (progtype==2) ++value;
            if (total>1) dotaskmsg(hotkeymsg_port,PROGRESS_UPDATE,value,total,NULL,0);
            else dotaskmsg(hotkeymsg_port,PROGRESS_UPDATE,1,1,NULL,0);
            if (progress_copy) dotaskmsg(hotkeymsg_port,PROGRESS_UPDATE,-2,0,file->name,1);
        }

        lastfile=flag=breakout=0;

functionloop:
        StrCombine(sourcename,sourcedir,file->name,256);
        if (!special || count==0 ||
            (special==2 && file->type>=0)) {
            dofilename(sourcename);
            displaydirgiven(act,file,0);
        }
        if (!firstset && !lastfile && !namebuf[0]) strcpy(namebuf,file->name);
        else if (lastfile) strcpy(namebuf,BaseName(newiconname));
        okayflag=a=0; show=-1;

        if (func_external_file[0] || file==&dummyfile) noremove=1;
        else noremove=0;

        switch (function) {
            case FUNC_AUTO:
            case FUNC_AUTO2:
            case FUNC_AUTO3:
            case FUNC_AUTO4:
                if (function==FUNC_AUTO) a=FTFUNC_AUTOFUNC1;
                else if (function==FUNC_AUTO2) a=FTFUNC_AUTOFUNC2;
                else if (function==FUNC_AUTO3) a=FTFUNC_AUTOFUNC3;
                else if (function==FUNC_AUTO4) a=FTFUNC_AUTOFUNC4;
                okayflag=1;
                if (file->type<=ENTRY_FILE) {
                    if ((type=checkfiletype(sourcename,a,0))) {
                        char title[256];

                        par.which=type->which[a]; par.stack=type->stack[a];
                        par.key=par.qual=0;
                        par.pri=type->pri[a]; par.delay=type->delay[a];
                        status_previousabort=0;
                        if (status_iconified && status_flags&STATUS_ISINBUTTONS)
                            strcpy(func_external_file,sourcename);
                        if (type->actionstring[a][0]) {
                            do_title_string(type->actionstring[a],title,0,file->name);
                            dostatustext(title);
                        }
                        else title[0]=0;
                        dofunctionstring(type->function[a],file->name,title,&par);
                        if (status_previousabort) status_haveaborted=1;
                    }
                    else {
                        lsprintf(buf,globstring[STR_NOT_IDENTIFIED],file->name);
                        dostatustext(buf);
                    }
                }
                break;

            case FUNC_BYTE:
                if (file->type>=ENTRY_DIRECTORY &&
                    (file->size<0 || (specflags&FUNCFLAGS_BYTEISCHECKFIT &&
                    (file->userdata==0 || file->userdata2!=blocksize)))) {
                    if ((a=recursedir(sourcename,NULL,R_GETBYTES,blocksize))==-10) {
                        myabort();
                        break;
                    }
                    file->userdata=dos_global_blocksneeded;
                    file->userdata2=blocksize;
                    setdirsize(file,dos_global_bytecount,act);
                    refreshwindow(act,0);
                }
                if (file->type>=ENTRY_DIRECTORY) data+=file->userdata+1;
                else {
                    a=(file->size+(blocksize-1))/blocksize;
                    data+=a+(a/72)+1;
                }
                if (doicons && !(isicon(file->name))) {
                    StrCombine(oldiconname,file->name,".info",256);
                    b=-1;
                    if (file=findfile(swindow,oldiconname,NULL)) {
                        if (!file->selected) b=file->size;
                    }
                    else {
                        StrCombine(tbuf,sourcedir,oldiconname,256);
                        if (lockandexamine(tbuf,&fileinfo)) b=fileinfo.fib_Size;
                    }
                    if (b>-1) {
                        a=(b+(blocksize-1))/blocksize;
                        data+=a+(a/72)+1;
                    }
                    oldiconname[0]=0;
                }
                file=NULL;
                okayflag=1;
                break;

            case FUNC_RUN:
                if (file->type<=ENTRY_FILE) {
                    if (checkexec(sourcename)) {
                        if ((a=dorun(sourcename,1,0))==-1) break;
                        else if (a && a!=-2) okayflag=1;
                    }
                    else if (file->protection&FIBF_SCRIPT) {
                        struct dopusfuncpar par;

                        lsprintf(buf,"Execute \"%s\"",sourcename);
                        defaultpar(&par);
                        dofunctionstring(buf,NULL,NULL,&par);
                        okayflag=1;
                    }
                }
                break;

            case FUNC_DELETE:
                if (file->type>=ENTRY_DIRECTORY) {
                    if ((a=delfile(sourcename,file->name,globstring[STR_DELETING],
                        glob_unprotect_all,0))==-1) {
                        myabort();
                        break;
                    }
                    else if (a>0) {
                        if (a==2) glob_unprotect_all=1;
                        if (!noremove) removefile(file,swindow,act,1); file=NULL;
                        okayflag=1;
                    }
/*
                    if (DeleteFile(sourcename)) {
                        if (!noremove) removefile(file,swindow,act,1); file=NULL;
                        okayflag=1;
                    }
*/
                    else if (a<0) {
                        if ((a=IoErr())==ERROR_DELETE_PROTECTED &&
                            config->deleteflags&DELETE_SET) {
                            if (!flag) {
                                flag=1;
                                SetProtection(sourcename,0);
                                goto functionloop;
                            }
                        }
                        else if (a==ERROR_OBJECT_NOT_FOUND) {
                            if (!noremove) removefile(file,swindow,act,1);
                            file=NULL;
                            okayflag=1;
                        }
                        else if (a==ERROR_DIRECTORY_NOT_EMPTY) {
                            if (config->deleteflags&DELETE_DIRS && askeach) {
                                lsprintf(buf2,globstring[STR_NOT_EMPTY],file->name);
                                if (!(a=simplerequest(buf2,globstring[STR_DELETE],
                                    globstring[STR_LEAVE],globstring[STR_ALL],globstring[STR_ABORT],NULL))) {
                                    okayflag=1;
                                    break;
                                }
                                if (a==2) askeach=0;
                                else if (a==3) {
                                    myabort();
                                    break;
                                }
                            }
                            TackOn(sourcename,NULL,256);
                            a=recursedir(sourcename,NULL,R_DELETE,0);
                            sourcename[strlen(sourcename)-1]=0;
                            if (!a) {
                                if ((a=delfile(sourcename,file->name,globstring[STR_DELETING],
                                    glob_unprotect_all,1))==-1) {
                                    myabort();
                                    break;
                                }
                                else if (a==1 || a==2) {
                                    if (a==2) glob_unprotect_all=1;
                                    if (!noremove) removefile(file,swindow,act,1); file=NULL;
                                    okayflag=1;
                                }
                                else {
                                    setdirsize(file,dos_global_bytecount-dos_global_deletedbytes,act);
                                    okayflag=1;
                                }
                            }
                            else {
                                setdirsize(file,file->size-dos_global_deletedbytes,act);
                                refreshwindow(act,0);
                            }
                        }
                        else {
                            doerror((a=IoErr()));
                            if ((a=checkerror(globstring[STR_DELETING],file->name,a))==3) {
                                myabort();
                                break;
                            }
                            if (a==1) goto functionloop;
                        }
                    }
                    show=act;
                    break;
                }
                if (config->deleteflags&DELETE_FILES && askeach && !lastfile) {
                    lsprintf(buf2,globstring[STR_WISH_TO_DELETE],file->name);
                    if (!(a=simplerequest(buf2,globstring[STR_DELETE],globstring[STR_LEAVE],
                        globstring[STR_ALL],globstring[STR_ABORT],NULL))) {
                        okayflag=1;
                        break;
                    }
                    if (a==2) askeach=0;
                    else if (a==3) {
                        myabort();
                        break;
                    }
                }
                if ((a=delfile(sourcename,file->name,globstring[STR_DELETING],
                    glob_unprotect_all,1))==-1) {
                    myabort();
                    break;
                }
                else if (a) {
                    if (a==2) glob_unprotect_all=1;
                    if (!noremove) removefile(file,swindow,act,1); file=NULL;
                    show=act;
                    okayflag=1;
                }
                break;

            case FUNC_RENAME:
                if (firstset || lastfile) a=1;
                else if (!destwild) {
                    if (!(a=whatsit(globstring[STR_ENTER_NEW_NAME],FILEBUF_SIZE-2,namebuf,
                        globstring[STR_SKIP]))) {
                        myabort();
                        break;
                    }
                    if (a==2) {
                        file=NULL;
                        okayflag=1;
                        oldiconname[0]=0;
                        break;
                    }
                }
                else if (!sourcewild) a=getwildrename("*",drename,file->name,namebuf);
                else if (sourcewild) a=getwildrename(srename,drename,file->name,namebuf);
                firstset=0;
                if (a) {
                    if (lastfile) StrCombine(destname,sourcedir,newiconname,256);
                    else {
/*                        if (doicons && oldiconname[0]) namebuf[FILEBUF_SIZE-7]=0;
                        else namebuf[FILEBUF_SIZE-2]=0; */ namebuf[FILEBUF_SIZE-1]=0;
                        StrCombine(destname,sourcedir,namebuf,256);
                        StrCombine(newiconname,namebuf,".info",256);
                    }
                    if (!(Rename(sourcename,destname))) {
                        if ((a=IoErr())==ERROR_OBJECT_EXISTS) {
                            if (askeach) {
                                if (!lastfile) {
                                    if (!(a=checkexistreplace(sourcename,destname,&file->date,destwild,1)))
                                        break;
                                    if (a==2) {
                                        if (!destwild) goto functionloop;
                                        askeach=0;
                                    }
                                    else if (a==3) {
                                        myabort();
                                        break;
                                    }
                                }
                            }
                            if ((a=delfile(destname,namebuf,globstring[STR_DELETING],1,1))==-2) {
                                if (!(a=recursedir(destname,NULL,R_DELETE,0))) a=1;
                                else if (a==-10) a=-1;
                            }
                            if (a==-1) {
                                myabort();
                                break;
                            }
                            if (a) {
                                if ((tempfile=findfile(swindow,namebuf,NULL))) {
                                    if (tempfile==nextfile) nextfile=tempfile->next;
                                    removefile(tempfile,swindow,act,1);
                                }
                                firstset=1;
                                goto functionloop;
                            }
                        }
                        doerror(a);
                        if ((a=checkerror(globstring[STR_RENAMING],file->name,a))==3) {
                            myabort();
                            break;
                        }
                        if (a==1) goto functionloop;
                    }
                    else {
                        if (file->type>=ENTRY_DIRECTORY) {
                            StrCombine(buf,sourcedir,file->name,256); TackOn(buf,NULL,256);
                            StrCombine(buf1,sourcedir,namebuf,256); TackOn(buf1,NULL,256);
                            renamebuffers(buf,buf1);
                        }
                        if (!noremove){
                            if (act>-1 && config->sortmethod[act]==DISPLAY_NAME) {
                                CopyMem((char *)file,(char *)&filebuf,sizeof(struct Directory));
                                if (file->comment) strcpy(buf2,file->comment);
                                else buf2[0]=0;
                                removefile(file,swindow,act,0); file=NULL;
                                addfile(swindow,act,namebuf,filebuf.size,filebuf.type,&filebuf.date,
                                    buf2,filebuf.protection,filebuf.subtype,1,NULL,NULL,
                                    filebuf.owner_id,filebuf.group_id);
                            }
                            else strcpy(file->name,namebuf);
                            if (lastfile) refreshwindow(act,0);
                        }
                        okayflag=1;
                    }
                }
                else okayflag=1;
                break;

            case FUNC_MOVEAS:
                if (!lastfile && !flag) {
                    if (rexx && rexx_argcount>1) strcpy(namebuf,rexx_args[1]);
                    else {
                        if (!(a=whatsit(globstring[STR_ENTER_NEW_NAME_MOVE],FILEBUF_SIZE-2,
                            namebuf,globstring[STR_SKIP]))) {
                            myabort();
                            break;
                        }
                        if (a==2) {
                            file=NULL;
                            okayflag=1;
                            oldiconname[0]=0;
                            break;
                        }
                    }
/*                    if (doicons && oldiconname[0]) namebuf[FILEBUF_SIZE-7]=0;
                    else namebuf[FILEBUF_SIZE-2]=0; */ namebuf[FILEBUF_SIZE-1]=0;
                }
            case FUNC_MOVE:
                if (lastfile) strcpy(destname,newiconname);
                else {
                    StrCombine(destname,destdir,namebuf,256);
                    StrCombine(newiconname,destname,".info",256);
                }
                if (!(checksame(destdir,sourcename,0))) break;
                if ((exist=CheckExist(destname,NULL))) {
                    if (askeach) {
                        if ((a=checkexistreplace(sourcename,destname,&file->date,(function==FUNC_MOVE),1))==3) {
                            myabort();
                            break;
                        }
                        if (!a) break;
                        if (a==2) {
                            if (function==FUNC_MOVEAS) goto functionloop;
                            askeach=0;
                        }
                    }
                    if ((a=delfile(destname,namebuf,globstring[STR_MOVING],1,1))==-1) {
                        myabort();
                        break;
                    }
                    if (!a) {
                        doerror(ERROR_OBJECT_EXISTS);
                        break;
                    }
                    if (a && (tempfile=findfile(dwindow,namebuf,NULL)))
                        removefile(tempfile,dwindow,inact,0);
                }
                if (!(Rename(sourcename,destname))) {
                    if ((exist<0 || file->type<=ENTRY_FILE) &&
                        (a=IoErr())!=ERROR_RENAME_ACROSS_DEVICES) {
                        doerror(a);
                        if ((a=checkerror(globstring[STR_MOVING],file->name,a))==3) {
                            myabort();
                            break;
                        }
                        if (a==1) goto functionloop;
                    }
                    else {
                        if (file->type>=ENTRY_DIRECTORY) {
                            a=recursedir(sourcename,destname,R_COPY|R_DELETE,0);
                            if (a==0) {
                                if (!func_external_file[0])
                                    setdirsize(file,dos_global_bytecount-dos_global_deletedbytes,act);
                            }
                            else if (status_justabort || a<0) {
                                if (a!=-10) {
                                    if ((a=checkerror(globstring[STR_MOVING],file->name,IoErr()))==3)
                                        a=-10;
                                    else if (a==1) goto functionloop;
                                }
                                if (!func_external_file[0]) {
                                    setdirsize(file,file->size-dos_global_deletedbytes,act);
                                    refreshwindow(act,0);
                                }
                                if (CheckExist(destname,NULL)) {
                                    if (exist) {
                                        if (tempfile=findfile(dwindow,namebuf,NULL))
                                            removefile(tempfile,dwindow,inact,0);
                                    }
                                    addfile(dwindow,inact,namebuf,dos_global_copiedbytes,
                                        file->type,&file->date,file->comment,
                                        file->protection,file->subtype,1,NULL,NULL,
                                        file->owner_id,file->group_id);
                                }
                                if (a==-10) myabort();
                                else status_justabort=0;
                                break;
                            }
                            if (!(tempfile=findfile(dwindow,namebuf,NULL))) {
                                addfile(dwindow,inact,namebuf,exist?-1:dos_global_copiedbytes,file->type,
                                    &file->date,file->comment,file->protection,
                                    file->subtype,1,NULL,NULL,file->owner_id,file->group_id);
                            }
                            else {
                                setdirsize(tempfile,exist?-1:dos_global_copiedbytes,act);
                                refreshwindow(inact,0);
                            }
                            if ((a=delfile(sourcename,file->name,globstring[STR_DELETING],1,1))==-1) {
                                myabort();
                                break;
                            }
                            if (a==1) {
                                if (!noremove) removefile(file,swindow,act,1);
                                file=NULL;
                            }
                            okayflag=1;
                        }
                        else {
                            if (!(a=copyfile(sourcename,destname,&err,-1,NULL,0))) {
                                doerror(err);
                                if ((a=checkerror(globstring[STR_MOVING],file->name,err))==3) {
                                    myabort();
                                    break;
                                }
                                if (a==1) goto functionloop;
                            }
                            else if (a==-1) {
                                myabort();
                                break;
                            }
                            else if (lockandexamine(destname,&fileinfo)) {
                                addfile(dwindow,inact,
                                    fileinfo.fib_FileName,
                                    fileinfo.fib_Size,
                                    fileinfo.fib_DirEntryType,
                                    &fileinfo.fib_Date,
                                    fileinfo.fib_Comment,
                                    fileinfo.fib_Protection,
                                    file->subtype,1,NULL,NULL,
                                    fileinfo.fib_OwnerUID,fileinfo.fib_OwnerGID);
                                if ((a=delfile(sourcename,file->name,globstring[STR_DELETING],1,1))==-2) {
                                    if (!(a=recursedir(sourcename,NULL,R_DELETE,0))) a=1;
                                    else if (a==-10) {
                                        myabort();
                                        break;
                                    }
                                }
                                if (a==-1) {
                                    myabort();
                                    break;
                                }
                                if (a) {
                                    if (!noremove) removefile(file,swindow,act,1); file=NULL;
                                }
                                else oldiconname[0]=0;
                                okayflag=1;
                            }
                        }
                        show=act;
                        seename(inact);
                    }
                }
                else {
                    if (progress_copy) dotaskmsg(hotkeymsg_port,PROGRESS_UPDATE,100,100,file->name,1);
                    addfile(dwindow,inact,namebuf,file->size,file->type,&file->date,
                        file->comment,file->protection,file->subtype,1,NULL,NULL,
                        file->owner_id,file->group_id);
                    if (!noremove) removefile(file,swindow,act,1); file=NULL;
                    okayflag=1;
                }
                break;

            case FUNC_COPYAS:  /* If flag is set then won't ask for new name */
                if (!lastfile && !flag) {
                    if (rexx && rexx_argcount>1) strcpy(namebuf,rexx_args[1]);
                    else {
                        if (!(a=whatsit(globstring[STR_ENTER_NEW_NAME],FILEBUF_SIZE-2,namebuf,
                            globstring[STR_SKIP]))) {
                            myabort();
                            break;
                        }
                        if (a==2) {
                            okayflag=1;
                            file=NULL;
                            oldiconname[0]=0;
                            break;
                        }
                        if (LStrCmpI(sourcedir,destdir)==0 && LStrCmpI(namebuf,file->name)==0) {
                            okayflag=1; oldiconname[0]=0;
                            break;
                        }
                    }
/*                    if (doicons && oldiconname[0]) namebuf[FILEBUF_SIZE-7]=0;
                    else namebuf[FILEBUF_SIZE-2]=0; */ namebuf[FILEBUF_SIZE-1]=0;
                }
            case FUNC_COPY:
                if (lastfile) strcpy(destname,newiconname);
                else {
                    StrCombine(destname,destdir,namebuf,256);
                    StrCombine(newiconname,destname,".info",256);
                }
                if (!(checksame(destdir,sourcename,0))) break;
                if ((exist=CheckExist(destname,NULL)) && askeach) {
                    if ((a=checkexistreplace(sourcename,destname,&file->date,
                        (function==FUNC_COPY),1))==3) {
                        myabort();
                        break;
                    }
                    if (!a) break;
                    if (a==2) {
                        if (function==FUNC_COPYAS) goto functionloop;
                        askeach=0;
                    }
                }
                if (exist<0) {
                    if ((a=delfile(destname,file->name,globstring[STR_COPYING],1,1))==-1) {
                        myabort();
                        break;
                    }
                    if (!a) {
                        doerror(ERROR_OBJECT_EXISTS);
                        break;
                    }
                    if (a==1 && (tempfile=findfile(dwindow,namebuf,NULL))) {
                        if (!noremove) removefile(tempfile,dwindow,inact,(tempfile->type!=file->type));
                        exist=0;
                    }
                }
                if (file->type>=ENTRY_DIRECTORY) {
                    a=recursedir(sourcename,destname,R_COPY,0);
                    if (exist) {
                        byte=-1;
                        exist=0;
                    }
                    else byte=dos_global_copiedbytes;
                    if (config->copyflags&COPY_DATE) setdate(destname,&file->date);

                    if (!a && !func_external_file[0]) {
                        setdirsize(file,dos_global_bytecount,act);
                        refreshwindow(act,0);
                        filloutcopydata(file);
                    }
                    else if (a==-1 || a==-10) {
                        if (a==-1) {
                            if ((a=checkerror(globstring[STR_COPYING],file->name,IoErr()))==1)
                                goto functionloop;
                            if (a==3) a=-10; 
                        }
                        if (CheckExist(destname,NULL)) {
                            if (exist && (tempfile=findfile(dwindow,namebuf,NULL)))
                                removefile(tempfile,dwindow,inact,0);
                            addfile(dwindow,inact,namebuf,byte,file->type,&file->date,
                                file->comment,file->protection,file->subtype,1,NULL,NULL,
                                file->owner_id,file->group_id);
                        }
                        if (a==-10) myabort();
                        show=inact;
                        break;
                    }
                    else if (a<0) break;
                }
                else {
                    if (!(a=copyfile(sourcename,destname,&err,-1,NULL,0))) {
                        doerror(err);
                        if ((a=checkerror(globstring[STR_COPYING],file->name,err))==3) {
                            myabort();
                            break;
                        }
                        if (a==1) goto functionloop;
                        break;
                    }
                    else if (a==-1) {
                        myabort();
                        break;
                    }
                    byte=file->size;
                }
                if (exist && (tempfile=findfile(dwindow,namebuf,NULL)))
                    removefile(tempfile,dwindow,inact,0);
                if (lockandexamine(destname,&fileinfo)) {
                    if (fileinfo.fib_DirEntryType<0) byte=fileinfo.fib_Size;
                    addfile(dwindow,inact,
                        fileinfo.fib_FileName,
                        byte,
                        fileinfo.fib_DirEntryType,
                        &fileinfo.fib_Date,
                        fileinfo.fib_Comment,
                        fileinfo.fib_Protection,
                        file->subtype,1,NULL,NULL,
                        fileinfo.fib_OwnerUID,fileinfo.fib_OwnerGID);
                    if (config->copyflags&COPY_ARC && !(file->protection&FIBF_ARCHIVE)) {
                        if (SetProtection(sourcename,file->protection|FIBF_ARCHIVE)) {
                            file->protection|=FIBF_ARCHIVE;
                            getprot(file->protection,file->protbuf);
                        }
                    }   
                }
                okayflag=1;
                show=inact;
                break;

            case FUNC_HUNT:
                if (file->type<=ENTRY_FILE) {
                    okayflag=1;
                    break;
                }
                if ((a=recursedir(sourcename,NULL,R_HUNT,0))==-3) {
                    wildselect(buf2,2,0);
                    findfirstsel(act,-2);
                    okayflag=breakout=noshow=1; count=-1;
                    break;
                }
                if (a>-1) {
                    okayflag=1;
                    if (a==0 && !func_external_file[0]) setdirsize(file,dos_global_bytecount,act);
                    if (a>0) count+=a;
                }
                else count=-1;
                break;

            case FUNC_READ:
            case FUNC_HEXREAD:
            case FUNC_ANSIREAD:
            case FUNC_SMARTREAD:
                if (file->type>=ENTRY_DEVICE) {
                    okayflag=1;
                    break;
                }
                if ((a=viewfile(sourcename,file->name,function,NULL,
                    viewdata,(viewdata)?1:0,(entry_depth>1)))!=-2) {
                    if (a!=-3) ++count;
                    else if (count==0) unselect(act,file);
                    if (file->selected) {
                        file->selected=0;
                        if (swindow) {
                            --swindow->filesel; swindow->bytessel-=file->size;
                        }
                    }
                    SetBusyPointer(Window);
                    if (a==-1) status_justabort=1;
                    else okayflag=1;
                }
                else {
                    if (!count && !(doerror(IoErr()))) okayflag=1;
                }
                break;

            case FUNC_SHOW:
                if (file->type>=ENTRY_DEVICE || file->size<1) {
                    okayflag=1;
                    file=NULL;
                    break;
                }
                if (entry_depth<2 &&
                    checkfiletypefunc(sourcename,FTFUNC_SHOW)) okayflag=1;
                else {
                    if (data==0) {
                        if (swindow && swindow->filesel>1 && config->viewbits&VIEWBITS_SHOWBLACK) {
                            if (blankscreen=OpenScreen((struct NewScreen *)&blank_scr))
                                SetRGB4(&blankscreen->ViewPort,0,0,0,0);
                            setnullpointer(Window);
                            pt=0;
                        }
                        data=1;
                    }
                    if ((a=showpic(sourcename,pt))==-1) {
                        okayflag=1;
                        myabort();
                        break;
                    }
                    else {
                        if (a==1) okayflag=1;
                        else file=NULL;
                    }
                }
                break;

            case FUNC_ICONINFO:
                if (LStrCmpI(file->name,".info")==0) okayflag=1;
                else {
                    if ((ptr=isicon(sourcename))) *ptr=0;
                    switch ((a=dopus_iconinfo(sourcename))) {
                        case -1:
                            myabort();
                            file=NULL;
                            break;
                        case -2:
                            dostatustext(globstring[STR_CANT_FIND_ICON]);
                            file=NULL;
                            break;
                        case -3:
                            dostatustext(globstring[STR_NO_CHIP_FOR_ICON]);
                            file=NULL;
                            break;
                        case -4:
                            file=NULL;
                            status_justabort=1;
                            break;
                        case 1:
                            if (act>-1) {
                                StrCombine(buf,sourcename,".info",256);
                                if (isicon(file->name)) {
                                    reload_file(act,sourcename);
                                    file=reload_file(act,buf);
                                }
                                else {
                                    file=reload_file(act,sourcename);
                                    reload_file(act,buf);
                                }
                            }
                        default:
                            okayflag=1;
                            show=act;
                            break;
                    }
                }
                break;

            case FUNC_PLAYST:
                a=1;    
            case FUNC_PLAY:
            case FUNC_LOOPPLAY:
                if (file->type>=ENTRY_DEVICE || file->size<1) {
                    okayflag=1;
                    file=NULL;
                    break;
                }
                if (entry_depth<2 &&
                    checkfiletypefunc(sourcename,(function==FUNC_PLAY)?FTFUNC_PLAY:FTFUNC_LOOPPLAY))
                    okayflag=1;
                else if (a || check_is_module(sourcename)) {
                    if ((a=playmod(sourcename)) && swindow && swindow->filesel>1) {
                        a=-1;
                        FOREVER {
                            Wait(1<<Window->UserPort->mp_SigBit);
                            while (getintuimsg()) {
                                class=IMsg->Class; code=IMsg->Code;
                                ReplyMsg((struct Message *)IMsg);
                                if (class==MOUSEBUTTONS) {
                                    a=(code==SELECTDOWN);
                                    break;
                                }
                            }
                            if (a!=-1) break;
                        }
                        FlushModule();
                        if (!a) myabort();
                        else okayflag=1;
                    }
                    else if (a) okayflag=1;
                    else file=NULL;
                }
                else {
                    a=doplay8svx(sourcename,(function==FUNC_LOOPPLAY));
                    kill8svx();
                    if (a==-1) {
                        myabort();
                        break;
                    }
                    else {
                        if (a==1) okayflag=1;
                        else {
                            handle8svxerror(a);
                            file=NULL;
                        }
                    }
                }
                break;

            case FUNC_ADDICON:
                if (strlen(file->name)>(FILEBUF_SIZE-6) || isicon(file->name)) {
                    okayflag=1;
                    file=NULL;
                    break;
                }
                StrCombine(buf2,file->name,".info",FILEBUF_SIZE-1);
                StrCombine(destname,sourcename,".info",256);
                if ((a=CheckExist(sourcename,NULL))==0) {
                    doerror((a=IoErr()));
                    if ((a=checkerror(globstring[STR_ADDING_ICON],file->name,a))==1)
                        goto functionloop;
                    if (a==3) {
                        myabort();
                        break;
                    }
                    file=NULL;
                    break;
                }
                if (a>0) data=ICONTYPE_DRAWER;
                else if (checkexec(sourcename)) data=ICONTYPE_TOOL;
                else data=ICONTYPE_PROJECT;
                if (CheckExist(destname,NULL) && askeach) {
                    doerror(ERROR_OBJECT_EXISTS);
                    if (!(a=checkexistreplace(destname,destname,NULL,1,1))) {
                        file=NULL;
                        break;
                    }
                    else if (a==2) askeach=0;
                    else if (a==3) {
                        myabort();
                        break;
                    }
                }
                if ((iconwrite(data,destname))!=-1) {
                    if (lockandexamine(destname,&fileinfo)) {
                        addfile(swindow,act,buf2,fileinfo.fib_Size,-1,&fileinfo.fib_Date,
                            fileinfo.fib_Comment,fileinfo.fib_Protection,0,1,NULL,NULL,
                            fileinfo.fib_OwnerUID,fileinfo.fib_OwnerGID);
                        show=act;
                        okayflag=1;
                    }
                }
                else {
                    myabort();
                    break;
                }
                break;

            case FUNC_COMMENT:
                if (askeach) {
                    if (rexx && rexx_argcount>0) strcpy(buf2,rexx_args[rexarg]);
                    else {
                        if (file->comment) strcpy(buf2,file->comment);
                        else buf2[0]=0;
                        if (!(a=whatsit(globstring[STR_ENTER_COMMENT],79,buf2,
                            globstring[STR_ALL]))) {
                            myabort();
                            break;
                        }
                        if (a==2) askeach=0;
                    }
                }
                FOREVER {
                    if (SetComment(sourcename,buf2)) break;
                    doerror((a=IoErr()));
                    if ((a=checkerror(globstring[STR_COMMENTING],file->name,a))==3) {
                        myabort();
                        break;
                    }
                    if (a!=1) {
                        file=NULL;
                        break;
                    }
                }
                if (status_justabort || !file) break;
                okayflag=1;
                if (file->type>=ENTRY_DIRECTORY) {
                    if ((a=recursedir(sourcename,buf2,R_COMMENT,0))>0 && status_justabort)
                        status_justabort=okayflag=0;
                    else if (!a && !func_external_file[0]) setdirsize(file,dos_global_bytecount,act);
                }
                if (!noremove && file->comment!=dos_copy_comment) {
                    if (act>-1 && config->sortmethod[act]==DISPLAY_COMMENT) {
                        CopyMem((char *)file,(char *)&filebuf,sizeof(struct Directory));
                        removefile(file,swindow,act,0); file=NULL;
                        addfile(swindow,act,namebuf,filebuf.size,filebuf.type,&filebuf.date,
                            buf2,filebuf.protection,filebuf.subtype,1,NULL,NULL,
                            filebuf.owner_id,filebuf.group_id);
                    }
                    else {
                        if (file->comment)
                            LibFreePooled(dir_memory_pool,file->comment,strlen(file->comment)+1);
                        if (file->comment=LibAllocPooled(dir_memory_pool,strlen(buf2)+1))
                            strcpy(file->comment,buf2);
                    }
                }
                break;

            case FUNC_PROTECT:
                if (askeach && !lastfile) {
                    if (rexx) {
                        data=rexx_arg_value[0];
                        mask=rexx_arg_value[1];
                    }
                    else {
                        data=file->protection;
                        if (!(a=getprotectdata(&data,&mask))) {
                            myabort();
                            break;
                        }
                        if (a==2) askeach=0;
                    }
                }
                temp=getnewprot(file->protection,data,mask);
                FOREVER {
                    if (SetProtection(sourcename,temp)) break;
                    doerror((a=IoErr()));
                    if ((a=checkerror(globstring[STR_PROTECTING],file->name,a))==3) {
                        myabort();
                        break;
                    }
                    if (a!=1) {
                        file=NULL;
                        break;
                    }
                }
                if (status_justabort || !file) break;
                file->protection=temp;
                getprot(temp,file->protbuf);
                if (file->type>=ENTRY_DIRECTORY) {
                    protstuff[0]=data; protstuff[1]=mask;
                    if ((a=recursedir(sourcename,NULL,R_PROTECT,(int)protstuff)) &&
                        status_justabort) break;
                    if (!a && !func_external_file[0]) setdirsize(file,dos_global_bytecount,act);
                }
                if (!file->selected) refreshwindow(act,0);
                okayflag=1;
                break;

            case FUNC_ENCRYPT:
                if (file->type>=ENTRY_DEVICE || file->size<1) {
                    okayflag=1;
                    file=NULL;
                    break;
                }
                StrCombine(destname,destdir,file->name,256);
                if (CheckExist(destname,NULL)) {
                    if (askeach) {
                        if ((a=checkexistreplace(sourcename,destname,&file->date,1,1))) {
                            if (a==2) askeach=0;
                            else if (a==3) {
                                myabort();  
                                break;
                            }
                        }
                        else {
                            file=NULL;
                            break;
                        }
                    }
                    if ((a=delfile(destname,file->name,globstring[STR_DATESTAMPING],1,1))==-1) {
                        myabort();
                        break;
                    }
                }
                if (!CheckExist(destname,NULL)) {
                    FOREVER {
                        if (copyfile(sourcename,destname,&err,-1,buf2,data)) {
                            addfile(dwindow,inact,file->name,file->size,file->type,&file->date,
                                file->comment,file->protection,file->subtype,1,NULL,NULL,
                                file->owner_id,file->group_id);
                            okayflag=1; show=inact;
                            break;
                        }
                        doerror(err);
                        if ((a=checkerror(globstring[STR_ENCRYPTING],file->name,err))==3) {
                            myabort();
                            break;
                        }
                        if (a!=1) {
                            file=NULL;
                            break;
                        }
                    }
                }
                else doerror(ERROR_OBJECT_EXISTS);
                break;

            case FUNC_DATESTAMP:
                if (askeach && !lastfile) {
                    if (rexx && rexx_argcount>0) strcpy(buf2,rexx_args[rexarg]);
                    else {
                        buf2[0]=0;
                        if (!(a=whatsit(globstring[STR_ENTER_DATE_AND_TIME],20,buf2,
                            globstring[STR_ALL]))) {
                            myabort();
                            break;
                        }
                        if (a==2) askeach=0;
                    }
                    if (buf2[0]) {
                        parsedatetime(buf2,buf,buf1,&a);
                        strtostamp(buf,buf1,&datetime.dat_Stamp);
                    }
                    else DateStamp(&datetime.dat_Stamp);
                }
                FOREVER {
                    if ((a=setdate(sourcename,&datetime.dat_Stamp))==1) {
                        if (!noremove) {
                            if (act>-1 && config->sortmethod[act]==DISPLAY_DATE) {
                                CopyMem((char *)file,(char *)&filebuf,sizeof(struct Directory));
                                if (file->comment) {
                                    strcpy(buf2,file->comment);
                                    filebuf.comment=buf2;
                                }
                                removefile(file,swindow,act,0);
                                file=(struct Directory *)addfile(swindow,act,filebuf.name,filebuf.size,
                                    filebuf.type,&datetime.dat_Stamp,filebuf.comment,filebuf.protection,
                                    filebuf.subtype,1,NULL,NULL,filebuf.owner_id,filebuf.group_id);
                            }
                            else {
                                file->date.ds_Days=datetime.dat_Stamp.ds_Days;
                                file->date.ds_Minute=datetime.dat_Stamp.ds_Minute;
                                file->date.ds_Tick=datetime.dat_Stamp.ds_Tick;
                                seedate(&file->date,file->datebuf,1);
                            }
                        }
                        break;
                    }
                    doerror(a);
                    if ((a=checkerror(globstring[STR_DATESTAMPING],file->name,a))==3) {
                        myabort();
                        break;
                    }
                    if (a!=1) {
                        file=NULL;
                        break;
                    }
                }
                if (status_justabort || !file) break;
                if (file->type>=ENTRY_DIRECTORY) {
                    if (!(recursedir(sourcename,NULL,R_DATESTAMP,(int)&datetime.dat_Stamp))) {
                        okayflag=1;
                        if (!func_external_file[0]) setdirsize(file,dos_global_bytecount,act);
                    }
                }
                else okayflag=1;
                break;

            case FUNC_SEARCH:
                if (file->type==ENTRY_DEVICE) {
                    if ((a=recursedir(file->name,NULL,R_SEARCH,0))==-2) {
                        okayflag=1;
                        count=-1; nextfile=NULL;
                        break;
                    }
                    if (a==-1) {
                        nextfile=NULL;
                        break;
                    }
                    if (a==-10) {
                        myabort();
                        break;
                    }
                    if (a>0) count+=a;
                    okayflag=1;
                }
                else {
                    if (file->type<=ENTRY_FILE) {
                        a=filesearch(sourcename,&b,(askeach)?1:-1);
                        count+=b;
                        if (a==2) {
                            okayflag=1; file=NULL;
                            busy();
                            if (act>-1) {
                                if (swindow) {
                                    if (count>0) b=(swindow->filesel-count)+swindow->dirsel;
                                    else b=swindow->filesel+swindow->dirsel;
                                    if (!b) nextfile=NULL;
                                }
                            }
                            if (nextfile && !simplerequest(globstring[STR_CONTINUE_WITH_SEARCH],
                                globstring[STR_CONTINUE],str_cancelstring,NULL))
                                nextfile=NULL;
                        }
                        if (a==-1) {
                            myabort();  
                            break;
                        }
                        if (a) {
                            okayflag=1;
                            if (a==3) file=NULL;
                            else if (a==4) {
                                file=NULL;
                                askeach=0;
                            }
                        }
                        else doerror(IoErr());
                    }
                    else {
                        if (!(a=recursedir(sourcename,NULL,R_SEARCH,0))) {
                            if (!func_external_file[0]) setdirsize(file,dos_global_bytecount,act);
                            okayflag=1;
                        }
                        if (a==-2) {
                            okayflag=1; breakout=2;
                            count=-1; nextfile=NULL;
                            break;
                        }
                        if (a==-1 || a==-10) {
                            if (a==-10) {
                                myabort();
                                file=NULL;
                            }
                            else nextfile=NULL;
                            break;
                        }
                        if (a>0) count+=a;
                    }
                }
                break;
        }

        if (config->dynamicflags&UPDATE_FREE && show>-1) seename(show);
        if (breakout==1) break;
        if (file && okayflag) {
            if (file->selected) unselect(act,file);
            else refreshwindow(act,0);
        }
        if (status_justabort || breakout==2) break;

        if (doicons && !lastfile && okayflag && oldiconname[0]) {
            if (file=findfile(swindow,oldiconname,NULL)) {
                if (file==nextfile) nextfile=file->next;
                lastfile=1;
                if (file->selected && prog_indicator) {
                    if (progtype==0 || progtype==2) {
                        ++value;
                        dotaskmsg(hotkeymsg_port,PROGRESS_UPDATE,value,total,NULL,0);
                    }
                }
                if (progress_copy) dotaskmsg(hotkeymsg_port,PROGRESS_UPDATE,-2,0,file->name,1);
                goto functionloop;
            }
            else {
                StrCombine(sourcename,sourcedir,oldiconname,256);
                if (filloutdummy(sourcename,&dummyfile)) {
                    dummyfile.selected=0;
                    file=&dummyfile;
                    lastfile=1;
                    goto functionloop;
                }
            }
        }

        if (globflag) break;
        if (!lastfile && file && file->next && file->next!=nextfile) file=file->next;
        else file=nextfile;
        namebuf[0]=0;
    }

    if (prog_indicator) {
        dotaskmsg(hotkeymsg_port,PROGRESS_UPDATE,-1,status_justabort,NULL,0);
        if (progress_copy) dotaskmsg(hotkeymsg_port,PROGRESS_UPDATE,-1,status_justabort,NULL,1);
    }

    switch (function) {
        case FUNC_HUNT:
            if (count==0) {
                okayflag=0;
                doerror(ERROR_OBJECT_NOT_FOUND);
                simplerequest(globstring[STR_COULD_NOT_FIND_FILE],globstring[STR_CONTINUE],NULL);
            }
            else if (count>0) {
                lsprintf(buf2,globstring[STR_FOUND_MATCHING_FILES],count);
                dostatustext(buf2);
                simplerequest(buf2,globstring[STR_CONTINUE],NULL);
            }
            break;

        case FUNC_READ:
        case FUNC_HEXREAD:
        case FUNC_ANSIREAD:
        case FUNC_SMARTREAD:
            if (act>-1) refreshwindow(act,0);
            if (viewdata) cleanupviewfile(viewdata);
            if (status_justabort) myabort();
            else if (!okayflag && !(doerror(IoErr()))) okayflag=1;
            break;

        case FUNC_SHOW:
            if (config->viewbits&VIEWBITS_SHOWBLACK) {
                if (blankscreen) {
                    CloseScreen(blankscreen);
                    blankscreen=NULL;
                }
                ClearPointer(Window);
            }
            break;

        case FUNC_COMMENT:
            if (status_flags&STATUS_IANSCRAP && okayflag) {
                dostatustext(buf2);
                okayflag=0;
            }
            break;

        case FUNC_PROTECT:
            if (status_flags&STATUS_IANSCRAP && okayflag) {
                getprot(data,buf2);
                dostatustext(buf2);
                okayflag=0;
            }
            break;

        case FUNC_DATESTAMP:
            if (status_flags&STATUS_IANSCRAP && okayflag) {
                seedate(&datetime.dat_Stamp,buf2,0);
                dostatustext(buf2);
                okayflag=0;
            }
            break;

        case FUNC_SEARCH:
            if (count>-1) {
                if (count==0) simplerequest(globstring[STR_STRING_NOT_FOUND],
                    globstring[STR_CONTINUE],NULL);
                else {
                    lsprintf(buf2,globstring[STR_MATCHED_FILES],count);
                    simplerequest(buf2,globstring[STR_CONTINUE],NULL);
                }
                okayflag=1;
            }
            break;

        case FUNC_BYTE:
            if (!status_justabort) {
                main_proc->pr_WindowPtr=(APTR)-1;
                if (!(filelock=Lock(destdir,ACCESS_READ))) value=0;
                else {
                    Info(filelock,&infodata);
                    if (ramdisk_lock && CompareLock(filelock,ramdisk_lock)!=LOCK_DIFFERENT)
                        value=AvailMem(0);
                    else value=(infodata.id_NumBlocks-infodata.id_NumBlocksUsed)*blocksize;
                    UnLock(filelock);
                }
                if (config->errorflags&ERROR_ENABLE_DOS) main_proc->pr_WindowPtr=(APTR)Window;
                if (specflags&FUNCFLAGS_BYTEISCHECKFIT) {
                    double needed,percent;

                    needed=data*blocksize;
                    if (value<1) percent=0;
                    else if (value>=needed || needed<1) {
                        percent=100;
                        retval=1;
                    }
                    else percent=100/(needed/value);
                    getfloatstr(percent,tbuf);
                    lsprintf(buf,globstring[STR_CHECKFIT_STRING],data*blocksize,value,tbuf);
                    dostatustext(buf);
                }
                else {
                    doselinfo(act);
                    strcat(str_select_info,
                        (value<=swindow->bytessel)?
                            globstring[STR_NO_FIT]:globstring[STR_YES_FIT]);
                    dostatustext(str_select_info);
                }
                okayflag=0;
            }
            break;
    }

    if (okayflag && !status_justabort) okay();
    if (!noshow) {
        endfollow(act);
        displaydir(act); seename(act);
    }
    if (inact>-1) {
        displaydir(inact);
        seename(inact);
    }
    switch (function) {
        case FUNC_DELETE:
        case FUNC_RENAME:
        case FUNC_MOVE:
        case FUNC_MOVEAS:
        case FUNC_ADDICON:
        case FUNC_ICONINFO:
            update_buffer_stamp(act,1);
            break;

        case FUNC_COMMENT:
        case FUNC_PROTECT:
        case FUNC_DATESTAMP:
            update_buffer_stamp(act,0);
            break;
    }

    switch (function) {
        case FUNC_MOVE:
        case FUNC_MOVEAS:
        case FUNC_COPY:
        case FUNC_COPYAS:
        case FUNC_ENCRYPT:
            update_buffer_stamp(inact,1);
            break;
    }

    switch (function) {
        case FUNC_SEARCH:
            if (count>0) rexx_return_value=count;
            break;
    }

    startnotifies();

endfunction:
    if (prog_indicator) dotaskmsg(hotkeymsg_port,PROGRESS_CLOSE,0,0,NULL,0);
    LFreeRemember(&funckey);
    --entry_depth;
    return(retval);
}
