/*

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/xadmaster.h>

#define EXALL_NUM 2

void freedir(dir,win)
struct DirectoryWindow *dir;
int win;
{
        struct Directory *free,*work;

        if (dir) {
D(bug("freedir: %lx (directory: %s\tflags: %lx)\n",dir,dir->directory?dir->directory:"<NULL>",dir->flags));
                if (dir->firstentry && dir->total>0) {
                        if (dir->firstentry) {
                                free=dir->firstentry;
                                while (free) {
                                        if (free->next) work=free->next;
                                        else work=NULL;
                                        free->next=NULL;
                                        free->last=NULL;

                                        free_file_memory(free);
                                        free=work;
                                }
                        }
                }
                dir->firstentry=dir->firstfile=dir->firstdir=NULL;
                dir->oldoff=dir->oldhoff=-1;
                dir->offset=dir->total=dir->filesel=
                        dir->dirsel=
                        dir->dirtot=dir->filetot=dir->hoffset=0;
                                dir->bytessel = 0;
                                dir->bytestot = 0;
                dir->custhandler[0]=0;
                dir->realdevice[0]=0;
                dir->volumename[0]=0;
                if ((!(dir->flags & DWF_ARCHIVE)) || (win == -1))
                 {
                  dir->flags=0;
                  freearchive(dir);
                 }
                if (Window && win>-1) {
                        fixhorizprop(win);
                        last_selected_entry=NULL;
                }
        }
}

getdir(dir,win,incmess)
struct DirectoryWindow *dir;
int win,incmess;
{
        struct FileInfoBlock __aligned fileinfo;
        int tot=1,a,use_exall=0,exall_entry,exall_continue,exall_bufsize,subtype;
        BPTR mylock;
        char buf[256];
        struct ExAllControl *exall_control;
        struct ExAllData *exall_buffer,*exall_current;
        struct MsgPort *deviceport;

        endnotify(win);
//D(bug("dir: %lx\tDWF_ARCHIVE flag: %ld\n",dir,dir->flags&DWF_ARCHIVE));
        freedir(dir,win);

        vert_propinfo[win].VertPot=0;
        if (Window && !status_iconified) {
                refreshwindow(win,1);
                if (win==data_active_window)
                        SetAPen(main_rp,screen_pens[config->disknameselbg].pen);
                else SetAPen(main_rp,screen_pens[config->disknamebg].pen);
                rectfill(main_rp,
                        scrdata_diskname_xpos[win]+2,
                        scrdata_diskname_ypos,
                        scrdata_diskname_width[win],
                        scrdata_diskname_height-2);
                SetAPen(main_rp,screen_pens[1].pen);
        }

        if (!(mylock=Lock(dir->directory,ACCESS_READ))) {
                if (OpenXADlib()) if (readarchive(dir, win))
                 {
                  unbusy();
                  seename(win);
                  refreshwindow(win,1);
                  startnotify(win);
                  return(1);
                 }
                if (Window) doerror(IoErr());
                for (a=0;a<30;a++) {
                        if (str_pathbuffer[win][a]==':' || str_pathbuffer[win][a]==0) break;
                }
                if (str_pathbuffer[win][a]==':') LStrnCpy(dir->realdevice,str_pathbuffer[win],a+1);
                return(0);
        }

        strcpy(buf,str_pathbuffer[win]);
        if (getroot(buf,NULL)) {
                strcpy(dir->volumename,buf);
                strcat(buf,":");
                if (deviceport=(struct MsgPort *)DeviceProc(buf))
                        get_device_task(mylock,dir->realdevice,deviceport);
        }

        if (config->dirflags&DIRFLAGS_EXPANDPATHS) {
                PathName(mylock,buf,256);
                strcpy(str_pathbuffer[win],buf);
                if (Window) checkdir(str_pathbuffer[win],&path_strgadget[win]);
                else checkdir(str_pathbuffer[win],NULL);
                strcpy(dir->directory,str_pathbuffer[win]);
        }

        Examine(mylock,&fileinfo);
        if (fileinfo.fib_DirEntryType<0) {
                UnLock(mylock);
                if (OpenXADlib()) if (readarchive(dir, win))
                 {
                  unbusy();
                  seename(win);
                  refreshwindow(win,1);
                  startnotify(win);
                  return(1);
                 }
                if (Window) doerror(ERROR_OBJECT_WRONG_TYPE);
                return(0);
        }
        dir->flags=0;
        dir->firstentry=NULL;
        freearchive(dir);

        if (Window) {
                if (incmess) dostatustext(globstring[STR_READING_CHANGED_DIRECTORY]);
                else dostatustext(globstring[STR_READING_DIRECTORY]);
                busy();
        }
        copy_datestamp(&fileinfo.fib_Date,&dir->dirstamp);

        if (config->dirflags&DIRFLAGS_EXALL && system_version2>=OSVER_40) {
                if (exall_control=AllocDosObject(DOS_EXALLCONTROL,NULL)) {
                        if (exall_buffer=(struct ExAllData *)
                                AllocMem((exall_bufsize=((sizeof(struct ExAllData)+160)*EXALL_NUM)),MEMF_CLEAR)) {
                                use_exall=1;
                                exall_entry=0;
                                exall_continue=1;
                                exall_control->eac_Entries=0;
                                exall_control->eac_LastKey=0;
                                exall_control->eac_MatchString=NULL;
                                exall_control->eac_MatchFunc=NULL;
                                exall_current=NULL;
                        }
                        else {
                                FreeDosObject(DOS_EXALLCONTROL,exall_control);
                                exall_control=NULL;
                        }
                }
        }

        FOREVER {
                fileinfo.fib_OwnerUID=fileinfo.fib_OwnerGID=0;
                if (use_exall) {
                        if (exall_entry>=exall_control->eac_Entries || !exall_current) {
                                if (!exall_continue) break;
                                exall_continue=ExAll(mylock,exall_buffer,exall_bufsize,ED_COMMENT,exall_control);
                                exall_entry=0;
                                exall_current=exall_buffer;
                                continue;
                        }
                        if (exall_current->ed_Name)
                                strcpy(fileinfo.fib_FileName,exall_current->ed_Name);
                        else fileinfo.fib_FileName[0]=0;

                        fileinfo.fib_DirEntryType=exall_current->ed_Type;
                        fileinfo.fib_Size=exall_current->ed_Size;
                        fileinfo.fib_Protection=exall_current->ed_Prot;
                        fileinfo.fib_Date.ds_Days=exall_current->ed_Days;
                        fileinfo.fib_Date.ds_Minute=exall_current->ed_Mins;
                        fileinfo.fib_Date.ds_Tick=exall_current->ed_Ticks;
                        if (exall_current->ed_Comment)
/*
                                BtoCStr((BSTR)exall_current->ed_Comment,fileinfo.fib_Comment,79);
*/
                                strcpy(fileinfo.fib_Comment,exall_current->ed_Comment);
                        else fileinfo.fib_Comment[0]=0;
                        ++exall_entry;
                        exall_current=exall_current->ed_Next;
                }
                else {
                        if (!(ExNext(mylock,&fileinfo))) break;
                }

                subtype=fileinfo.fib_DirEntryType;
//D(bug("name: %s\ttype: %ld\n",fileinfo.fib_FileName,fileinfo.fib_DirEntryType));
                if (subtype == ST_SOFTLINK)
                 {
                  struct FileInfoBlock __aligned fib = fileinfo;
                  struct DevProc *dp;
                  BPTR ld, lf;
                  char linkbuf[512];

                  NameFromLock(mylock,linkbuf,512);
                  do
                   {
D(bug("SoftLink! path: %s/%s\n",linkbuf,fib.fib_FileName));
                    ld = Lock(linkbuf,ACCESS_READ);
                    if (dp = GetDeviceProc(linkbuf,NULL))
                     {
//D(bug("DeviceProc: %lX\n",dp));
                      if (ReadLink(dp->dvp_Port,ld,fib.fib_FileName,buf,256))
                       {
                        AddPart(linkbuf,buf,512);
D(bug("Resolved: %s\n",linkbuf));
                        if (lf = Lock(linkbuf,ACCESS_READ))
                         {
                          if (Examine(lf,&fib))
                           {
                            switch (fib.fib_DirEntryType)
                             {
                              case ST_ROOT:
                              case ST_USERDIR:
                              case ST_LINKDIR:
                                fileinfo.fib_DirEntryType = ENTRY_DIRECTORY;
                                break;
                              case ST_SOFTLINK:
                                NameFromLock(lf,linkbuf,512);
                                *PathPart(linkbuf) = 0;
                                break;
                              default:
                                fileinfo.fib_DirEntryType = ENTRY_FILE;
//                                  fileinfo.fib_Size = fib.fib_Size;
                                break;
                             }
                           }
                          UnLock(lf);
                         }
                        else
                         {
// D(bug("Lock() failed!\n"));
                          fileinfo.fib_DirEntryType = fib.fib_DirEntryType = ENTRY_FILE;
                          fileinfo.fib_Size = 0;
                         }
                       }
                      FreeDeviceProc(dp);
                      if (ld) UnLock(ld);
                     }
                   } while (fib.fib_DirEntryType == ST_SOFTLINK);
                 }
                if (status_haveaborted && Window) {
                        myabort();
                        dir->flags|=DWF_ABORTED;
                        tot=-1;
                        break;
                }
                if (!(addfile(dir,win,fileinfo.fib_FileName,
                        (fileinfo.fib_DirEntryType>0)?-1:fileinfo.fib_Size,
                        fileinfo.fib_DirEntryType,
                        &fileinfo.fib_Date,fileinfo.fib_Comment,fileinfo.fib_Protection,subtype,
                        FALSE,NULL,NULL,fileinfo.fib_OwnerUID,fileinfo.fib_OwnerGID))) {
                        if (Window) doerror(IoErr());
                        tot=0;
                        break;
                }
/* Code deleted by Pavel Cizek, 28. 3. 2000:
 *   This code was disable to speed-up directory reading.
 *   Its deletion causes no proportional-gadget refresh during scanning of a directory.
 *   The final update of directory proportional gadget is done by call refreshwindow(win,1)
 *   below via the same function - fixprop(win).
*/
                else if (Window) if ( config->dynamicflags & UPDATE_QUIETGETDIR ) fixprop(win); //HUX
/* * End of deleted code
 */
        }
        UnLock(mylock);

        if (Window) {
                unbusy();
                if (tot) {
                        seename(win);
                        if (tot==1) okay();
                }
                refreshwindow(win,1);
        }
        if (use_exall) {
                if (exall_control) FreeDosObject(DOS_EXALLCONTROL,exall_control);
                if (exall_buffer) FreeMem(exall_buffer,exall_bufsize);
        }
        startnotify(win);
        return(1);
}

void fixprop(win)
int win;
{
        if (win>-1 && !status_iconified) {
                FixSliderBody(Window,&vert_propgad[win],dopus_curwin[win]->total,scrdata_dispwin_lines,0);
                fixvertprop(win);
        }
}

void fixvertprop(win)
int win;
{
        if (win>-1 && !status_iconified) {
                FixSliderPot(Window,&vert_propgad[win],dopus_curwin[win]->offset,
                        dopus_curwin[win]->total,scrdata_dispwin_lines,2);
        }
}

void fixhorizprop(win)
int win;
{
        if (win>-1 && !status_iconified) {
                fixhlen(win);
                if (Window) {
                        FixSliderBody(NULL,&horiz_propgad[win],dopus_curwin[win]->hlen,scrdata_dispwin_nchars[win],0);
                        FixSliderPot(Window,&horiz_propgad[win],dopus_curwin[win]->hoffset,dopus_curwin[win]->hlen,scrdata_dispwin_nchars[win],2);
                }
        }
}

doposprop(win)
int win;
{
        int i;

        if (win<0 || status_iconified) return(0);
        if (!(status_flags&STATUS_NEWLOOK) &&
                vert_propgad[win].MutualExclude) ShowSlider(Window,&vert_propgad[win]);
        i=GetSliderPos(&vert_propgad[win],dopus_curwin[win]->total,scrdata_dispwin_lines);
        if (dopus_curwin[win]->offset==i) return(0);
        dopus_curwin[win]->offset=i;
        displaydir(win);
        return(1);
}

void doposhprop(win)
int win;
{
        int i;

        if (!status_iconified && win>-1) {
                if (!(status_flags&STATUS_NEWLOOK) &&
                        horiz_propgad[win].MutualExclude) ShowSlider(Window,&horiz_propgad[win]);
                i=GetSliderPos(&horiz_propgad[win],dopus_curwin[win]->hlen,scrdata_dispwin_nchars[win]);
                if (dopus_curwin[win]->hoffset==i) return;
                dopus_curwin[win]->hoffset=i; dopus_curwin[win]->oldoff=-1;
                displaydir(win);
        }
}

void checkdir(str,gad)
char *str;
struct Gadget *gad;
{
        struct StringInfo *sinfo;

        TackOn(str,NULL,256);
        if (gad) {
                sinfo=(struct StringInfo *)gad->SpecialInfo;
                gad->Flags|=GADGHNONE;
/*                if (!system_version2) {
                        sinfo->BufferPos=0; RefreshGList(gad,Window,NULL,1);
                } */
                sinfo->BufferPos=strlen(str); RefreshGList(gad,Window,NULL,1);
                gad->Flags&=~GADGHNONE;
        }
}

void verticalscroll(win,dir)
int win,dir;
{
        if (win<0 || dopus_curwin[win]->total<=scrdata_dispwin_lines) return;

        if (dir<0) {
                --dopus_curwin[win]->offset;
                if (dopus_curwin[win]->offset<0) {
                        dopus_curwin[win]->offset=0;
                        return;
                }
        }
        else {
                ++dopus_curwin[win]->offset;
                if (dopus_curwin[win]->offset>dopus_curwin[win]->total-scrdata_dispwin_lines) {
                        dopus_curwin[win]->offset=dopus_curwin[win]->total-scrdata_dispwin_lines;
                        return;
                }
        }
        fixvertprop(win);
        displaydir(win);
}

void horizontalscroll(win,dir)
int win,dir;
{
        if (win<0 || dopus_curwin[win]->total==0 || dopus_curwin[win]->firstentry->type==ENTRY_DEVICE)
                return;
        if (dir<0) {
                if (dopus_curwin[win]->hoffset==0) return;
                --dopus_curwin[win]->hoffset;
        }
        else {
                if (dopus_curwin[win]->hoffset==dopus_curwin[win]->hlen-scrdata_dispwin_nchars[win]) return;
                ++dopus_curwin[win]->hoffset;
        }
        refreshwindow(win,1);
}

void findfirstsel(win,type)
int win,type;
{
        struct Directory *sel;
        int a;

        if (win<0 || dopus_curwin[win]->total<=scrdata_dispwin_lines) return;
        sel=dopus_curwin[win]->firstentry; a=0;
        while (sel) {
                if (sel->selected) {
                        if (type==-2 || ENTRYTYPE(sel->type)==type) break;
                }
                sel=sel->next;
                ++a;
        }
        if (sel) {
                dopus_curwin[win]->offset=a;
                if (dopus_curwin[win]->offset>dopus_curwin[win]->total-scrdata_dispwin_lines)
                        dopus_curwin[win]->offset=dopus_curwin[win]->total-scrdata_dispwin_lines;
                fixvertprop(win);
                displaydir(win);
        }
        return;
}

void findfirstchar(win,c)
int win;
char c;
{
        struct Directory *sel;
        int a=0,b=0,file=0;

        if (isupper(c)) { file=1; c=ToLower(c); }
        if (dopus_curwin[win]->total<=scrdata_dispwin_lines) return;
        sel=dopus_curwin[win]->firstentry;
        while (sel) {
                if (ToLower(sel->name[0])>=c) {
                        if (!file || ENTRYTYPE(sel->type)==ENTRY_FILE) {
                                b=1;
                                break;
                        }
                }
                if (sel->next) sel=sel->next;
                else sel=NULL;
                ++a;
        }
        if (!b) dopus_curwin[win]->offset=dopus_curwin[win]->total-scrdata_dispwin_lines;
        else {
                dopus_curwin[win]->offset=a;
                if (dopus_curwin[win]->offset>dopus_curwin[win]->total-scrdata_dispwin_lines)
                        dopus_curwin[win]->offset=dopus_curwin[win]->total-scrdata_dispwin_lines;
        }
        if (dopus_curwin[win]->offset<0) dopus_curwin[win]->offset=0;
        fixvertprop(win);
        displaydir(win);
}

void doinfodisplay(entry,state)
struct Directory *entry;
int state;
{
        char buf[MAXDISPLAYLENGTH],pbuf[10],dbuf[30];

        buf[0]=0;
        if (entry->selected==state) {
                getprot(entry->protection,pbuf);
                nodayseedate(&(entry->date),dbuf);
                lsprintf(buf,"%8s %18s ",pbuf,dbuf);
                if (entry->type!=ENTRY_CUSTOM && entry->comment)
                        strcat(buf,entry->comment);
        }
        dostatustext(buf);
}

void nodayseedate(ds,date)
struct DateStamp *ds;
char *date;
{
        char datebuf[16],timebuf[16];
        struct DOpusDateTime dt;

        copy_datestamp(ds,&dt.dat_Stamp);
        initdatetime(&dt,datebuf,timebuf,0);
        strcpy(date,datebuf); strcat(date," "); strcat(date,timebuf);
}

void displaydirgiven(win,dir,bypass)
int win;
struct Directory *dir;
char bypass;
{
        struct Directory *display;
        int off;

        if (win<0 ||
                (!bypass && !(config->dynamicflags&UPDATE_SCROLL))) return;

        display=dopus_curwin[win]->firstentry;
        off=0;
        while (display) {
                if (display==dir) break;
                display=display->next;
                ++off;
        }
        if (!display) return;
        dopus_curwin[win]->offset=off;
        if (dopus_curwin[win]->oldoff>-1) {
                if (dopus_curwin[win]->offset>=dopus_curwin[win]->oldoff &&
                        dopus_curwin[win]->offset<dopus_curwin[win]->oldoff+scrdata_dispwin_lines)
                        dopus_curwin[win]->offset=dopus_curwin[win]->oldoff;
        }
        if (dopus_curwin[win]->offset>dopus_curwin[win]->total-scrdata_dispwin_lines)
                dopus_curwin[win]->offset=dopus_curwin[win]->total-scrdata_dispwin_lines;
        if (dopus_curwin[win]->offset<0) dopus_curwin[win]->offset=0;
        if (dopus_curwin[win]->offset!=dopus_curwin[win]->oldoff) {
                displaydir(win);
                fixvertprop(win);
        }
}

void endfollow(win)
int win;
{
        if (win>-1 && scrdata_old_offset_store>-1) {
                dopus_curwin[win]->offset=scrdata_old_offset_store;
                if (dopus_curwin[win]->offset>(dopus_curwin[win]->total-scrdata_dispwin_lines))
                        dopus_curwin[win]->offset=dopus_curwin[win]->total-scrdata_dispwin_lines;
                if (dopus_curwin[win]->offset<0) dopus_curwin[win]->offset=0;
                fixvertprop(win);
                displaydir(win);
                scrdata_old_offset_store=-1;
        }
}

void displaydir(win)
int win;
{
        int d,a,l,tl,bl,b,ds,my,c,f,pw,px,lpst8,sc,to,y;
        char sbuf[MAXDISPLAYLENGTH];
        struct Directory *display;

        if (win<0 || status_iconified) return;
        l=dopus_curwin[win]->oldoff-dopus_curwin[win]->offset;
        display=dopus_curwin[win]->firstentry;
        if (l<0) {
                tl=scrdata_dispwin_lines-1+l; bl=scrdata_dispwin_lines; a=-l;
        }
        else {
                tl=-1; bl=l; a=l;
        }
        b=scrdata_dispwin_lines-1;
        if (dopus_curwin[win]->oldoff==-1 || a>b) {
                tl=-1; bl=scrdata_dispwin_lines; ds=0; sc=0;
        }
        else {
                b=ABSI(l);
                if (config->dynamicflags&4 && b>(scrdata_dispwin_lines/4)) {
                        tl=-1; bl=scrdata_dispwin_lines; ds=0; sc=0;
                }
                else {
                        if (b==0) d=0;
                        else d=-(dopus_curwin[win]->oldoff-dopus_curwin[win]->offset)/b;
                        ds=1; sc=d;
                }
        }
        for (a=0;a<dopus_curwin[win]->offset;a++) {
                if (!display) break;
                display=display->next;
        }
        if (sc<0 && ds) {
                c=b-1;
                for (a=0;a<c;a++) {
                        if (!display) break;
                        display=display->next;
                }
        }
        if (ds) {
                if (sc<0) my=scrdata_font_baseline;
                else my=(scrdata_font_baseline+scrdata_dirwin_height)-scrdata_font_ysize;
        }
        else my=scrdata_font_ysize+scrdata_font_baseline+(tl*scrdata_font_ysize);
        my+=scrdata_dirwin_ypos[win];
        lpst8=scrdata_dirwin_height-scrdata_font_ysize;

        ++tl;
        for (a=0;a<tl;a++) {
                if (!display) break;
                if (sc<0) display=display->last;
                else display=display->next;
        }
        pw=scrdata_dispwin_nchars[win]; px=scrdata_dirwin_xpos[win]; to=0;
        if (dopus_curwin[win]->oldhoff!=-1) {
                f=dopus_curwin[win]->oldhoff-dopus_curwin[win]->hoffset;
                if (f && f>-scrdata_dispwin_nchars[win] && f<scrdata_dispwin_nchars[win]) {
                        if (f>0) ClipBlit(&dir_rp[win],scrdata_dirwin_xpos[win],scrdata_dirwin_ypos[win],&dir_rp[win],
                                (f*scrdata_font_xsize)+scrdata_dirwin_xpos[win],scrdata_dirwin_ypos[win],scrdata_dirwin_width[win]-(f*scrdata_font_xsize),scrdata_dirwin_height,0xc0);
                        else {
                                f=-f;
                                ClipBlit(&dir_rp[win],(f*scrdata_font_xsize)+scrdata_dirwin_xpos[win],scrdata_dirwin_ypos[win],&dir_rp[win],
                                        scrdata_dirwin_xpos[win],scrdata_dirwin_ypos[win],scrdata_dirwin_width[win]-(f*scrdata_font_xsize),scrdata_dirwin_height,0xc0);
                                px=(scrdata_dirwin_width[win]-(f*scrdata_font_xsize))+scrdata_dirwin_xpos[win]; to=scrdata_dispwin_nchars[win]-f;
                        }
                        pw=f;
                }
        }
        for (a=tl;a<bl;a++) {
                setdispcol(display,win);
                builddisplaystring(display,sbuf,win);
                y=my;
                if (ds) {
                        if (sc>0) ClipBlit(&dir_rp[win],scrdata_dirwin_xpos[win],scrdata_font_ysize+scrdata_dirwin_ypos[win],&dir_rp[win],
                                scrdata_dirwin_xpos[win],scrdata_dirwin_ypos[win],scrdata_dirwin_width[win],lpst8,0xc0);
                        else ClipBlit(&dir_rp[win],scrdata_dirwin_xpos[win],scrdata_dirwin_ypos[win],&dir_rp[win],
                                scrdata_dirwin_xpos[win],scrdata_font_ysize+scrdata_dirwin_ypos[win],scrdata_dirwin_width[win],lpst8,0xc0);
                }
                else my+=scrdata_font_ysize;
                entry_text(&dir_rp[win],display,&sbuf[to],pw,px,y);
                if (display) {
                        if (sc<0) display=display->last;
                        else display=display->next;
                }
        }
        dopus_curwin[win]->oldoff=dopus_curwin[win]->offset;
        dopus_curwin[win]->oldhoff=dopus_curwin[win]->hoffset;
}

void display_entry(entry,win,x,y)
struct Directory *entry;
int win,x,y;
{
        char dispbuf[MAXDISPLAYLENGTH];

        setdispcol(entry,win);
        builddisplaystring(entry,dispbuf,win);
        entry_text(&dir_rp[win],entry,dispbuf,scrdata_dispwin_nchars[win],x,y);
}

void entry_text(rp,entry,buf,len,x,y)
struct RastPort *rp;
struct Directory *entry;
char *buf;
int len,x,y;
{
        int a,final=0;

        Move(rp,x,y);
        if (entry && entry->type==ENTRY_CUSTOM && entry->subtype==CUSTOMENTRY_DIRTREE) {
                char pbuf[MAXDISPLAYLENGTH];

                strcpy(pbuf,buf);
                for (a=0;a<len;a++) {
                        if (buf[a]=='|' || buf[a]=='+' || buf[a]=='-')
                                buf[a]=' ';
                        else if (buf[a]!=' ') break;
                }
                Text(rp,buf,len);
                if (entry->selected) SetAPen(rp,screen_pens[config->dirsselfg].pen);
                else SetAPen(rp,screen_pens[config->dirsfg].pen);
                y-=scrdata_font_baseline;

                for (a=0;a<len;a++) {
                        if (pbuf[a]=='|') {
                                if (pbuf[a+1]=='-') draw_dirtree_gfx(rp,x,y,DIRTREEGFX_VERTCROSS);
                                else draw_dirtree_gfx(rp,x,y,DIRTREEGFX_VERT);
                        }
                        else if (pbuf[a]=='-') {
                                draw_dirtree_gfx(rp,x,y,(final)?DIRTREEGFX_FINALCROSS:DIRTREEGFX_CROSS);
                                final=1-final;
                        }
                        else if (pbuf[a]=='+') draw_dirtree_gfx(rp,x,y,DIRTREEGFX_BRANCH);
                        else if (pbuf[a]!=' ') break;
                        x+=scrdata_font_xsize;
                }
        }
        else
         {
          if (entry) switch (entry->subtype)
           {
            case ST_SOFTLINK:
            case ST_LINKDIR:
            case ST_LINKFILE:
              a = 1;
              break;
            default:
              a = 0;
           }
          else a = 0;
          if (a) SetSoftStyle(rp,FSF_BOLD,FSF_BOLD);
          Text(rp,buf,len);
          if (a) SetSoftStyle(rp,FS_NORMAL,FSF_BOLD);
         }
}

#define DISPLAYSIZELENGTH     10
#define DISPLAYSIZEFORMAT     "%9ld "

void buildkmgstring(char *buf, ULONG size, int lister)
{
 if ( config->listerdisplayflags[ lister ] & SIZE_KMG ) // HUX
  {
   if (size & 0xFFFFFC00) // >1024
    {
     char tmp[16],c;

     if (size & 0xFFF00000) // >1024*1024
      {
       if (size & 0xC0000000) // >1024*1024*1024
        {
         getfloatstr(size/(float)(1024*1024*1024),tmp);
         c = 'G';
//         if (tmp[3] == '.') tmp[3] = 0;
//         else if (tmp[4] == '.') tmp[4] = 0;
//         lsprintf(buf,"%4sG ",tmp);
        }
       else
        {
         getfloatstr(size/(float)(1024*1024),tmp);
         c = 'M';
//         if (tmp[3] == '.') tmp[3] = 0;
//         else if (tmp[4] == '.') tmp[4] = 0;
//         lsprintf(buf,"%4sM ",tmp);
        }
      }
     else
      {
       getfloatstr(size/(float)1024,tmp);
       c = 'K';
//       if (tmp[3] == '.') tmp[3] = 0;
//       else if (tmp[4] == '.') tmp[4] = 0;
//       lsprintf(buf,"%4sK ",tmp);
      }
     if (tmp[3] == '.') tmp[3] = 0;
     else if (tmp[4] == '.') tmp[4] = 0;
     lsprintf(buf,"%4s%lc ",tmp,c);
    }
   else lsprintf(buf,"%4ld  ",size);
  }
 else lsprintf(buf, DISPLAYSIZEFORMAT,size);
}

char *buildfileliststring(entry,dptr,win)
struct Directory *entry;
char *dptr;
int win;
{
 char sizebuf[20];
 char *sptr;
 int  a,b,namelen;

  namelen=config->displaylength[win][DISPLAY_NAME];

/* Code modified by Pavel Cizek, 1. 4. 2000:
*   Introduced a symbol for the length of size string
*   MAXDISPLAYLENGTH (=256) of buffer to which the file entry is recorder is definitely
*   high enough for DISPLAYSIZELENGTH up to 10 (given the limits 30, 80, and 40 on the length
*   of file name, file comment and file type. If unsure, increase MAXDISPLAYLENGTH
*   by (DISPLAYSIZELENGTH - 8).
*   This constant includes presumed length of size + 1 (for separating space).
*   DISPLAYSIZEFORMAT contains the corresponding formating string of the form
*   "%<DISPLAYSIZELENGTH-1>ld "
*/
  if (entry->type<0 || (entry->type>0 && entry->size>=0)) {
          buildkmgstring(sizebuf,entry->size,win);
          if ((a=strlen(sizebuf))>DISPLAYSIZELENGTH) {
                  a-=DISPLAYSIZELENGTH;
                  if (namelen>(64-a)) namelen=64-a;
          }
  }
  else LStrnCpy(sizebuf,str_space_string, ( config->listerdisplayflags[win] & SIZE_KMG ) == SIZE_KMG ? 6 : DISPLAYSIZELENGTH); // HUX

  for (a=0;a<DISPLAY_LAST+1;a++) {
          switch (config->displaypos[win][a]) {
                  case DISPLAY_NAME:
                          b=namelen;
                          sptr=entry->name;
                          while (*sptr && b) {
                                  *dptr++=*sptr++;
                                  --b;
                          }
                          while (b--) *dptr++=' ';
                          break;
                  case DISPLAY_SIZE:
                          sptr=sizebuf;
                          while (*sptr) *dptr++=*sptr++;
                          break;
                  case DISPLAY_PROTECT:
                          sptr=entry->protbuf;
                          while (*sptr) *dptr++=*sptr++; *dptr++=' ';
                          break;
                  case DISPLAY_DATE:
                          sptr=entry->datebuf;
                          while (*sptr) *dptr++=*sptr++; *dptr++=' ';
                          break;
                  case DISPLAY_COMMENT:
                          b=config->displaylength[win][1];
                          if ((sptr=entry->comment)) {
                                  while (*sptr && b) {
                                          *dptr++=*sptr++;
                                          --b;
                                  }
                          }
                          while (b--) *dptr++=' ';
                          break;
                  case DISPLAY_FILETYPE:
                          b=config->displaylength[win][2];
                          if ((sptr=entry->description)) {
                                  while (*sptr && b) {
                                          *dptr++=*sptr++;
                                          --b;
                                  }
                          }
                          while (b--) *dptr++=' ';
                          break;
                  case DISPLAY_OWNER:
                          if (AccountsBase) {
                                  b=config->displaylength[win][3];
                                  if (!entry->network || !(sptr=entry->network->owner))
                                          sptr=globstring[STR_NETWORK_NO_OWNER];
                                  while (*sptr && b) {
                                          *dptr++=*sptr++;
                                          --b;
                                  }
                                  while (b--) *dptr++=' ';
                          }
                          break;
                  case DISPLAY_GROUP:
                          if (AccountsBase) {
                                  b=config->displaylength[win][4];
                                  if (!entry->network || !(sptr=entry->network->group))
                                          sptr=globstring[STR_NETWORK_NO_GROUP];
                                  while (*sptr && b) {
                                          *dptr++=*sptr++;
                                          --b;
                                  }
                                  while (b--) *dptr++=' ';
                          }
                          break;
                  case DISPLAY_NETPROT:
                          if (AccountsBase) {
                                  b=10;
                                  if (entry->network) {
                                          sptr=entry->network->net_protbuf;
                                          while (*sptr && b) {
                                                  *dptr++=*sptr++;
                                                  --b;
                                          }
                                  }
                                  while (b--) *dptr++=' ';
                          }
                          break;
          }
  }
 return dptr;
}

void builddisplaystring(display,sbuf,win)
 struct Directory *display;
 char *sbuf;
 int win;
{
        char buf[MAXDISPLAYLENGTH];
        char *dptr,*eptr;
        int a;

        if (!display) CopyMem(str_space_string,sbuf,scrdata_dispwin_nchars[win]);
        else switch (ENTRYTYPE(display->type)) {
                case ENTRY_CUSTOM:
                        CopyMem(str_space_string,sbuf,scrdata_dispwin_nchars[win]);
                        if (display->comment) {
                                a=strlen(display->comment)-dopus_curwin[win]->hoffset;
                                if (a>scrdata_dispwin_nchars[win]) a=scrdata_dispwin_nchars[win];
                                if (a>0) CopyMem(&display->comment[dopus_curwin[win]->hoffset],sbuf,a);
                        }
                        break;
                case ENTRY_DEVICE:
                        CopyMem(str_space_string,sbuf,scrdata_dispwin_nchars[win]);
                        CopyMem(display->name,sbuf,strlen(display->name));
                        CopyMem(display->comment,&sbuf[scrdata_dispwin_nchars[win]-5],5);
                        break;
                default:
                        dptr = buildfileliststring(display,buf,win);
                        /*dptr=buf;*/ eptr=buf+dopus_curwin[win]->hlen+1;
                        while (dptr<eptr) *dptr++=' ';
                        CopyMem(&buf[dopus_curwin[win]->hoffset],sbuf,scrdata_dispwin_nchars[win]);
                        break;
        }
}

void setdispcol(display,win)
struct Directory *display;
int win;
{
        int fg,bg;

        if (display && !status_iconified) {
                switch (ENTRYTYPE(display->type)) {
                        case ENTRY_FILE:
                                if (display->selected) {
                                        fg=config->filesselfg;
                                        bg=config->filesselbg;
                                }
                                else {
                                        fg=config->filesfg;
                                        bg=config->filesbg;
                                }
                                break;
                        case ENTRY_DEVICE:
                                if (display->size==DLT_DEVICE || display->size==DLT_VOLUME) {
                                        if (display->selected) {
                                                fg=config->filesselfg;
                                                bg=config->filesselbg;
                                        }
                                        else {
                                                fg=config->filesfg;
                                                bg=config->filesbg;
                                        }
                                        break;
                                }
                        case ENTRY_DIRECTORY:
                                if (display->selected) {
                                        fg=config->dirsselfg;
                                        bg=config->dirsselbg;
                                }
                                else {
                                        fg=config->dirsfg;
                                        bg=config->dirsbg;
                                }
                                break;
                        case ENTRY_CUSTOM:
                                if (display->subtype==CUSTOMENTRY_USER) {
                                        if (display->selected) {
                                                fg=config->filesselfg;
                                                bg=config->filesselbg;
                                        }
                                        else {
                                                if ((display->size&0xff)==0xff) fg=config->filesfg;
                                                else fg=display->size&0xff;
                                                if ((display->size&0xff00)==0xff00) bg=config->filesbg;
                                                else bg=(display->size&0xff00)>>8;
                                        }
                                }
                                else {
                                        if (display->selected) {
                                                fg=config->dirsselfg;
                                                bg=config->dirsselbg;
                                        }
                                        else {
                                                fg=config->dirsfg;
                                                bg=config->dirsbg;
                                        }
                                }
                                break;
                }
        }
        else {
                fg=bg=config->filesbg;
        }
        SetAPen(&dir_rp[win],screen_pens[fg].pen);
        SetBPen(&dir_rp[win],screen_pens[bg].pen);
}
