#define INCL_DOS
#define INCL_DOSERRORS
#define INCL_WIN
#define INCL_GPI

#include <os2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <process.h>
#include "fm3dll.h"
#include "fm3dlg.h"
#include "fm3str.h"

#pragma data_seg(DATA2)
#pragma alloc_text(SEEALL,comparefullnames,comparenames,comparesizes)
#pragma alloc_text(SEEALL,comparedates,compareexts,SeeStatusProc)
#pragma alloc_text(SEEALL,InitWindow,PaintLine,SeeAllWndProc)
#pragma alloc_text(SEEALL,UpdateList,CollectList,ReSort,Mark,MarkList)
#pragma alloc_text(SEEALL,BuildAList,RemoveDeleted,SeeFrameWndProc,FilterList)
#pragma alloc_text(SEEALL2,SeeObjWndProc,MakeSeeObj,FindDupes,DupeDlgProc)
#pragma alloc_text(SEEALL3,FreeAllFilesList,DoADir,FindAll,AFDrvsWndProc)
#pragma alloc_text(SEEALL3,StartSeeAll)

typedef struct {
  CHAR   *fullname,*filename;
  USHORT  attrFile,flags;
  FDATE   date;
  FTIME   time;
  ULONG   cbFile,CRC;
} ALLFILES;

#define AF_SELECTED     0x0001
#define AF_DELETED      0x0002
#define AF_FILTERED     0x0004
#define AF_DUPE         0x0008
#define AF_CRCED        0x0010

#define AFM_MARK        0
#define AFM_UNMARK      1
#define AFM_INVERT      2
#define AFM_MARKDELETED 3
#define AFM_FILTER      4

#define DP_NAMES        0x0001
#define DP_DATES        0x0002
#define DP_SIZES        0x0004
#define DP_CRCS         0x0008
#define DP_EXTS         0x0010

#define FIXED_FONT_LCID 5

#define COLORS_MAX                   8

#define COLORS_CURSOREDNORMALBACK    0
#define COLORS_CURSOREDSELECTEDBACK  1
#define COLORS_NORMALBACK            2
#define COLORS_SELECTEDBACK          3
#define COLORS_SELECTEDNORMALFORE    4
#define COLORS_NORMALFORE            5
#define COLORS_READONLYFORE          6
#define COLORS_SYSTEMFORE            7

static LONG   Colors[COLORS_MAX] = {COLR_WHITE,COLR_DARKGRAY,COLR_PALEGRAY,
                                    COLR_BLACK,COLR_WHITE,COLR_BLACK,
                                    COLR_DARKBLUE,COLR_DARKRED};

typedef int(FNSORT)(const void *,const void *);
typedef FNSORT *PFNSORT;

typedef struct {
  USHORT    size;
  USHORT    dupeflags;
  ALLFILES *afhead,**afindex;
  ULONG     affiles,afalloc,afFilesToGet,longest,longestw,
            topfile,cursored,selected,selbytes,afifiles,
            lastselected,lastdirection,multiplier,lasttime;
  CHAR      stopflag,drvsflags[26],lasttarget[CCHMAXPATH],
            comnam[CCHMAXPATH],findpath[CCHMAXPATH];
  LONG      lMaxAscender,lMaxDescender,lMaxHeight,maxx,horzscroll;
  BOOL      fullnames,invertsort,mousecaptured;
  HMTX      ScanSem;
  HWND      hvscroll,hhscroll,hwndMenu,hwndObj,hwndClient,hwndPopup,
            hwndStatus,hwndFrame;
  HPS       hps;
  PFNSORT   compare;
  MASK      mask;
  FATTRS    fattrs;
  LONG      colors[8];
  BOOL      killme;
} ALLDATA;

static BOOL   Fullnames = FALSE;
static BOOL   Firsttime = TRUE;
static BOOL   SortReverse;
static USHORT Codepage,SortType;
static FATTRS Fattrs;

extern LONG CRCFile (CHAR *filename,INT *error);


MRESULT EXPENTRY DupeDlgProc (HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2) {

  switch(msg) {
    case WM_INITDLG:
      {
        USHORT flags = SHORT1FROMMP(mp2);

        WinCheckButton(hwnd,DUPE_NAMES,((flags & DP_NAMES) != 0));
        WinCheckButton(hwnd,DUPE_DATES,((flags & DP_NAMES) != 0));
        WinCheckButton(hwnd,DUPE_SIZES,((flags & DP_NAMES) != 0));
        WinCheckButton(hwnd,DUPE_CRCS,((flags & DP_NAMES) != 0));
        if(!(flags & DP_NAMES))
          WinEnableWindow(WinWindowFromID(hwnd,DUPE_EXTS),FALSE);
      }
      break;

    case WM_CONTROL:
      switch(SHORT1FROMMP(mp1)) {
        case DUPE_NAMES:
          if(WinQueryButtonCheckstate(hwnd,DUPE_NAMES))
            WinEnableWindow(WinWindowFromID(hwnd,DUPE_EXTS),TRUE);
          else {
            WinCheckButton(hwnd,DUPE_EXTS,FALSE);
            WinEnableWindow(WinWindowFromID(hwnd,DUPE_EXTS),FALSE);
          }
          break;
        case DUPE_SIZES:
          if(!WinQueryButtonCheckstate(hwnd,DUPE_SIZES))
            WinCheckButton(hwnd,DUPE_CRCS,FALSE);
          break;
        case DUPE_CRCS:
          if(WinQueryButtonCheckstate(hwnd,DUPE_CRCS))
            WinCheckButton(hwnd,DUPE_SIZES,TRUE);
          break;
      }
      return 0;

    case WM_COMMAND:
      switch(SHORT1FROMMP(mp1)) {
        case DID_OK:
          {
            USHORT flags = 0;

            if(WinQueryButtonCheckstate(hwnd,DUPE_NAMES)) {
              flags |= DP_NAMES;
              if(WinQueryButtonCheckstate(hwnd,DUPE_EXTS))
                flags |= DP_EXTS;
            }
            if(WinQueryButtonCheckstate(hwnd,DUPE_DATES))
              flags |= DP_DATES;
            if(WinQueryButtonCheckstate(hwnd,DUPE_SIZES)) {
              flags |= DP_SIZES;
              if(WinQueryButtonCheckstate(hwnd,DUPE_CRCS))
                flags |= (DP_CRCS | DP_SIZES);
            }
            if(!flags)
              saymsg(MB_ENTER,
                     hwnd,
                     GetPString(IDS_ERRORTEXT),
                     "%s",
                     GetPString(IDS_CHECKONETEXT));
            else
              WinDismissDlg(hwnd,flags);
          }
          break;

        case DID_CANCEL:
          WinDismissDlg(hwnd,0);
          break;

        case IDM_HELP:
          if(hwndHelp)
            WinSendMsg(hwndHelp,HM_DISPLAY_HELP,
                       MPFROM2SHORT(HELP_DUPES,0),
                       MPFROMSHORT(HM_RESOURCEID));
          break;
      }
      return 0;
  }
  return WinDefDlgProc(hwnd,msg,mp1,mp2);
}


static ULONG NumLines (RECTL *rcl,ALLDATA *ad) {

  ULONG numlines;

  numlines = (rcl->yTop - rcl->yBottom) / ad->lMaxHeight;
  if(ad->lMaxDescender && numlines &&
     ((rcl->yTop - rcl->yBottom) -
      (numlines * ad->lMaxHeight) <= ad->lMaxDescender))
    numlines--;
  return numlines;
}


MRESULT EXPENTRY SeeObjWndProc (HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2) {

  switch(msg) {
    case UM_MASSACTION:
      {
        CHAR         **files = NULL,**list = (CHAR **)mp2,path[CCHMAXPATH];
        INT            numfiles = 0,numalloc = 0,plen = 0;
        HWND           hwndFrame = WinQueryWindowULong(hwnd,0);
        CHAR           message[CCHMAXPATH * 2],wildname[CCHMAXPATH];
        register INT   x;
        register CHAR *p,*pp;
        BOOL           dontask = FALSE,wildcarding = FALSE,
                       overold = FALSE,overnew = FALSE;

        if(!list || !list[0])
          goto Abort;
        *path = *wildname = 0;

        switch(SHORT1FROMMP(mp1)) {
          case IDM_MOVEPRESERVE:
            {
              CHAR preserve[CCHMAXPATH],*end;

              mp1 = MPFROM2SHORT(IDM_MOVE,
                                 SHORT2FROMMP(mp1));
              strcpy(preserve,list[0] + 2);
              end = strrchr(preserve,'\\');
              if(end) {
                end++;
                for(x = 1;list[x];x++) {
                  p = preserve;
                  pp = list[x] + 2;
                  while(p < end && toupper(*p) == toupper(*pp)) {
                    p++;
                    pp++;
                  }
                  if(*p == '\\')
                    p++;
                  if(p < end)
                    end = p;
                }
                *end = 0;
              }
              else
                *preserve = 0;
              plen = strlen(preserve);
              if(plen)
                plen += 2;
            }
            break;
          case IDM_COPYPRESERVE:
            {
              CHAR preserve[CCHMAXPATH],*end;

              mp1 = MPFROM2SHORT(IDM_COPY,
                                 SHORT2FROMMP(mp1));
              strcpy(preserve,list[0] + 2);
              end = strrchr(preserve,'\\');
              if(end) {
                end++;
                for(x = 1;list[x];x++) {
                  p = preserve;
                  pp = list[x] + 2;
                  while(p < end && toupper(*p) == toupper(*pp)) {
                    p++;
                    pp++;
                  }
                  if(*p == '\\')
                    p++;
                  if(p < end)
                    end = p;
                }
                *end = 0;
              }
              else
                *preserve = 0;
              plen = strlen(preserve);
              if(plen)
                plen += 2;
            }
            break;
          case IDM_WILDMOVE:
            wildcarding = TRUE;
            mp1 = MPFROM2SHORT(IDM_MOVE,
                               SHORT2FROMMP(mp1));
            break;
          case IDM_WILDRENAME:
            wildcarding = TRUE;
            mp1 = MPFROM2SHORT(IDM_RENAME,
                               SHORT2FROMMP(mp1));
            break;
          case IDM_WILDCOPY:
            wildcarding = TRUE;
            mp1 = MPFROM2SHORT(IDM_COPY,
                               SHORT2FROMMP(mp1));
            break;
        }

        switch(SHORT1FROMMP(mp1)) {
          case IDM_OBJECT:
          case IDM_SHADOW:
            {
              APIRET   rc;

              GetDesktopName(path,sizeof(path));
              rc = WinDlgBox(HWND_DESKTOP,
                             hwndFrame,
                             ObjCnrDlgProc,
                             FM3ModHandle,
                             OBJCNR_FRAME,
                             MPFROMP(path));
              if(rc) {
                if(rc > 1)
                  strcpy(path,"<WP_DESKTOP>");
              }
              else {
                FreeList(list);
                break;
              }
              MakeShadows(hwndFrame,
                          list,
                          (SHORT1FROMMP(mp1) == IDM_SHADOW),
                          path,
                          NULL);
            }
            FreeList(list);
            break;

          case IDM_PRINT:
            {
              LISTINFO *li;

              li = malloc(sizeof(LISTINFO));
              if(li) {
                memset(li,0,sizeof(LISTINFO));
                li->hwndS = WinWindowFromID(hwndFrame,FID_CLIENT);
                li->type = IDM_PRINT;
                li->list = list;
                if(WinDlgBox(HWND_DESKTOP,
                             li->hwndS,
                             PrintDlgProc,
                             FM3ModHandle,
                             PRN_FRAME,
                             MPFROMP(li))) {
                  if(li && li->list && li->list[0]) {
                    strcpy(li->targetpath,printer);
                    if(_beginthread(PrintList,
                                    NULL,
                                    65536,
                                    (PVOID)li) == -1) {
                      DosBeep(50,100);
                      FreeListInfo(li);
                    }
                  }
                }
              }
              else
                FreeList(list);
            }
            break;

          case IDM_EAS:
            if(WinDlgBox(HWND_DESKTOP,
                         hwndFrame,
                         DisplayEAsProc,
                         FM3ModHandle,
                         EA_FRAME,
                         (PVOID)list)) {
              if(!PostMsg(WinWindowFromID(hwndFrame,FID_CLIENT),
                          UM_UPDATERECORDLIST,
                          MPFROMP(list),
                          MPVOID))
                FreeList(list);
            }
            else
              FreeList(list);
            break;

          case IDM_INFO:
            if(WinDlgBox(HWND_DESKTOP,
                         hwndFrame,
                         FileInfoProc,
                         FM3ModHandle,
                         FLE_FRAME,
                         (PVOID)list) == 2) {
              if(!PostMsg(WinWindowFromID(hwndFrame,FID_CLIENT),
                             UM_UPDATERECORDLIST,
                             MPFROMP(list),
                             MPVOID))
                FreeList(list);
            }
            else
              FreeList(list);
            break;

          case IDM_ARCHIVE:
            {
              DIRCNRDATA     ad;
              CHAR           szBuffer[1025];

              memset(&ad,0,sizeof(DIRCNRDATA));
              ad.namecanchange = 1;
              ad.info = arcsighead;
              if(!WinDlgBox(HWND_DESKTOP,
                            hwndFrame,
                            SBoxDlgProc,
                            FM3ModHandle,
                            ASEL_FRAME,
                            (PVOID)&ad.info) ||
                            !ad.info) { /* we blew it */
                FreeList(list);
                break;
              }
              if(!ad.info->create &&
                 !ad.info->move &&
                 !ad.info->createwdirs &&
                 !ad.info->movewdirs &&
                 !ad.info->createrecurse) {
                FreeList(list);
                break;
              }
              if(!WinDlgBox(HWND_DESKTOP,
                            hwndFrame,
                            ArchiveDlgProc,
                            FM3ModHandle,
                            ARCH_FRAME,
                            (PVOID)&ad) ||
                            !*ad.arcname ||
                            !*ad.command) { /* we blew it */
                FreeList(list);
                break;
              }
              /* build the sucker */
              strcpy(szBuffer,ad.command);
              strcat(szBuffer," ");
              strcat(szBuffer,ad.arcname);
              p = &szBuffer[strlen(szBuffer)];
              if(ad.mask.szMask) {
                strcat(szBuffer," ");
                strcat(szBuffer,ad.mask.szMask);
              }
              strcat(szBuffer," ");
              x = 0;
              while(list[x]) {

                FILESTATUS3 fsa;
                BOOL        spaces;

                if(needs_quoting(list[x])) {
                  spaces = TRUE;
                  strcat(szBuffer,"\"");
                }
                else
                  spaces = FALSE;
                strcat(szBuffer,list[x]);
                memset(&fsa,0,sizeof(FILESTATUS3));
                DosError(FERR_DISABLEHARDERR);
                DosQueryPathInfo(list[x],FIL_STANDARD,
                                 &fsa,
                                 (ULONG)sizeof(FILESTATUS3));
                if(fsa.attrFile & FILE_DIRECTORY) {
                  if(szBuffer[strlen(szBuffer) - 1] != '\\')
                    strcat(szBuffer,"\\");
                  strcat(szBuffer,"*");
                }
                if(spaces)
                  strcat(szBuffer,"\"");
                x++;
                if(!list[x] || strlen(szBuffer) +
                   strlen(list[x]) + 5 > 1024) {
                  runemf2(SEPARATE | WINDOWED |
                          ((fArcStuffVisible) ? 0 :
                            (BACKGROUND | MINIMIZED)) |
                          WAIT,
                          HWND_DESKTOP,
                          NULL,
                          NULL,
                          "%s",
                          szBuffer);
                  DosSleep(1L);
                  *p = 0;
                }
                strcat(szBuffer," ");
              }
              AddToList(ad.arcname,
                        &files,
                        &numfiles,
                        &numalloc);
            }
            if(!PostMsg(WinWindowFromID(hwndFrame,FID_CLIENT),
                        UM_UPDATERECORDLIST,
                        MPFROMP(list),
                        MPVOID))
              FreeList(list);
            break;

          case IDM_ATTRS:
            {
              LISTINFO li;

              memset(&li,0,sizeof(li));
              li.list = list;
              if(WinDlgBox(HWND_DESKTOP,
                           hwndFrame,
                           AttrListDlgProc,
                           FM3ModHandle,
                           ATR_FRAME,
                           MPFROMP(&li))) {
                if(li.list && li.list[0]) {
                  if(!PostMsg(WinWindowFromID(hwndFrame,FID_CLIENT),
                              UM_UPDATERECORDLIST,
                              MPFROMP(li.list),
                              MPVOID))
                    FreeList(li.list);
                }
              }
              else
                FreeList(list);
            }
            break;

          case IDM_MOVE:
          case IDM_COPY:
            if(!*path)
              strcpy(path,targetdir);
            if(!*path)
              strcpy(path,list[0]);
            MakeValidDir(path);
RetryPath:
            if(SHORT1FROMMP(mp1) == IDM_MOVE) {
              if(!WinDlgBox(HWND_DESKTOP,
                            hwndFrame,
                            WalkMoveDlgProc,
                            FM3ModHandle,
                            WALK_FRAME,
                            MPFROMP(path)) ||
                 !*path) {
                FreeList(list);
                goto Abort;
              }
            }
            else {
              if(!WinDlgBox(HWND_DESKTOP,
                            hwndFrame,
                            WalkCopyDlgProc,
                            FM3ModHandle,
                            WALK_FRAME,
                            MPFROMP(path)) ||
                 !*path) {
                FreeList(list);
                goto Abort;
              }
            }
            if(driveflags[toupper(*path) - 'A'] & DRIVE_NOTWRITEABLE) {
              saymsg(MB_CANCEL,
                     hwndFrame,
                     GetPString(IDS_ERRORTEXT),
                     "%s",
                     GetPString(IDS_NOTWRITENOTARGETTEXT));
              goto RetryPath;
            }
            /* intentional fallthru */
          case IDM_RENAME:
            {
              CHAR        newname[CCHMAXPATH],*moving,*move,*moved;
              APIRET      rc;
              INT         type;
              FILESTATUS4 fs4;
              BOOL        isnewer,existed;

              for(x = 0;list[x];x++) {
Retry:
                type = (SHORT1FROMMP(mp1) == IDM_RENAME) ? MOVE :
                       (SHORT1FROMMP(mp1) == IDM_MOVE) ? MOVE :
                       (SHORT1FROMMP(mp1) == IDM_WPSMOVE) ? WPSMOVE :
                       (SHORT1FROMMP(mp1) == IDM_WPSCOPY) ? WPSCOPY :
                       COPY;
                moving = (SHORT1FROMMP(mp1) == IDM_RENAME) ?
                          GetPString(IDS_RENAMINGTEXT) :
                          (SHORT1FROMMP(mp1) == IDM_MOVE ||
                           SHORT1FROMMP(mp1) == IDM_WPSMOVE) ?
                           GetPString(IDS_MOVINGTEXT) :
                           GetPString(IDS_COPYINGTEXT);
                move = (SHORT1FROMMP(mp1) == IDM_RENAME) ?
                        GetPString(IDS_RENAMETEXT) :
                        (SHORT1FROMMP(mp1) == IDM_MOVE ||
                         SHORT1FROMMP(mp1) == IDM_WPSMOVE) ?
                         GetPString(IDS_MOVETEXT) :
                         GetPString(IDS_COPYTEXT);
                moved = (SHORT1FROMMP(mp1) == IDM_RENAME) ?
                         GetPString(IDS_RENAMEDTEXT) :
                         (SHORT1FROMMP(mp1) == IDM_MOVE ||
                          SHORT1FROMMP(mp1) == IDM_WPSMOVE) ?
                          GetPString(IDS_MOVEDTEXT) :
                          GetPString(IDS_COPIEDTEXT);
                if(*path) {
                  strcpy(newname,path);
                  if(newname[strlen(newname) - 1] != '\\')
                    strcat(newname,"\\");
                  if(plen)
                    p = list[x] + plen;
                  else {
                    p = strrchr(list[x],'\\');
                    if(p)
                      p++;
                    else
                      p = list[x];
                  }
                  strcat(newname,p);
                }
                else
                  strcpy(newname,list[x]);
                if((wildcarding ||
                    SHORT1FROMMP(mp1) == IDM_RENAME) &&
                   *wildname) {

                  CHAR testname[CCHMAXPATH];

                  strcpy(testname,wildname);
                  if(AdjustWildcardName(newname,testname))
                    strcpy(newname,testname);
                }
                existed = (IsFile(newname) != -1);
                isnewer = IsNewer(list[x],newname);
                if(existed &&
                   SHORT1FROMMP(mp1) != IDM_RENAME &&
                   dontask) {
                  if(!overold && !overnew)
                    break;
                  if(!overold && !isnewer)
                    break;
                  if(!overnew && isnewer)
                    break;
                }
                if((SHORT1FROMMP(mp1) == IDM_RENAME &&
                   (!dontask || !*wildname)) ||
                   (!dontask && existed) ||
                   (!dontask && wildcarding) ||
                   (IsFile(newname) == 0 && IsFile(list[x]) == 1)) {

                  MOVEIT mv;

                  memset(&mv,0,sizeof(MOVEIT));
                  mv.rename = (SHORT1FROMMP(mp1) == IDM_RENAME);
                  mv.source = list[x];
                  strcpy(mv.target,newname);
                  rc = WinDlgBox(HWND_DESKTOP,
                                 hwndFrame,
                                 RenameProc,
                                 FM3ModHandle,
                                 REN_FRAME,
                                 (PVOID)&mv);
                  if(!rc) {
                    FreeList(list);
                    goto Abort;
                  }
                  DosSleep(1L);
                  if(mv.skip || !*mv.target)
                    break;
                  if(mv.dontask)
                    dontask = TRUE;
                  if(mv.overold)
                    overold = TRUE;
                  if(mv.overnew)
                    overnew = TRUE;
                  if(wildcarding ||
                     SHORT1FROMMP(mp1) == IDM_RENAME) {
                    p = strrchr(mv.target,'\\');
                    if(p && (strchr(p,'*') || strchr(p,'?'))) {
                      strcpy(wildname,mv.target);
                      AdjustWildcardName(list[x],mv.target);
                    }
                    else
                      *wildname = 0;
                  }
                  strcpy(newname,mv.target);
                  existed = (IsFile(newname) != -1);
                  isnewer = IsNewer(list[x],newname);
                  if(!mv.overwrite) {
                    if(existed && SHORT1FROMMP(mp1) != IDM_RENAME &&
                       dontask) {
                      if(!overold && !overnew)
                        break;
                      if(!overold && !isnewer)
                        break;
                      if(!overnew && isnewer)
                        break;
                    }
                  }
                }
                if(!stricmp(list[x],newname))
                  break;
                sprintf(message,
                        " %s \"%s\" %s \"%s\"",
                        moving,
                        list[x],
                        GetPString(IDS_TOTEXT),
                        newname);
                WinSetWindowText(WinWindowFromID(hwndFrame,
                                                 SEEALL_STATUS),
                                 message);
                if(fRealIdle)
                  priority_idle();
                if(plen) {
                  /* make directory/ies, if required */

                  CHAR dirpart[CCHMAXPATH];

                  strcpy(dirpart,newname);
                  p = strrchr(dirpart,'\\');
                  if(p) {
                    *p = 0;
                    if(p > dirpart + 3)
                      MassMkdir((hwndMain) ? hwndMain : (HWND)0,
                                dirpart);
                  }
                }
                rc = docopyf(type,
                             list[x],
                             "%s",
                             newname);
                priority_normal();
                if(rc) {
                  if((rc == ERROR_DISK_FULL ||
                      rc == ERROR_HANDLE_DISK_FULL) &&
                     isalpha(*newname) &&
                     (driveflags[toupper(*newname) - 'A'] & DRIVE_REMOVABLE) &&
                     !(driveflags[toupper(*newname) - 'A'] & DRIVE_NOTWRITEABLE) &&
                     toupper(*newname) != toupper(*list[x]) &&
                     !DosQueryPathInfo(list[x],
                                       FIL_QUERYEASIZE,
                                       &fs4,
                                       sizeof(fs4)) &&
                     !(fs4.attrFile & FILE_DIRECTORY)) {

                    FSALLOCATE  fsa;
                    ULONG       totalsize;
                    CHAR       *ptr;
                    INT         cntr;

                    WinSetWindowText(WinWindowFromID(hwndFrame,SEEALL_STATUS),
                                     GetPString(IDS_FITTINGTEXT));
                    DosError(FERR_DISABLEHARDERR);
                    if(!DosQueryFSInfo(toupper(*newname) - '@',
                       FSIL_ALLOC,&fsa,sizeof(FSALLOCATE))) {
                      totalsize = fsa.cUnitAvail * fsa.cSectorUnit *
                                  fsa.cbSector;
                      if(totalsize) {
                        for(cntr = x + 1;list[cntr];cntr++) {
                          DosError(FERR_DISABLEHARDERR);
                          if(!DosQueryPathInfo(list[cntr],
                                               FIL_QUERYEASIZE,
                                               &fs4,sizeof(fs4)) &&
                             !(fs4.attrFile & FILE_DIRECTORY) &&
                             fs4.cbFile + fs4.cbList <= totalsize) {
                            ptr = list[x];
                            list[x] = list[cntr];
                            list[cntr] = ptr;
                            goto Retry;
                          }
                        }
                        WinSetWindowText(WinWindowFromID(hwndFrame,
                                                         SEEALL_STATUS),
                                         GetPString(IDS_COULDNTFITTEXT));
                      }
                    }
                    rc = saymsg(MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION,
                                hwndFrame,
                                GetPString(IDS_DISKFULLTEXT),
                                "%s",
                                GetPString(IDS_ANOTHERDISKTEXT));
                    if(rc == MBID_RETRY)
                      goto Retry;
                    if(rc == MBID_ABORT) {
                      FreeList(list);
                      goto Abort;
                    }
                  }
                  else {
                    if(LogFileHandle)
                      fprintf(LogFileHandle,
                              GetPString(IDS_LOGTOFAILEDTEXT),
                              move,
                              list[x],
                              newname,
                              rc);
                    rc = Dos_Error(MB_ENTERCANCEL,
                                   rc,
                                   hwndFrame,
                                   __FILE__,
                                   __LINE__,
                                   "%s %s \"%s\" %s\"%s\" %s.",
                                   move,
                                   GetPString(IDS_OFTEXT),
                                   list[x],
                                   GetPString(IDS_TOTEXT),
                                   newname,
                                   GetPString(IDS_FAILEDTEXT));
                    if(rc == MBID_CANCEL) {
                      FreeList(list);
                      goto Abort;
                    }
                  }
                }
                else {
                  if(LogFileHandle)
                    fprintf(LogFileHandle,
                            "%s \"%s\" %s \"%s\"\n",
                            moved,
                            list[x],
                            GetPString(IDS_TOTEXT),
                            newname);
                  AddToList(newname,
                            &files,
                            &numfiles,
                            &numalloc);
                }
              }
            }
            if(SHORT1FROMMP(mp1) != IDM_COPY) {
              if(!PostMsg(WinWindowFromID(hwndFrame,FID_CLIENT),
                          UM_UPDATERECORDLIST,
                          MPFROMP(list),
                          MPVOID))
                FreeList(list);
            }
            else
              FreeList(list);
            break;

          case IDM_UUDECODE:
            for(x = 0;list[x];x++)
              UUD(list[x],NULL);
            break;

          case IDM_EXTRACT:
            for(x = 0;list[x];x++) {

              EXTRDATA ex;
              BOOL     maskspaces = FALSE;

              memset(&ex,0,sizeof(EXTRDATA));
              ex.info = find_type(list[x],NULL);
              if(!ex.info || (!ex.info->extract &&
                              !ex.info->exwdirs))
                break;
              ex.size = sizeof(EXTRDATA);
              ex.arcname = list[x];
              strcpy(ex.masks,"*");
              if(!WinDlgBox(HWND_DESKTOP,
                            hwndFrame,
                            ExtractDlgProc,
                            FM3ModHandle,
                            EXT_FRAME,
                            (PVOID)&ex) ||
                 !ex.ret ||
                 !*ex.command ||
                 !*ex.arcname ||
                 !*ex.extractdir)
                break;
              if(!IsFile(ex.extractdir)) {
                if(needs_quoting(ex.masks) &&
                   !strchr(ex.masks,'\"') )
                  maskspaces = TRUE;
                runemf2(SEPARATE | WINDOWED |
                        ((fArcStuffVisible) ? 0 :
                         (BACKGROUND | MINIMIZED)),
                        HWND_DESKTOP,
                        ex.extractdir,
                        NULL,
                        "%s %s %s%s%s",
                        ex.command,
                        ex.arcname,
                        (maskspaces) ? "\"" : NullStr,
                        (*ex.masks) ? ex.masks : "*",
                        (maskspaces) ? "\"" : NullStr);
              }
              else
                DosBeep(50,100);
            }
            if(!PostMsg(WinWindowFromID(hwndFrame,FID_CLIENT),
                        UM_UPDATERECORDLIST,
                        MPFROMP(list),
                        MPVOID))
              FreeList(list);
            break;

          case IDM_SUBJECT:
            for(x = 0;list[x];x++) {

              INT ret;

              if(IsFile(list[x]) == 1) {
                ret = Subject(hwndFrame,list[x]);
                if(!ret)
                  break;
              }
            }
            if(!PostMsg(WinWindowFromID(hwndFrame,FID_CLIENT),
                        UM_UPDATERECORDLIST,
                        MPFROMP(list),
                        MPVOID))
              FreeList(list);
            break;

          case IDM_OPENDEFAULT:
          case IDM_OPENSETTINGS:
            for(x = 0;list[x];x++) {
              if(IsFile(list[x]) != -1) {

                CHAR *s;

                switch(SHORT1FROMMP(mp1)) {
                  case IDM_OPENSETTINGS:
                    s = Settings;
                    break;
                  default:
                    s = Default;
                    break;
                }
                OpenObject(list[x],
                           s,
                           hwndFrame);
              }
            }
            FreeList(list);
            break;

          case IDM_DELETE:
          case IDM_PERMDELETE:
            {
              CHECKLIST    cl;
              INT          isdir = 0,sysdir = 0,ro = 0,hs = 0;
              FILESTATUS3  fsa;
              CHAR         prompt[CCHMAXPATH * 3];
              APIRET       error;

              for(x = 0;list[x];x++) {
                if(IsRoot(list[x])) {
                  list = RemoveFromList(list,list[x]);
                  if(!list)
                    break;
                  x--;
                  continue;
                }
                DosError(FERR_DISABLEHARDERR);
                if(DosQueryPathInfo(list[x],
                                    FIL_STANDARD,
                                    &fsa,
                                    (ULONG)sizeof(FILESTATUS3))) {
                  list = RemoveFromList(list,list[x]);
                  if(!list)
                    break;
                  x--;
                  continue;
                }
                if(fsa.attrFile & FILE_DIRECTORY) {
                  isdir++;
                  if(stristr(list[x],":\\OS2\\") ||
                     !stricmp(list[x] + 1,":\\OS2"))
                    sysdir++;
                }
                else {
                  if(fsa.attrFile & (FILE_HIDDEN | FILE_SYSTEM))
                    hs++;
                  if(fsa.attrFile & FILE_READONLY)
                    ro++;
                }
              }
              if(!list)
                break;
              if(fConfirmDelete || isdir) {
                memset(&cl,0,sizeof(cl));
                cl.size = sizeof(cl);
                cl.list = list;
                cl.prompt = prompt;
                cl.flags |= CHECK_FILES;
                cl.cmd = SHORT1FROMMP(mp1);
                sprintf(prompt,
                        GetPString(IDS_DELPROMPT1TEXT),
                        (SHORT1FROMMP(mp1) == IDM_DELETE) ?
                         NullStr :
                         GetPString(IDS_PERMANENTLYTEXT),
                         &"s"[list[1] == NULL]);
                if(isdir) {
                  sprintf(&prompt[strlen(prompt)],
                          GetPString(IDS_DELPROMPT2TEXT),
                          isdir,
                          (isdir > 1) ?
                           GetPString(IDS_ARETEXT) :
                           GetPString(IDS_ISTEXT),
                          (isdir == 1) ?
                           GetPString(IDS_ATEXT) :
                           NullStr,
                          (isdir > 1) ?
                           GetPString(IDS_IESTEXT) :
                           GetPString(IDS_YTEXT));
                  if(sysdir)
                    sprintf(&prompt[strlen(prompt)],
                            GetPString(IDS_DELPROMPT3TEXT),
                            sysdir,
                            (sysdir == 1) ?
                             GetPString(IDS_YTEXT) :
                             GetPString(IDS_IESTEXT));
                }
                if(ro)
                  sprintf(&prompt[strlen(prompt)],
                          GetPString(IDS_DELPROMPT4TEXT),
                          ro,
                          &"s"[ro == 1],
                          (ro > 1) ?
                           GetPString(IDS_ARETEXT) :
                           GetPString(IDS_ISTEXT));
                if(hs)
                  sprintf(&prompt[strlen(prompt)],
                          GetPString(IDS_DELPROMPT5TEXT),
                          hs,
                          &"s"[hs == 1],
                          (hs > 1) ?
                           GetPString(IDS_ARETEXT) :
                           GetPString(IDS_ISTEXT));
                if(ro || hs || sysdir)
                  DosBeep(300,100);
                strcat(prompt,
                       GetPString(IDS_DELPROMPT6TEXT));
                if(!WinDlgBox(HWND_DESKTOP,
                              WinWindowFromID(hwndFrame,FID_CLIENT),
                              CheckListProc,
                              FM3ModHandle,
                              CHECK_FRAME,
                              MPFROMP(&cl)))
                  break;
                list = cl.list;
                if(!list || !list[0])
                  break;
              }
              for(x = 0;list[x];x++) {
                fsa.attrFile = 0;
                DosError(FERR_DISABLEHARDERR);
                DosQueryPathInfo(list[x],
                                 FIL_STANDARD,
                                 &fsa,
                                 (ULONG)sizeof(FILESTATUS3));
                if(fsa.attrFile & FILE_DIRECTORY) {
                  sprintf(prompt,
                          GetPString(IDS_DELETINGTEXT),
                          list[x]);
                  WinSetWindowText(WinWindowFromID(hwndFrame,SEEALL_STATUS),
                                   prompt);
                  error = (APIRET)wipeallf("%s%s*",
                                           list[x],
                                           (*list[x] &&
                                            list[x][strlen(list[x]) - 1] != '\\') ?
                                             "\\" : NullStr);
                  DosError(FERR_DISABLEHARDERR);
                  if(!error)
                    error = DosDeleteDir(list[x]);
                  else
                    DosDeleteDir(list[x]);
                }
                else {
                  DosError(FERR_DISABLEHARDERR);
                  if(SHORT1FROMMP(mp1) == IDM_DELETE)
                    error = DosDelete(list[x]);
                  else
                    error = DosForceDelete(list[x]);
                  if(error) {
                    DosError(FERR_DISABLEHARDERR);
                    make_deleteable(list[x]);
                    if(SHORT1FROMMP(mp1) == IDM_DELETE)
                      error = DosDelete(list[x]);
                    else
                      error = DosForceDelete(list[x]);
                  }
                }
                if(error) {
                  if(LogFileHandle)
                    fprintf(LogFileHandle,
                            GetPString(IDS_DELETEFAILED1TEXT),
                            list[x],
                            error);
                  if(Dos_Error(MB_ENTERCANCEL,
                               error,
                               hwndFrame,
                               __FILE__,
                               __LINE__,
                               GetPString(IDS_DELETEFAILED2TEXT),
                               list[x]) ==
                     MBID_CANCEL)
                    break;
                }
                else
                  if(LogFileHandle)
                    fprintf(LogFileHandle,
                            "%s\n",
                            GetPString(IDS_DELETEDTEXT),
                            list[x]);
                AddToList(list[x],
                          &files,
                          &numfiles,
                          &numalloc);
              }
            }
            FreeList(list);
            break;

          case IDM_SAVETOLIST:
            if(list) {
              WinDlgBox(HWND_DESKTOP,
                        WinWindowFromID(hwndFrame,FID_CLIENT),
                        SaveAllListDlgProc,
                        FM3ModHandle,
                        SAV_FRAME,
                        MPFROMP(list));
              FreeList(list);
            }
            break;

          case IDM_SAVETOCLIP:
          case IDM_APPENDTOCLIP:
            if(list) {
              ListToClipboardHab(WinQueryAnchorBlock(hwnd),
                                 list,
                                 (SHORT1FROMMP(mp1) == IDM_APPENDTOCLIP));
              FreeList(list);
            }
            break;

          default:
            if(list)
              FreeList(list);
            break;
        }

        switch(SHORT1FROMMP(mp1)) {
          case IDM_MOVE:
          case IDM_COPY:
          case IDM_RENAME:
            sprintf(message,
                    GetPString(IDS_OPSCOMPLETETEXT),
                    (SHORT1FROMMP(mp1) == IDM_MOVE) ?
                     GetPString(IDS_MOVETEXT) :
                     (SHORT1FROMMP(mp1) == IDM_COPY) ?
                      GetPString(IDS_COPYTEXT) :
                      (SHORT1FROMMP(mp1) == IDM_WPSMOVE) ?
                       GetPString(IDS_WPSMOVETEXT) :
                       (SHORT1FROMMP(mp1) == IDM_WPSCOPY) ?
                        GetPString(IDS_WPSCOPYTEXT) :
                        GetPString(IDS_RENAMETEXT),
                    &"s"[x == 1],
                    (SHORT1FROMMP(mp1) == IDM_MOVE ||
                     SHORT1FROMMP(mp1) == IDM_COPY ||
                     SHORT1FROMMP(mp1) == IDM_WPSMOVE ||
                     SHORT1FROMMP(mp1) == IDM_WPSCOPY) ?
                      GetPString(IDS_TOTEXT) :
                      NullStr,
                    (SHORT1FROMMP(mp1) == IDM_MOVE ||
                     SHORT1FROMMP(mp1) == IDM_COPY ||
                     SHORT1FROMMP(mp1) == IDM_WPSMOVE ||
                     SHORT1FROMMP(mp1) == IDM_WPSCOPY) ?
                     path :
                     NullStr,
                    (x != 1) ?
                     GetPString(IDS_ARETEXT) :
                     GetPString(IDS_ISTEXT));
            WinSetWindowText(WinWindowFromID(hwndFrame,SEEALL_STATUS),
                             message);
            if(toupper(*path) < 'C')
              DosBeep(1000,25);
            DosSleep(33L);
            break;

          default:
            break;
        }
Abort:
        if(files) {
          if(!PostMsg(WinWindowFromID(hwndFrame,FID_CLIENT),
                      UM_UPDATERECORDLIST,
                      MPFROMP(files),
                      MPVOID))
            FreeList(files);
        }
        PostMsg(WinWindowFromID(hwndFrame,FID_CLIENT),
                UM_RESCAN,
                MPVOID,
                MPVOID);
      }
      return 0;

    case WM_CLOSE:
      WinDestroyWindow(hwnd);
      break;

    case WM_DESTROY:
      if(!PostMsg((HWND)0,
                  WM_QUIT,
                  MPVOID,
                  MPVOID))
        WinSendMsg((HWND)0,
                   WM_QUIT,
                   MPVOID,
                   MPVOID);
      break;
  }
  return WinDefWindowProc(hwnd,msg,mp1,mp2);
}


static VOID MakeSeeObj (VOID *args) {

  HAB      hab2;
  HMQ      hmq2;
  HWND     hwndObj;
  ALLDATA *ad = (ALLDATA *)args;
  QMSG     qmsg2;

  if(ad) {
    hab2 = WinInitialize(0);
    if(hab2) {
      hmq2 = WinCreateMsgQueue(hab2,256);
      if(hmq2) {
        DosError(FERR_DISABLEHARDERR);
        WinRegisterClass(hab2,
                         GetPString(IDS_WCOBJECTWINDOW),
                         SeeObjWndProc,
                         0,
                         sizeof(PVOID));
        hwndObj = WinCreateWindow(HWND_OBJECT,
                                  GetPString(IDS_WCOBJECTWINDOW),
                                  (PSZ)NULL,
                                  0,
                                  0L,
                                  0L,
                                  0L,
                                  0L,
                                  0L,
                                  HWND_TOP,
                                  SEEALL_OBJ,
                                  NULL,
                                  NULL);
        if(hwndObj) {
          ad->hwndObj = hwndObj;
          WinSetWindowULong(hwndObj,0,ad->hwndFrame);
          priority_normal();
          while(WinGetMsg(hab2,&qmsg2,(HWND)0,0,0))
            WinDispatchMsg(hab2,&qmsg2);
          WinDestroyWindow(hwndObj);
        }
        else {
          if(!PostMsg(ad->hwndClient,WM_CLOSE,MPVOID,MPVOID))
            WinSendMsg(ad->hwndClient,WM_CLOSE,MPVOID,MPVOID);
        }
        WinDestroyMsgQueue(hmq2);
      }
      else
        WinTerminate(hab2);
    }
  }
}


static VOID SelectMask (HWND hwnd,BOOL deselect) {

  MASK           mask;
  register ULONG x,y,z;
  BOOL           ret;
  ALLDATA       *ad = WinQueryWindowPtr(hwnd,0);

  memset(&mask,0,sizeof(MASK));
  mask.fNoAttribs = FALSE;
  mask.fNoDirs = TRUE;
  mask.attrFile = ad->mask.attrFile;
  mask.antiattr = ad->mask.antiattr;
  mask.fIsSeeAll = TRUE;
  strcpy(mask.prompt,
         GetPString((!deselect) ?
                    IDS_SELECTFILTERTEXT :
                    IDS_DESELECTFILTERTEXT));
  if(WinDlgBox(HWND_DESKTOP,
               hwnd,
               PickMaskDlgProc,
               FM3ModHandle,
               MSK_FRAME,
               MPFROMP(&mask)) &&
     (*mask.szMask ||
      mask.attrFile != ad->mask.attrFile ||
      mask.antiattr != ad->mask.antiattr)) {
    for(x = 0;x < ad->afifiles;x++) {
      y = (ad->invertsort) ? (ad->afifiles - 1) - x : x;
      ret = FALSE;
      if(mask.pszMasks[1]) {
        for(z = 0;mask.pszMasks[z];z++) {
          if(*mask.pszMasks[z]) {
            if(*mask.pszMasks[z] != '/') {
              if(wildcard((strchr(mask.pszMasks[z],'\\') ||
                           strchr(mask.pszMasks[z],':')) ?
                           ad->afindex[y]->fullname : ad->afindex[y]->filename,
                           mask.pszMasks[z],FALSE))
                ret = TRUE;
            }
            else {
              if(wildcard((strchr(mask.pszMasks[z],'\\') ||
                           strchr(mask.pszMasks[z],':')) ?
                           ad->afindex[y]->fullname : ad->afindex[y]->filename,
                           mask.pszMasks[y] + 1,FALSE)) {
                ret = FALSE;
                break;
              }
            }
          }
        }
      }
      else if(*mask.szMask) {
        if(wildcard((strchr(mask.szMask,'\\') ||
                     strchr(mask.szMask,':')) ?
                     ad->afindex[y]->fullname : ad->afindex[y]->filename,
                     mask.szMask,FALSE))
          ret = TRUE;
      }
      else
        ret = TRUE;
      if(ret) {
        if((!(mask.attrFile & FILE_HIDDEN) && (ad->afindex[y]->attrFile & FILE_HIDDEN)) ||
           (!(mask.attrFile & FILE_SYSTEM) && (ad->afindex[y]->attrFile & FILE_SYSTEM)) ||
           (!(mask.attrFile & FILE_READONLY) && (ad->afindex[y]->attrFile & FILE_READONLY)) ||
           (!(mask.attrFile & FILE_ARCHIVED) && (ad->afindex[y]->attrFile & FILE_ARCHIVED)))
          ret = FALSE;
        else if(((mask.antiattr & FILE_HIDDEN) && !(ad->afindex[y]->attrFile & FILE_HIDDEN)) ||
                ((mask.antiattr & FILE_SYSTEM) && !(ad->afindex[y]->attrFile & FILE_SYSTEM)) ||
                ((mask.antiattr & FILE_READONLY) && !(ad->afindex[y]->attrFile & FILE_READONLY)) ||
                ((mask.antiattr & FILE_ARCHIVED) && !(ad->afindex[y]->attrFile & FILE_ARCHIVED)))
         ret = FALSE;
      }
      if(ret) {
        if(deselect) {
          if(ad->afindex[y]->flags & AF_SELECTED) {
            ad->selected--;
            ad->selbytes -= ad->afindex[y]->cbFile;
          }
          ad->afindex[y]->flags &= (~AF_SELECTED);
        }
        else {
          if(!(ad->afindex[y]->flags & AF_SELECTED)) {
            ad->selected++;
            ad->selbytes += ad->afindex[y]->cbFile;
          }
          ad->afindex[y]->flags |= AF_SELECTED;
        }
      }
    }
  }
}


static VOID CollectList (HWND hwnd,CHAR **list) {

  if(!Collector) {
    if(hwndMain && !fExternalCollector && !strcmp(realappname,FM3Str)) {

      HWND hwndC;
      SWP  swp;

      if(!fAutoTile)
        GetNextWindowPos(hwndMain,&swp,NULL,NULL);
      hwndC = StartCollector(hwndMain,4);
      if(hwndC) {
        if(!fAutoTile)
          WinSetWindowPos(hwndC,HWND_TOP,swp.x,swp.y,
                          swp.cx,swp.cy,SWP_MOVE | SWP_SIZE |
                          SWP_SHOW | SWP_ZORDER);
        else
          TileChildren(hwndMain,TRUE);
        WinSetWindowPos(hwndC,HWND_TOP,0,0,0,0,SWP_ACTIVATE);
        DosSleep(250L);
      }
    }
    else {
      StartCollector(HWND_DESKTOP,4);
      DosSleep(250L);
    }
  }
  if(!PostMsg(hwnd,WM_COMMAND,MPFROM2SHORT(IDM_COLLECTOR,0),
                 MPFROMP(list)))
    FreeList(list);
}


static VOID FreeAllFilesList (HWND hwnd) {

  ALLDATA       *ad = WinQueryWindowPtr(hwnd,0);
  register ULONG x;

  if(ad->afhead && ad->affiles) {
    for(x = 0L;x < ad->affiles;x++) {
      if(ad->afhead[x].fullname)
        free(ad->afhead[x].fullname);
    }
    free(ad->afhead);
    ad->afhead = NULL;
    if(ad->afindex)
      free(ad->afindex);
    ad->afindex = NULL;
  }
  DosPostEventSem(CompactSem);
  ad->afalloc = ad->afifiles = ad->affiles = ad->longest = ad->longestw =
    ad->maxx = ad->horzscroll = 0;
}


static CHAR ** BuildAList (HWND hwnd) {

  ALLDATA       *ad = WinQueryWindowPtr(hwnd,0);
  register ULONG x,y,z = 0;
  CHAR         **list = NULL;
  INT            numfiles = 0,numalloc = 0,error;

  if(ad->selected) {
    for(x = 0;x < ad->afifiles;x++) {
      y = (ad->invertsort) ? (ad->afifiles - 1) - x : x;
      if(ad->afindex[y]->flags & AF_SELECTED) {
        error = AddToList(ad->afindex[y]->fullname,&list,
                          &numfiles,&numalloc);
        if(error)
          break;
        z++;
        if(z >= ad->selected)
          break;
      }
    }
  }
  return list;
}


static BOOL Mark (HWND hwnd,INT command,CHAR **list) {

  /* Marks only unfiltered files */

  ALLDATA       *ad = WinQueryWindowPtr(hwnd,0);
  register ULONG x,y,z;
  BOOL           ret = TRUE,didone = FALSE;

  for(x = 0;x < ad->afifiles;x++) {
    y = (ad->invertsort) ? (ad->afifiles - 1) - x : x;
    if(list) {
      ret = FALSE;
      for(z = 0;list[z];z++) {
        if(!stricmp(list[z],ad->afindex[y]->fullname)) {
          ret = TRUE;
          break;
        }
      }
    }
    if(ret) {
      didone = TRUE;
      if(command == AFM_UNMARK) {
        if(ad->afindex[y]->flags & AF_SELECTED) {
          ad->selected--;
          ad->selbytes -= ad->afindex[y]->cbFile;
        }
        ad->afindex[y]->flags &= (~AF_SELECTED);
      }
      else if(command == AFM_MARK) {
        if(!(ad->afindex[y]->flags & AF_SELECTED)) {
          ad->selected++;
          ad->selbytes += ad->afindex[y]->cbFile;
        }
        ad->afindex[y]->flags |= AF_SELECTED;
      }
      else if(command == AFM_INVERT) {
        if(ad->afindex[y]->flags & AF_SELECTED) {
          ad->selected--;
          ad->selbytes -= ad->afindex[y]->cbFile;
          ad->afindex[y]->flags &= (~AF_SELECTED);
        }
        else {
          ad->selected++;
          ad->selbytes += ad->afindex[y]->cbFile;
          ad->afindex[y]->flags |= AF_SELECTED;
        }
      }
      else if(command == AFM_MARKDELETED) {
        if(ad->afindex[y]->flags & AF_SELECTED)
          ad->afindex[y]->flags |= AF_DELETED;
      }
      else if(command == AFM_FILTER) {
        if(ad->afindex[y]->flags & AF_SELECTED)
          ad->afindex[y]->flags |= AF_FILTERED;
      }
    }
  }
  return didone;
}


static BOOL MarkList (HWND hwnd,INT command,CHAR **list) {

  /* Marks files whether filtered or not */

  ALLDATA       *ad = WinQueryWindowPtr(hwnd,0);
  register ULONG x,z;
  BOOL           ret = TRUE,didone = FALSE;

  for(x = 0;x < ad->affiles;x++) {
    if(list) {
      ret = FALSE;
      for(z = 0;list[z];z++) {
        if(!stricmp(list[z],ad->afhead[x].fullname)) {
          ret = TRUE;
          break;
        }
      }
    }
    if(ret) {
      didone = TRUE;
      if(command == AFM_UNMARK) {
        if(ad->afhead[x].flags & AF_SELECTED) {
          ad->selected--;
          ad->selbytes -= ad->afhead[x].cbFile;
        }
        ad->afhead[x].flags &= (~AF_SELECTED);
      }
      else if(command == AFM_MARK) {
        if(!(ad->afhead[x].flags & AF_SELECTED)) {
          ad->selected++;
          ad->selbytes += ad->afhead[x].cbFile;
        }
        ad->afhead[x].flags |= AF_SELECTED;
      }
      else if(command == AFM_INVERT) {
        if(ad->afhead[x].flags & AF_SELECTED) {
          ad->selected--;
          ad->selbytes -= ad->afhead[x].cbFile;
          ad->afhead[x].flags &= (~AF_SELECTED);
        }
        else {
          ad->selected++;
          ad->selbytes += ad->afhead[x].cbFile;
          ad->afhead[x].flags |= AF_SELECTED;
        }
      }
      else if(command == AFM_MARKDELETED) {
        if(ad->afhead[x].flags & AF_SELECTED)
          ad->afhead[x].flags |= AF_DELETED;
      }
      else if(command == AFM_FILTER) {
        if(ad->afhead[x].flags & AF_SELECTED)
          ad->afhead[x].flags |= AF_FILTERED;
      }
    }
  }
  return didone;
}


static BOOL UpdateList (HWND hwnd,CHAR **list) {

  /* Updates files in the list */

  ALLDATA       *ad = WinQueryWindowPtr(hwnd,0);
  register ULONG x,z;
  BOOL           ret,didone = FALSE;
  FILEFINDBUF3   ffb;
  ULONG          nm;
  HDIR           hdir;
  CHAR          *p;

  if(list) {
    for(z = 0;list[z] && !ad->stopflag;z++) {
      ret = FALSE;
      for(x = 0;x < ad->affiles;x++) {
        if(!stricmp(list[z],ad->afhead[x].fullname)) {
          ret = TRUE;
          break;
        }
      }
      if(ret) {
        didone = TRUE;
        hdir = HDIR_CREATE;
        nm = 1L;
        if(!DosFindFirst(list[z],&hdir,FILE_NORMAL | FILE_ARCHIVED |
                         FILE_DIRECTORY | FILE_READONLY | FILE_SYSTEM |
                         FILE_HIDDEN,&ffb,sizeof(ffb),&nm,FIL_STANDARD)) {
          DosFindClose(hdir);
          if(!(ffb.attrFile & FILE_DIRECTORY)) {
            ad->afhead[x].attrFile = (USHORT)ffb.attrFile;
            ad->afhead[x].cbFile = ffb.cbFile;
            ad->afhead[x].date = ffb.fdateLastWrite;
            ad->afhead[x].time = ffb.ftimeLastWrite;
          }
          else
            ad->afhead[x].flags |= AF_DELETED;
        }
        else
          ad->afhead[x].flags |= AF_DELETED;
      }
      else if(isalpha(*list[z]) && ad->drvsflags[toupper(*list[z]) - 'A']) {
        didone = TRUE;
        hdir = HDIR_CREATE;
        nm = 1L;
        if(!DosFindFirst(list[z],&hdir,FILE_NORMAL | FILE_ARCHIVED |
                         FILE_DIRECTORY | FILE_READONLY | FILE_SYSTEM |
                         FILE_HIDDEN,&ffb,sizeof(ffb),&nm,FIL_STANDARD)) {
          DosFindClose(hdir);
          if(!(ffb.attrFile & FILE_DIRECTORY)) {
            if(!ad->afalloc || ad->affiles > ad->afalloc - 1) {

              ALLFILES *temp,**templ;

              temp = realloc(ad->afhead,(ad->afalloc + 1) *
                             sizeof(ALLFILES));
              if(temp) {
                ad->afhead = temp;
                templ = realloc(ad->afindex,(ad->afalloc + 1) *
                                sizeof(ALLFILES *));
                if(templ)
                  ad->afindex = templ;
                else {
// saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"Realloc failed.");
                  ad->stopflag = 1;
                  break;
                }
                ad->afalloc++;
              }
              else {
// saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"Realloc failed.");
                ad->stopflag = 1;
                break;
              }
            }
            ad->afhead[ad->affiles].fullname   = strdup(list[z]);
            if(ad->afhead[ad->affiles].fullname) {
              p = strrchr(ad->afhead[ad->affiles].fullname,'\\');
              if(!p)
                p = ad->afhead[ad->affiles].fullname;
              else
                p++;
              ad->afhead[ad->affiles].filename = p;
              ad->afhead[ad->affiles].cbFile   = ffb.cbFile;
              ad->afhead[ad->affiles].date     = ffb.fdateLastWrite;
              ad->afhead[ad->affiles].time     = ffb.ftimeLastWrite;
              ad->afhead[ad->affiles].attrFile = (USHORT)ffb.attrFile;
              ad->afhead[ad->affiles].flags    = 0;
              if(ad->longest < strlen(ad->afhead[ad->affiles].filename))
                ad->longest = strlen(ad->afhead[ad->affiles].filename);
              if(ad->longestw < strlen(ad->afhead[ad->affiles].fullname))
                ad->longestw = strlen(ad->afhead[ad->affiles].fullname);

              ad->affiles++;
            }
            else {
// saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"Strdup failed.");
              ad->stopflag = 1;
              break;
            }
          }
        }
      }
    }
  }
  return didone;
}


static int comparefullnames (const void *v1,const void *v2) {

  ALLFILES *d1 = *(ALLFILES **)v1;
  ALLFILES *d2 = *(ALLFILES **)v2;
  int       ret;

  ret = stricmp(d1->fullname,d2->fullname);
  return ret;
}


static int comparenames (const void *v1,const void *v2) {

  ALLFILES *d1 = *(ALLFILES **)v1;
  ALLFILES *d2 = *(ALLFILES **)v2;
  int       ret;

  ret = stricmp(d1->filename,d2->filename);
  if(!ret)
    ret = comparefullnames(v1,v2);
  return ret;
}


static int compareexts (const void *v1,const void *v2) {

  ALLFILES *d1 = *(ALLFILES **)v1;
  ALLFILES *d2 = *(ALLFILES **)v2;
  register CHAR *p1,*p2;
  int            ret;

  p1 = strrchr(d1->filename,'.');
  p2 = strrchr(d2->filename,'.');
  if(!p1)
    p1 = NullStr;
  else
    p1++;
  if(!p2)
    p2 = NullStr;
  else
    p2++;
  ret = stricmp(p1,p2);
  if(!ret)
    ret = comparenames(v1,v2);
  return ret;
}


static int comparesizes (const void *v1,const void *v2) {

  ALLFILES *d1 = *(ALLFILES **)v1;
  ALLFILES *d2 = *(ALLFILES **)v2;
  int       ret;

  ret = (d1->cbFile > d2->cbFile) ? 1 : (d1->cbFile == d2->cbFile) ? 0 : -1;
  if(!ret)
    ret = comparenames(v1,v2);
  return ret;
}


static int comparedates (const void *v1,const void *v2) {

  ALLFILES *d1 = *(ALLFILES **)v1;
  ALLFILES *d2 = *(ALLFILES **)v2;
  int ret;

  ret = (d1->date.year > d2->date.year) ? 1 :
        (d1->date.year < d2->date.year) ? -1 :
         (d1->date.month > d2->date.month) ? 1 :
         (d1->date.month < d2->date.month) ? -1 :
          (d1->date.day > d2->date.day) ? 1 :
          (d1->date.day < d2->date.day) ? -1 :
           (d1->time.hours > d2->time.hours) ? 1 :
           (d1->time.hours < d2->time.hours) ? -1 :
            (d1->time.minutes > d2->time.minutes) ? 1 :
            (d1->time.minutes < d2->time.minutes) ? -1 :
             (d1->time.twosecs > d2->time.twosecs) ? 1 :
             (d1->time.twosecs < d2->time.twosecs) ? -1 : 0;

  if(!ret)
    ret = comparenames(v1,v2);
  return ret;
}


static VOID ReSort (HWND hwnd) {

  ALLDATA       *ad = WinQueryWindowPtr(hwnd,0);
  register ULONG x,y;

  ad->selected = ad->selbytes = 0;
  for(x = 0,y = 0;x < ad->affiles;x++) {
    if(!(ad->afhead[x].flags & (AF_DELETED | AF_FILTERED))) {
      if(ad->afhead[x].flags & AF_SELECTED) {
        ad->selected++;
        ad->selbytes += ad->afhead[x].cbFile;
      }
      ad->afindex[y++] = &(ad->afhead[x]);
    }
  }
  ad->afifiles = y;
  PostMsg(hwnd,UM_SETUP3,MPVOID,MPVOID);
  if(!ad->stopflag && ad->compare && ad->afifiles) {
    WinSendMsg(hwnd,UM_RESCAN,MPFROMLONG(1L),MPVOID);
    qsort(ad->afindex,ad->afifiles,sizeof(ALLFILES *),ad->compare);
  }
}


VOID FindDupes (VOID *args) {

  register ULONG x,z;
  register CHAR *px,*pz;
  CHAR           s[80];
  INT            error;
  HWND           hwnd = (HWND)args;
  HAB            hab2 = (HAB)0;
  HMQ            hmq2 = (HMQ)0;
  ALLDATA       *ad = WinQueryWindowPtr(hwnd,0);

  if(!DosRequestMutexSem(ad->ScanSem,SEM_INDEFINITE_WAIT)) {
    priority_normal();
    hab2 = WinInitialize(0);
    if(hab2) {
      hmq2 = WinCreateMsgQueue(hab2,0);
      if(hmq2) {
        WinCancelShutdown(hmq2,TRUE);
        if(ad->cursored <= ad->afifiles) {
          for(x = 0;x < ad->affiles;x++)
            ad->afhead[x].flags &= (~(AF_DUPE | AF_SELECTED));
          DosSleep(1L);
          for(x = 0;x < ad->affiles && !ad->stopflag;x++) {
            if(!(ad->afhead[x].flags & (AF_DUPE | AF_FILTERED))) {
              if(!(x % 50)) {
                sprintf(s,
                        GetPString(IDS_DUPECHECKINGOFTEXT),
                        x,
                        ad->affiles);
                WinSetWindowText(ad->hwndStatus,s);
              }
              for(z = 0;z < ad->affiles && !ad->stopflag;z++) {
                if(x != z && !(ad->afhead[z].flags & (AF_DUPE | AF_FILTERED))) {
                  if(ad->dupeflags & DP_SIZES) {
                    if(ad->afhead[x].cbFile != ad->afhead[z].cbFile)
                      goto SkipNonDupe;
                  }
                  if(ad->dupeflags & DP_DATES) {
                    if(*(INT *)&ad->afhead[x].date !=
                         *(INT *)&ad->afhead[z].date ||
                       *(INT *)&ad->afhead[x].time !=
                         *(INT *)&ad->afhead[z].time)
                      goto SkipNonDupe;
                  }
                  if(ad->dupeflags & DP_NAMES) {
                    if(ad->dupeflags & DP_EXTS) {
                      px = strrchr(ad->afhead[x].filename,'.');
                      pz = strrchr(ad->afhead[z].filename,'.');
                      if((px || pz) && (!px || !pz))
                        goto SkipNonDupe;
                      if(px) {
                        *px = 0;
                        *pz = 0;
                      }
                    }
                    if(stricmp(ad->afhead[x].filename,
                               ad->afhead[z].filename)) {
                      if(ad->dupeflags & DP_EXTS) {
                        if(px) {
                          *px = '.';
                          *pz = '.';
                        }
                      }
                      goto SkipNonDupe;
                    }
                    if(ad->dupeflags & DP_EXTS) {
                      if(px) {
                        *px = '.';
                        *pz = '.';
                      }
                    }
                  }
                  if(ad->dupeflags & DP_CRCS) {
                    if(!(ad->afhead[x].flags & AF_CRCED)) {
                      ad->afhead[x].CRC = CRCFile(ad->afhead[x].fullname,
                                                  &error);
                      if(!error)
                        ad->afhead[x].flags |= AF_CRCED;
                    }
                    if(!(ad->afhead[z].flags & AF_CRCED)) {
                      ad->afhead[z].CRC = CRCFile(ad->afhead[z].fullname,
                                                  &error);
                      if(!error)
                        ad->afhead[z].flags |= AF_CRCED;
                    }
                    if((ad->afhead[x].flags & AF_CRCED) &&
                       (ad->afhead[z].flags & AF_CRCED)) {
                      if(ad->afhead[x].CRC != ad->afhead[z].CRC)
                        goto SkipNonDupe;
                    }
                    DosSleep(0);
                  }
                  ad->afhead[x].flags |= AF_DUPE;
                  ad->afhead[z].flags |= AF_DUPE;
SkipNonDupe:
;
                }
              }
              DosSleep(1L);
            }
          }
          for(x = 0;x < ad->affiles && !ad->stopflag;x++) {
            if(!(ad->afhead[x].flags & AF_DUPE))
              ad->afhead[x].flags |= AF_FILTERED;
          }
          ReSort(hwnd);
          WinInvalidateRect(hwnd,NULL,FALSE);
        }
      }
    }
    PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
    DosReleaseMutexSem(ad->ScanSem);
  }
  PostMsg(hwnd,UM_CONTAINER_FILLED,MPVOID,MPVOID);
  if(hmq2)
    WinDestroyMsgQueue(hmq2);
  if(hab2)
    WinTerminate(hab2);
}


static VOID FilterList (HWND hwnd) {

  register ULONG x,z;
  BOOL           ret;
  ALLDATA       *ad = WinQueryWindowPtr(hwnd,0);
  CHAR          *p;

  if(ad->cursored <= ad->afifiles) {
    x = ad->cursored - 1;
    x = (ad->invertsort) ? (ad->afifiles - 1) - x : x;
    p = strrchr(ad->afindex[x]->filename,'.');
    if(p) {
      strcpy(ad->mask.szMask,"*");
      strcat(ad->mask.szMask,p);
    }
  }
  *(ad->mask.prompt) = 0;
  ad->mask.fIsSeeAll = TRUE;
  if(WinDlgBox(HWND_DESKTOP,hwnd,PickMaskDlgProc,
               FM3ModHandle,MSK_FRAME,MPFROMP(&ad->mask))) {
    for(x = 0;x < ad->affiles;x++) {
      ret = FALSE;
      if(ad->mask.pszMasks[1]) {
        for(z = 0;ad->mask.pszMasks[z];z++) {
          if(*ad->mask.pszMasks[z]) {
            if(*ad->mask.pszMasks[z] != '/') {
              if(wildcard((strchr(ad->mask.pszMasks[z],'\\') ||
                           strchr(ad->mask.pszMasks[z],':')) ?
                           ad->afhead[x].fullname : ad->afhead[x].filename,
                           ad->mask.pszMasks[z],FALSE))
                ret = TRUE;
            }
            else {
              if(wildcard((strchr(ad->mask.pszMasks[z],'\\') ||
                           strchr(ad->mask.pszMasks[z],':')) ?
                           ad->afhead[x].fullname : ad->afhead[x].filename,
                           ad->mask.pszMasks[z] + 1,FALSE)) {
                ret = FALSE;
                break;
              }
            }
          }
        }
      }
      else if(*ad->mask.szMask) {
        if(wildcard((strchr(ad->mask.szMask,'\\') ||
                     strchr(ad->mask.szMask,':')) ?
                     ad->afhead[x].fullname : ad->afhead[x].filename,
                     ad->mask.szMask,FALSE))
          ret = TRUE;
      }
      else
        ret = TRUE;

      if(ret) {
        if((!(ad->mask.attrFile & FILE_HIDDEN) && (ad->afhead[x].attrFile & FILE_HIDDEN)) ||
           (!(ad->mask.attrFile & FILE_SYSTEM) && (ad->afhead[x].attrFile & FILE_SYSTEM)) ||
           (!(ad->mask.attrFile & FILE_READONLY) && (ad->afhead[x].attrFile & FILE_READONLY)) ||
           (!(ad->mask.attrFile & FILE_ARCHIVED) && (ad->afhead[x].attrFile & FILE_ARCHIVED)))
          ret = FALSE;
        else if(((ad->mask.antiattr & FILE_HIDDEN) && !(ad->afhead[x].attrFile & FILE_HIDDEN)) ||
                ((ad->mask.antiattr & FILE_SYSTEM) && !(ad->afhead[x].attrFile & FILE_SYSTEM)) ||
                ((ad->mask.antiattr & FILE_READONLY) && !(ad->afhead[x].attrFile & FILE_READONLY)) ||
                ((ad->mask.antiattr & FILE_ARCHIVED) && !(ad->afhead[x].attrFile & FILE_ARCHIVED)))
         ret = FALSE;
      }

      if(!ret)
        ad->afhead[x].flags |= AF_FILTERED;
      else
        ad->afhead[x].flags &= (~AF_FILTERED);
    }
    ReSort(hwnd);
    PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
    WinInvalidateRect(hwnd,NULL,FALSE);
  }
}


static ULONG RemoveDeleted (HWND hwnd) {

  ALLDATA       *ad = WinQueryWindowPtr(hwnd,0);
  ULONG          oldaffiles = ad->affiles;
  register ULONG x,y;

  for(x = 0;x < ad->affiles;x++) {
    if(ad->afhead[x].flags & AF_DELETED) {
      for(y = x;y < ad->affiles;y++) {
        if(!(ad->afhead[y].flags & AF_DELETED))
          break;
        if((ad->afhead[y].flags & AF_SELECTED) &&
           !(ad->afhead[y].flags & AF_FILTERED)) {
          ad->selected--;
          ad->selbytes -= ad->afhead[y].cbFile;
        }
        free(ad->afhead[y].fullname);
      }
      memmove(&(ad->afhead[x]),&(ad->afhead[y]),
              (ad->affiles - y) * sizeof(ALLFILES));
      ad->affiles -= (y - x);
    }
  }
  if(ad->affiles != oldaffiles) {

    ALLFILES *tempa,**templ;

    if(!ad->affiles)
      FreeAllFilesList(hwnd);
    else {
      tempa = realloc(ad->afhead,ad->affiles * sizeof(ALLFILES));
      if(tempa) {
        ad->afhead = tempa;
        ad->afalloc = ad->affiles;
      }
      templ = realloc(ad->afindex,ad->affiles * sizeof(ALLFILES *));
      if(templ)
        ad->afindex = templ;
      DosPostEventSem(CompactSem);
      ReSort(hwnd);
    }
  }
  return ad->affiles;
}


static VOID DoADir (HWND hwnd,CHAR *pathname) {

  ALLDATA       *ad = WinQueryWindowPtr(hwnd,0);
  CHAR          *filename,*enddir;
  FILEFINDBUF3  *pffb,*ffb;
  HDIR           hdir = HDIR_CREATE;
  ULONG          nm,uL;
  register ULONG x;
  register PBYTE fb;

  filename = malloc(CCHMAXPATH);
  if(!filename) {
// saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"Malloc filename failed.");
    return;
  }
  uL = ad->afFilesToGet;
  if(fRemoteBug && isalpha(*pathname) && pathname[1] == ':' &&
     pathname[2] == '\\' &&
     (driveflags[toupper(*pathname) - 'A'] & DRIVE_REMOTE))
    uL = 1L;
  pffb = malloc(sizeof(FILEFINDBUF3) * uL);
  if(!pffb) {
    free(filename);
// saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"Malloc pffb failed.");
    return;
  }
  nm = uL;
  strcpy(filename,pathname);
  enddir = &filename[strlen(filename) - 1];
  if(*enddir != '\\') {
    enddir++;
    *enddir = '\\';
  }
  enddir++;
  strcpy(enddir,"*");
  DosError(FERR_DISABLEHARDERR);
  if(!DosFindFirst(filename,&hdir,FILE_NORMAL | FILE_ARCHIVED |
                   FILE_READONLY | FILE_DIRECTORY | FILE_SYSTEM | FILE_HIDDEN,
                   pffb,sizeof(FILEFINDBUF3) * nm,&nm,FIL_STANDARD)) {
    do {
      priority_normal();
      fb = (PBYTE)pffb;
      for(x = 0;x < nm;x++) {
        ffb = (FILEFINDBUF3 *)fb;
        if(ffb->attrFile & FILE_DIRECTORY) {
          if(*ffb->achName != '.' ||
             (ffb->achName[1] &&
              ffb->achName[1] != '.')) {
            strcpy(enddir,ffb->achName);
            DoADir(hwnd,filename);
          }
        }
        else {
          *enddir = 0;
          strcpy(enddir,ffb->achName);
          if(!ad->afalloc || ad->affiles > ad->afalloc - 1) {

            ALLFILES *temp;

            temp = realloc(ad->afhead,(ad->afalloc + 1000) *
                           sizeof(ALLFILES));
            if(temp) {
              ad->afhead = temp;
              if(ad->stopflag)
                break;
              ad->afalloc += 1000;
            }
            else {
// saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"Realloc failed.");
              ad->stopflag = 1;
              break;
            }
          }
          ad->afhead[ad->affiles].fullname   = strdup(filename);
          if(ad->afhead[ad->affiles].fullname) {
            ad->afhead[ad->affiles].filename =
              ad->afhead[ad->affiles].fullname + (enddir - filename);
            ad->afhead[ad->affiles].cbFile   = ffb->cbFile;
            ad->afhead[ad->affiles].date     = ffb->fdateLastWrite;
            ad->afhead[ad->affiles].time     = ffb->ftimeLastWrite;
            ad->afhead[ad->affiles].attrFile = (USHORT)ffb->attrFile;
            ad->afhead[ad->affiles].flags    = 0;
            ad->affiles++;
            if(ad->longest < ffb->cchName)
              ad->longest = ffb->cchName;
            if(ad->longestw < ffb->cchName + (enddir - filename))
              ad->longestw = ffb->cchName + (enddir - filename);
          }
          else {
// saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"Strdup failed.");
            ad->stopflag = 1;
            break;
          }
        }
        fb += ffb->oNextEntryOffset;
      }
      nm = uL;
    } while(!ad->stopflag &&
            !DosFindNext(hdir,pffb,sizeof(FILEFINDBUF3) * nm,&nm));
    DosFindClose(hdir);
  }
  free(pffb);
  free(filename);
}


static VOID FindAll (VOID *args) {

  ULONG     ulDriveNum,ulDriveMap,x;
  CHAR      startname[] = " :\\";
  HWND      hwnd = (HWND)args;
  HAB       hab2 = (HAB)0;
  HMQ       hmq2 = (HMQ)0;
  ALLDATA  *ad = WinQueryWindowPtr(hwnd,0);

  if(!DosRequestMutexSem(ad->ScanSem,SEM_INDEFINITE_WAIT)) {
    priority_normal();
    hab2 = WinInitialize(0);
    if(hab2) {
      hmq2 = WinCreateMsgQueue(hab2,0);
      if(hmq2) {
        WinCancelShutdown(hmq2,TRUE);
        ad->afFilesToGet = min(FilesToGet,128);
        if(!*ad->findpath) {
          DosError(FERR_DISABLEHARDERR);
          if(!DosQCurDisk(&ulDriveNum,&ulDriveMap)) {
            for(x = 2L;x < 26L && !ad->stopflag;x++) {
              if((ulDriveMap & (1L << x)) && ad->drvsflags[x]) {
                *startname = (CHAR)(x + 'A');
                DoADir(hwnd,startname);
                PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
                DosSleep(1L);
              }
            }
          }
        }
        else
          DoADir(hwnd,ad->findpath);
        DosPostEventSem(CompactSem);
      }
    }
    if(ad->afalloc != ad->affiles) {

      ALLFILES *tempa,**templ;

      tempa = realloc(ad->afhead,sizeof(ALLFILES) * ad->affiles);
      if(tempa) {
        ad->afhead = tempa;
        ad->afalloc = ad->affiles;
      }
      templ = realloc(ad->afindex,sizeof(ALLFILES *) * ad->affiles);
      if(templ)
        ad->afindex = templ;
      DosPostEventSem(CompactSem);
    }

    if(!ad->stopflag) {
      PostMsg(hwnd,UM_RESCAN,MPFROMLONG(1L),MPVOID);
      ReSort(hwnd);
    }
    DosReleaseMutexSem(ad->ScanSem);
  }
  PostMsg(hwnd,UM_CONTAINER_FILLED,MPVOID,MPVOID);
  if(hmq2)
    WinDestroyMsgQueue(hmq2);
  if(hab2)
    WinTerminate(hab2);
}


MRESULT EXPENTRY AFDrvsWndProc (HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2) {

  switch(msg) {
    case WM_INITDLG:
      if(mp2) {

        ULONG    ulDriveNum,ulDriveMap,x;
        CHAR     startname[] = " :";
        SHORT    sSelect;
        ALLDATA *ad;

        ad = (ALLDATA *)mp2;
        WinSetWindowPtr(hwnd,0,mp2);
        DosError(FERR_DISABLEHARDERR);
        if(!DosQCurDisk(&ulDriveNum,&ulDriveMap)) {
          for(x = 2L;x < 26L && !ad->stopflag;x++) {
            if(!(driveflags[x] & (DRIVE_IGNORE | DRIVE_INVALID))) {
              if(ulDriveMap & (1L << x)) {
                *startname = (CHAR)(x + 'A');
                sSelect = (SHORT)WinSendDlgItemMsg(hwnd,DRVS_LISTBOX,
                                                   LM_INSERTITEM,
                                                   MPFROM2SHORT(LIT_END,0),
                                                   MPFROMP(startname));
                if(sSelect >= 0 && ad->drvsflags[x])
                  WinSendDlgItemMsg(hwnd,DRVS_LISTBOX,LM_SELECTITEM,
                                    MPFROM2SHORT(sSelect,0),
                                    MPFROMLONG(TRUE));
              }
            }
          }
        }
      }
      else
        WinDismissDlg(hwnd,0);
      break;

    case WM_CONTROL:
      switch(SHORT1FROMMP(mp1)) {
        case DRVS_LISTBOX:
          switch(SHORT2FROMMP(mp1)) {
            case LN_ENTER:
              PostMsg(hwnd,WM_COMMAND,MPFROM2SHORT(DID_OK,0),MPVOID);
              break;
          }
          break;
      }
      return 0;

    case WM_COMMAND:
      switch(SHORT1FROMMP(mp1)) {
        case DID_OK:
          {
            INT       x;
            SHORT     sSelect;
            CHAR      filename[3];
            ALLDATA  *ad = WinQueryWindowPtr(hwnd,0);

            memset(ad->drvsflags,0,sizeof(ad->drvsflags));
            sSelect = (SHORT)WinSendDlgItemMsg(hwnd,DRVS_LISTBOX,
                                               LM_QUERYSELECTION,
                                               MPFROM2SHORT(LIT_FIRST,0),
                                               MPVOID);
            while(sSelect >= 0) {
              *filename = 0;
              if(WinSendDlgItemMsg(hwnd,DRVS_LISTBOX,LM_QUERYITEMTEXT,
                                   MPFROM2SHORT(sSelect,2),
                                   MPFROMP(filename)) && *filename)
                ad->drvsflags[*filename - 'A'] = 1;
              sSelect = (SHORT)WinSendDlgItemMsg(hwnd,DRVS_LISTBOX,
                                                 LM_QUERYSELECTION,
                                                 MPFROM2SHORT(sSelect,0),
                                                 MPVOID);
            }
            for(x = 2L;x < 26L;x++) {
              if(ad->drvsflags[x]) {
                WinDismissDlg(hwnd,1);
                return 0;
              }
            }
          }
          WinDismissDlg(hwnd,0);
          break;

        case IDM_HELP:
          if(hwndHelp)
            WinSendMsg(hwndHelp,HM_DISPLAY_HELP,
                       MPFROM2SHORT(HELP_DRVSWND,0),
                       MPFROMSHORT(HM_RESOURCEID));
          break;

        case DID_CANCEL:
          WinDismissDlg(hwnd,0);
          break;
      }
      return 0;
  }
  return WinDefDlgProc(hwnd,msg,mp1,mp2);
}


static HPS InitWindow (HWND hwnd) {

  ALLDATA     *ad = WinQueryWindowPtr(hwnd,0);
  HPS          hps = (HPS)0;
  SIZEL        sizel;
  FONTMETRICS  FontMetrics;

  if(ad) {
    sizel.cx = sizel.cy = 0;
    hps = GpiCreatePS(WinQueryAnchorBlock(hwnd),WinOpenWindowDC(hwnd),
                     (PSIZEL)&sizel,PU_PELS | GPIF_DEFAULT | GPIT_MICRO |
                                    GPIA_ASSOC);
    if(hps) {
      GpiSetCp(hps,(ULONG)ad->fattrs.usCodePage);
      GpiCreateLogFont(hps,NULL,FIXED_FONT_LCID,&ad->fattrs);
      GpiSetCharSet(hps,FIXED_FONT_LCID);
      GpiQueryFontMetrics(hps,(long)sizeof(FONTMETRICS),&FontMetrics);
      ad->fattrs.lAveCharWidth  = FontMetrics.lAveCharWidth;
      ad->fattrs.lMaxBaselineExt = FontMetrics.lMaxBaselineExt;
      ad->lMaxAscender = max(FontMetrics.lMaxAscender,0);
      ad->lMaxDescender = max(FontMetrics.lMaxDescender,0);
      ad->lMaxHeight = ad->lMaxDescender + ad->lMaxAscender;
      if(ad->fattrs.usCodePage != FontMetrics.usCodePage) {
        ad->fattrs.usCodePage = FontMetrics.usCodePage;
        Codepage = ad->fattrs.usCodePage;
        PrfWriteProfileData(fmprof,
                            appname,
                            "Seeall.Codepage",
                            &ad->fattrs.usCodePage,
                            sizeof(USHORT));
      }
      else if(ad->fattrs.usCodePage) {

        HMQ hmq;
        ULONG cps[50],len,x;

        if(!DosQueryCp(sizeof(cps),cps,&len)) {
          for(x = 0;x < len / sizeof(ULONG);x++) {
            if(cps[x] == (ULONG)ad->fattrs.usCodePage) {
              hmq = WinQueryWindowULong(hwnd,QWL_HMQ);
              WinSetCp(hmq,ad->fattrs.usCodePage);
              break;
            }
          }
        }
        DosSetProcessCp((ULONG)ad->fattrs.usCodePage);
      }
      GpiSetBackMix(hps,BM_OVERPAINT);
    }
  }
  return (hps);
}


static VOID PaintLine (HWND hwnd,HPS hps,ULONG whichfile,ULONG topfile,
                       RECTL *Rectl) {

  ALLDATA *ad = WinQueryWindowPtr(hwnd,0);
  POINTL   ptl;
  CHAR     szBuff[CCHMAXPATH + 80];
  ULONG    len,y;

  y = (ad->invertsort) ? (ad->afifiles - 1) - whichfile : whichfile;
  ptl.y = (Rectl->yTop -
           (ad->lMaxHeight * (((whichfile + 1) - topfile) + 1)));
  ptl.x = ad->horzscroll;
  if(ptl.y < Rectl->yBottom || ptl.y > Rectl->yTop || y > ad->afifiles)
    return;
  GpiSetBackMix(hps,BM_OVERPAINT);
  if(ad->afindex[y]->flags & AF_SELECTED) {
    GpiSetColor(hps,standardcolors[Colors[COLORS_SELECTEDNORMALFORE]]);
    GpiSetBackColor(hps,(whichfile == ad->cursored - 1) ?
                    standardcolors[Colors[COLORS_CURSOREDSELECTEDBACK]] :
                    standardcolors[Colors[COLORS_SELECTEDBACK]]);
  }
  else {
    GpiSetColor(hps,
               ((ad->afindex[y]->attrFile & (FILE_SYSTEM | FILE_HIDDEN)) != 0) ?
                standardcolors[Colors[COLORS_SYSTEMFORE]] :
                ((ad->afindex[y]->attrFile & FILE_READONLY) != 0) ?
                 standardcolors[Colors[COLORS_READONLYFORE]] :  standardcolors[Colors[COLORS_NORMALFORE]]);
    GpiSetBackColor(hps,(whichfile == ad->cursored - 1) ?
                    standardcolors[Colors[COLORS_CURSOREDNORMALBACK]] :
                    standardcolors[Colors[COLORS_NORMALBACK]]);
  }
  len = sprintf(szBuff,
                "%c%-*.*s  %-12lu  %c%c%c%c%c  %04u/%02u/%02u %02u:%02u:%02u ",
                (whichfile == ad->cursored - 1) ? '>' : ' ',
                (ad->fullnames) ? ad->longestw : ad->longest,
                (ad->fullnames) ? ad->longestw : ad->longest,
                (ad->fullnames) ? ad->afindex[y]->fullname :
                                  ad->afindex[y]->filename,
                ad->afindex[y]->cbFile,
                "-A"[((ad->afindex[y]->attrFile & FILE_ARCHIVED) != 0)],
                "-R"[((ad->afindex[y]->attrFile & FILE_READONLY) != 0)],
                "-H"[((ad->afindex[y]->attrFile & FILE_HIDDEN) != 0)],
                "-S"[((ad->afindex[y]->attrFile & FILE_SYSTEM) != 0)],
                "-D"[((ad->afindex[y]->attrFile & FILE_DIRECTORY) != 0)],
                ad->afindex[y]->date.year + 1980,
                ad->afindex[y]->date.month,
                ad->afindex[y]->date.day,
                ad->afindex[y]->time.hours,
                ad->afindex[y]->time.minutes,
                ad->afindex[y]->time.twosecs * 2);
  GpiCharStringAt(hps,&ptl,len,szBuff);
  GpiQueryCurrentPosition(hps,&ptl);
  if(ptl.x + abs(ad->horzscroll) > ad->maxx) {
    ad->maxx = ptl.x + abs(ad->horzscroll);
    WinSendMsg(ad->hhscroll,SBM_SETTHUMBSIZE,
               MPFROM2SHORT((SHORT)Rectl->xRight,(SHORT)ad->maxx),
               MPVOID);
  }
}


MRESULT EXPENTRY SeeStatusProc (HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2) {

  switch(msg) {
    case WM_CREATE:
      return CommonTextProc(hwnd,msg,mp1,mp2);

    case WM_SETFOCUS:
      if(mp2)
        PostMsg(hwnd,UM_FOCUSME,MPVOID,MPVOID);
      break;

    case WM_PAINT:
      {
        SWP       swp;
        POINTL    ptl;
        HPS       hps;

        PaintRecessedWindow(hwnd,(HPS)0,FALSE,FALSE);
        hps = WinGetPS(WinQueryWindow(hwnd,QW_PARENT));
        if(hps) {
          WinQueryWindowPos(hwnd,&swp);
          ptl.x = swp.x - 1;
          ptl.y = swp.y + swp.cy + 2;
          GpiMove(hps,&ptl);
          GpiSetColor(hps,CLR_WHITE);
          ptl.x = swp.x + swp.cx;
          GpiLine(hps,&ptl);
          WinReleasePS(hps);
        }
      }
      break;

    case UM_FOCUSME:
      WinSetFocus(HWND_DESKTOP,WinWindowFromID(WinQueryWindow(hwnd,QW_PARENT),
                  FID_CLIENT));
      return 0;
  }
  return PFNWPStatic(hwnd,msg,mp1,mp2);
}


MRESULT EXPENTRY SeeFrameWndProc (HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2) {

  PFNWP oldproc = (PFNWP)WinQueryWindowPtr(hwnd,0);

  switch(msg) {
    case WM_BUTTON1UP:
    case WM_BUTTON2UP:
    case WM_BUTTON3UP:
    case WM_MOUSEMOVE:
    case WM_CHORD:
      shiftstate = (SHORT2FROMMP(mp2) & (KC_SHIFT | KC_ALT | KC_CTRL));
      break;

    case WM_CHAR:
      shiftstate = (SHORT1FROMMP(mp1) & (KC_SHIFT | KC_ALT | KC_CTRL));
      break;

    case WM_CALCFRAMERECT:
      {
        MRESULT mr;
        PRECTL  prectl;

        mr = oldproc(hwnd,msg,mp1,mp2);

        /*
         * Calculate the position of the client rectangle.
         * Otherwise,  we'll see a lot of redraw when we move the
         * client during WM_FORMATFRAME.
         */

        if(mr && mp2) {
          prectl = (PRECTL)mp1;
          prectl->yBottom += 22;
          prectl->yTop -= 24;
        }
        return mr;
      }

    case WM_FORMATFRAME:
      {
        SHORT sCount;
        PSWP  pswp,pswpClient,pswpNew;

        sCount = (SHORT)oldproc(hwnd,msg,mp1,mp2);

        /*
         * Reformat the frame to "squeeze" the client
         * and make room for status window sibling beneath
         */

        pswp = (PSWP)mp1;
        {
          SHORT x;

          for(x = 0;x < sCount;x++) {
            if(WinQueryWindowUShort(pswp->hwnd,QWS_ID) == FID_CLIENT) {
              pswpClient = pswp;
              break;
            }
            pswp++;
          }
        }
        pswpNew = (PSWP)mp1 + sCount;
        *pswpNew = *pswpClient;
        pswpNew->hwnd = WinWindowFromID(hwnd,SEEALL_STATUS);
        pswpNew->x = pswpClient->x + 2;
        pswpNew->y = pswpClient->y + 2;
        pswpNew->cx = pswpClient->cx - 3;
        pswpNew->cy = 20;
        pswpClient->y = pswpNew->y + pswpNew->cy + 3;
        pswpClient->cy = (pswpClient->cy - pswpNew->cy) - 5;
        sCount++;
        return MRFROMSHORT(sCount);
      }

    case WM_QUERYFRAMECTLCOUNT:
      {
        SHORT sCount;

        sCount = (SHORT)oldproc(hwnd,msg,mp1,mp2);
        sCount++;
        return MRFROMSHORT(sCount);
      }
  }
  return oldproc(hwnd,msg,mp1,mp2);
}


MRESULT EXPENTRY SeeAllWndProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) {

  ALLDATA *ad = WinQueryWindowPtr(hwnd,0);

  switch (msg) {
    case WM_CREATE:
// fprintf(stderr,"Seeall: WM_CREATE\n");
      WinSetWindowPtr(hwnd,0,NULL);
      ad = malloc(sizeof(ALLDATA));
      if(ad) {
        memset(ad,0,sizeof(ALLDATA));
        ad->size = sizeof(ALLDATA);
        ad->hwndFrame = WinQueryWindow(hwnd,QW_PARENT);
        ad->mask.attrFile = FILE_READONLY | FILE_HIDDEN   |
                            FILE_SYSTEM   | FILE_ARCHIVED;
        ad->mask.fNoDirs = TRUE;
        *(ad->mask.prompt) = 0;
        WinSetWindowPtr(hwnd,0,(PVOID)ad);
        ad->compare = comparenames;
        if(Firsttime) {

          ULONG  size;

          size = sizeof(USHORT);
          PrfQueryProfileData(fmprof,
                              appname,
                              "Seeall.Codepage",
                              (PVOID)&Codepage,
                              &size);
          size = sizeof(BOOL);
          PrfQueryProfileData(fmprof,
                              appname,
                              "Seeall.Fullnames",
                              (PVOID)&Fullnames,
                              &size);
          size = sizeof(USHORT);
          PrfQueryProfileData(fmprof,
                              appname,
                              "Seeall.Sort",
                              (PVOID)&SortType,
                              &size);
          size = sizeof(BOOL);
          PrfQueryProfileData(fmprof,
                              appname,
                              "Seeall.SortReverse",
                              (PVOID)&SortReverse,
                              &size);
          memset(&Fattrs,0,sizeof(FATTRS));
          size = sizeof(FATTRS);
          Fattrs.usRecordLength  = sizeof(FATTRS);
          Fattrs.lMaxBaselineExt = 16;
          Fattrs.lAveCharWidth   = 8;
          Fattrs.usCodePage = Codepage;
          strcpy(Fattrs.szFacename,
                 GetPString(IDS_SYSMONOTEXT));
          PrfQueryProfileData(fmprof,
                              appname,
                              "Seeall.Fattrs",
                              (PVOID)&Fattrs,
                              &size);
          size = sizeof(LONG) * COLORS_MAX;
          PrfQueryProfileData(fmprof,
                              appname,
                              "Seeall.Colors",
                              (PVOID)Colors,
                              &size);
          Firsttime = FALSE;
        }
        switch(SortType) {
          case IDM_SORTEASIZE:
            ad->compare = (PFNSORT)NULL;
            break;
          case IDM_SORTNAME:
            ad->compare = comparefullnames;
            break;
          case IDM_SORTFILENAME:
            ad->compare = comparenames;
            break;
          case IDM_SORTSIZE:
            ad->compare = comparesizes;
            break;
          case IDM_SORTLWDATE:
            ad->compare = comparedates;
            break;
          case IDM_SORTFIRST:
            ad->compare = compareexts;
            break;
        }
        ad->invertsort = SortReverse;
        ad->fattrs     = Fattrs;
        ad->fullnames  = Fullnames;
        ad->stopflag   = 0;
        ad->cursored   = ad->topfile = 1;
        ad->fattrs.usCodePage = Codepage;
        memcpy(ad->colors,Colors,sizeof(LONG) * COLORS_MAX);
        ad->hwndMenu   = WinWindowFromID(WinQueryWindow(hwnd,QW_PARENT),
                                         FID_MENU);
        SetConditionalCascade(ad->hwndMenu,IDM_DELETESUBMENU,
                              (fDefaultDeletePerm) ?
                               IDM_PERMDELETE : IDM_DELETE);
        SetConditionalCascade(ad->hwndMenu,IDM_MOVEMENU,IDM_MOVE);
        SetConditionalCascade(ad->hwndMenu,IDM_COPYMENU,IDM_COPY);
        SetConditionalCascade(ad->hwndMenu,IDM_OPENSUBMENU,IDM_OPENDEFAULT);
        SetConditionalCascade(ad->hwndMenu,IDM_OBJECTSUBMENU,IDM_SHADOW);
        if(fWorkPlace) {
          WinSendMsg(ad->hwndMenu,MM_DELETEITEM,
                     MPFROM2SHORT(IDM_OPENSUBMENU,TRUE),MPVOID);
          WinSendMsg(ad->hwndMenu,MM_DELETEITEM,
                     MPFROM2SHORT(IDM_OBJECTSUBMENU,TRUE),MPVOID);
        }
        ad->hwndClient = hwnd;
        ad->hps = InitWindow(hwnd);
        ad->hvscroll = WinWindowFromID(WinQueryWindow(hwnd,QW_PARENT),
                                       FID_VERTSCROLL);
        ad->hhscroll = WinWindowFromID(WinQueryWindow(hwnd,QW_PARENT),
                                       FID_HORZSCROLL);
        ad->multiplier = 1;
        if(_beginthread(MakeSeeObj,NULL,122880,(PVOID)ad) != -1) {
          if(!DosCreateMutexSem(NULL,&ad->ScanSem,0L,FALSE)) {
            ad->hwndStatus = WinCreateWindow(WinQueryWindow(hwnd,QW_PARENT),
                                             GetPString(IDS_WCSEESTATUS),
                                             NullStr,
                                             WS_VISIBLE | SS_TEXT |
                                             DT_LEFT | DT_VCENTER,
                                             0,
                                             0,
                                             0,
                                             0,
                                             WinQueryWindow(hwnd,QW_PARENT),
                                             HWND_TOP,
                                             SEEALL_STATUS,
                                             NULL,
                                             NULL);
            {
              PFNWP oldproc;

              oldproc = WinSubclassWindow(WinQueryWindow(hwnd,QW_PARENT),
                                          (PFNWP)SeeFrameWndProc);
              if(oldproc)
                WinSetWindowPtr(WinQueryWindow(hwnd,QW_PARENT),0,
                                (PVOID)oldproc);
            }
            break;
          }
        }
      }
      PostMsg(hwnd,WM_CLOSE,MPVOID,MPVOID);
      break;

    case UM_SETUP5:
// fprintf(stderr,"Seeall: UM_SETUP5\n");
      if(ad) {
        if(mp1 && *((CHAR *)mp1))
          strcpy(ad->findpath,(CHAR *)mp1);
        else {
          if(!WinDlgBox(HWND_DESKTOP,hwnd,AFDrvsWndProc,
                        FM3ModHandle,DRVS_FRAME,(PVOID)ad)) {
            PostMsg(hwnd,WM_CLOSE,MPVOID,MPVOID);
            return 0;
          }
        }
        if(_beginthread(FindAll,NULL,524288,(PVOID)hwnd) == -1)
          PostMsg(hwnd,WM_CLOSE,MPVOID,MPVOID);
        else {
          DosSleep(100L);
          PostMsg(hwnd,UM_SETUP,MPVOID,MPVOID);
          PostMsg(hwnd,UM_SETUP2,MPVOID,MPVOID);
        }
      }
      else
        PostMsg(hwnd,WM_CLOSE,MPVOID,MPVOID);
      return 0;

    case UM_UPDATERECORDLIST:
      if(mp1) {

        APIRET rc;

        rc = DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN);
        if(!rc) {
          WinSetPointer(HWND_DESKTOP,hptrBusy);
          if(UpdateList(hwnd,mp1)) {
            FreeList(mp1);
            RemoveDeleted(hwnd);
            ReSort(hwnd);
            WinInvalidateRect(hwnd,NULL,FALSE);
          }
          DosReleaseMutexSem(ad->ScanSem);
          WinSetPointer(HWND_DESKTOP,hptrArrow);
        }
      }
      return 0;

    case UM_SETUP2:
// fprintf(stderr,"Seeall: UM_SETUP2\n");
      if(ad) {

        CHAR  s[256];
        BOOL  once = FALSE;
        ULONG x,ulDriveNum,ulDriveMap;

        strcpy(s,
               GetPString(IDS_SEEALLTITLETEXT));
        if(!*ad->findpath) {
          DosError(FERR_DISABLEHARDERR);
          if(!DosQCurDisk(&ulDriveNum,&ulDriveMap)) {
            for(x = 2L;x < 26L && !ad->stopflag;x++) {
              if((ulDriveMap & (1L << x)) && ad->drvsflags[x]) {
                sprintf(&s[strlen(s)],
                        "%s%c:",
                        (once) ? ", " : " (",
                        x + 'A');
                once = TRUE;
              }
            }
            if(once)
              strcat(s,")");
          }
        }
        else {
          strcat(s," (");
          strcat(s,ad->findpath);
          strcat(s,")");
        }
        WinSetWindowText(WinQueryWindow(hwnd,QW_PARENT),s);
      }
      return 0;

    case UM_SETUP3:
// fprintf(stderr,"Seeall: UM_SETUP3\n");
      if(ad) {
        ad->multiplier = ad->afifiles / 32767;
        if(ad->multiplier * 32767 != ad->afifiles)
          ad->multiplier++;
        if(!ad->multiplier)
          ad->multiplier++;
        {
          RECTL Rectl;
          ULONG numlines;

          WinQueryWindowRect(hwnd,&Rectl);
          numlines = NumLines(&Rectl,ad);
          if(numlines) {
            WinSendMsg(ad->hhscroll,SBM_SETTHUMBSIZE,
                       MPFROM2SHORT((SHORT)Rectl.xRight,(SHORT)ad->maxx),
                       MPVOID);
            WinSendMsg(ad->hvscroll,SBM_SETTHUMBSIZE,
                       MPFROM2SHORT((SHORT)numlines,
                                    (SHORT)min(ad->afifiles,32767)),
                       MPFROM2SHORT(1,ad->afifiles + 1));
            WinSendMsg(ad->hhscroll,SBM_SETSCROLLBAR,
                       MPFROMSHORT((SHORT)abs(ad->horzscroll)),
                       MPFROM2SHORT(0,(SHORT)(ad->maxx - Rectl.xRight)));
            WinSendMsg(ad->hvscroll,SBM_SETSCROLLBAR,
                       MPFROMSHORT((SHORT)(ad->topfile / ad->multiplier)),
                       MPFROM2SHORT(1,
                                    (SHORT)(ad->afifiles / ad->multiplier) -
                                            (numlines - 1)));
            if(ad->afifiles - ad->topfile < numlines) {
              ad->topfile = ((ad->afifiles - ad->topfile) - numlines);
              WinInvalidateRect(hwnd,NULL,FALSE);
            }
          }
        }
      }
      return 0;

    case UM_SETUP4:
// fprintf(stderr,"Seeall: UM_SETUP4\n");
      if(ad)
        ad->killme = TRUE;
      else
        PostMsg((HWND)0,WM_QUIT,MPVOID,MPVOID);
      return 0;

    case UM_RESCAN:
// fprintf(stderr,"Seeall: UM_RESCAN\n");
      if(ad && !ad->stopflag) {
        if(DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN)) {

          CHAR s[CCHMAXPATH + 80],tm[34];

          if(mp1) {
            strcpy(s,
                   GetPString(IDS_SORTINGTEXT));
            if(ad->afifiles) {
              *tm = 0;
              commafmt(tm,sizeof(tm),ad->afifiles);
              strcat(s,tm);
            }
          }
          else {
            strcpy(s,
                   GetPString(IDS_WORKINGTEXT));
            if(ad->affiles) {
              *tm = 0;
              commafmt(tm,sizeof(tm),ad->affiles);
              strcat(s,tm);
            }
          }
          if(mp2) {
            strcat(s," ");
            strcat(s,(CHAR *)mp2);
          }
          WinSetWindowText(ad->hwndStatus,s);
        }
        else {

          CHAR  s[(CCHMAXPATH * 2) + 80],tm[34],ts[34],tb[34];
          ULONG y;

          if(mp1) {
            strcpy(s,
                   GetPString(IDS_SORTINGTEXT));
            if(ad->afifiles) {
              *tm = 0;
              commafmt(tm,sizeof(tm),ad->afifiles);
              strcat(s,tm);
            }
            if(mp2) {
              strcat(s," ");
              strcat(s,(CHAR *)mp2);
            }
          }
          else if(ad->afifiles) {
            y = (ad->invertsort) ? (ad->afifiles - 1) - (ad->cursored - 1) :
                                   ad->cursored - 1;
            *tm = *ts = *tb = 0;
            commafmt(tm,sizeof(tm),ad->afifiles);
            commafmt(ts,sizeof(ts),ad->selected);
            commafmt(tb,sizeof(tb),ad->selbytes / 1024);
            sprintf(s,
                    " %s %s%s%s  %s %s (%sk)  %s %s",
                    tm,
                    GetPString(IDS_FILETEXT),
                    &"s"[ad->afifiles == 1],
                    (*ad->mask.szMask ||
                     (ad->mask.attrFile & (~FILE_DIRECTORY)) !=
                      (ALLATTRS & (~FILE_DIRECTORY)) ||
                       ad->mask.antiattr) ?
                        GetPString(IDS_FILTEREDTEXT) :
                        NullStr,
                    ts,
                    GetPString(IDS_SELECTEDTEXT),
                    tb,
                    GetPString(IDS_CURRTEXT),
                    ad->afindex[y]->fullname);
          }
          else
            sprintf(s,
                    GetPString(IDS_NOFILESPSTEXT),
                    (*ad->mask.szMask ||
                     (ad->mask.attrFile & (~FILE_DIRECTORY)) !=
                      (ALLATTRS & (~FILE_DIRECTORY)) ||
                     ad->mask.antiattr) ?
                      GetPString(IDS_FILTEREDTEXT) :
                      NullStr);
          WinSetWindowText(ad->hwndStatus,s);
          DosReleaseMutexSem(ad->ScanSem);
        }
      }
      return 0;

    case UM_SETUP:
// fprintf(stderr,"Seeall: UM_SETUP\n");
      if(ad) {
        WinSendMsg(ad->hvscroll,SBM_SETTHUMBSIZE,MPFROM2SHORT(1,1),
                   MPVOID);
        WinSendMsg(ad->hhscroll,SBM_SETTHUMBSIZE,MPFROM2SHORT(1,1),
                         MPVOID);
        WinSetActiveWindow(HWND_DESKTOP,WinQueryWindow(hwnd,QW_PARENT));
      }
      return 0;

    case WM_CHAR:
      shiftstate = (SHORT1FROMMP(mp1) & (KC_SHIFT | KC_ALT | KC_CTRL));
      if(ad && !(SHORT1FROMMP(mp1) & KC_KEYUP)) {

        register ULONG  x;
        ULONG           numlines,y,wascursored = ad->cursored,
                        thistime,len;
        BOOL            found = FALSE;
        RECTL           rcl;

        WinQueryWindowRect(hwnd,&rcl);
        numlines = NumLines(&rcl,ad);
        if(numlines) {
          if(SHORT1FROMMP(mp1) & KC_VIRTUALKEY) {
            ad->lasttime = 0;
            *ad->comnam = 0;
            switch(SHORT2FROMMP(mp2)) {
              case VK_DELETE:
                if((shiftstate & KC_CTRL) == KC_CTRL)
                  PostMsg(hwnd,WM_COMMAND,MPFROM2SHORT(IDM_PERMDELETE,0),MPVOID);
                else if((shiftstate & KC_SHIFT) == KC_SHIFT)
                  PostMsg(hwnd,WM_COMMAND,MPFROM2SHORT(IDM_SAVETOCLIP,0),MPVOID);
                else
                  PostMsg(hwnd,WM_COMMAND,MPFROM2SHORT(IDM_DELETE,0),MPVOID);
                break;
              case VK_LEFT:
                WinSendMsg(hwnd,WM_HSCROLL,MPFROM2SHORT(FID_HORZSCROLL,0),
                           MPFROM2SHORT(0,SB_LINELEFT));
                break;
              case VK_RIGHT:
                WinSendMsg(hwnd,WM_HSCROLL,MPFROM2SHORT(FID_HORZSCROLL,0),
                           MPFROM2SHORT(0,SB_LINERIGHT));
                break;
              case VK_PAGEUP:
                WinSendMsg(hwnd,WM_VSCROLL,MPFROM2SHORT(FID_VERTSCROLL,0),
                           MPFROM2SHORT(0,SB_PAGEUP));
                break;
              case VK_PAGEDOWN:
                WinSendMsg(hwnd,WM_VSCROLL,MPFROM2SHORT(FID_VERTSCROLL,0),
                           MPFROM2SHORT(0,SB_PAGEDOWN));
                break;
              case VK_UP:
                if(ad->cursored > 1) {
                  if(shiftstate & KC_SHIFT)
                    WinSendMsg(hwnd,WM_BUTTON1CLICK,
                               MPFROM2SHORT(ad->fattrs.lAveCharWidth + 2,
                                            ((rcl.yTop - (ad->lMaxHeight *
                                            ((ad->cursored) - ad->topfile))) -
                                            ad->lMaxDescender) - 1),
                               MPFROM2SHORT(TRUE,0));
                  ad->cursored--;
                  if(ad->cursored < ad->topfile) {
                    PaintLine(hwnd,ad->hps,ad->cursored,ad->topfile,&rcl);
                    WinSendMsg(hwnd,WM_VSCROLL,MPFROM2SHORT(FID_VERTSCROLL,0),
                               MPFROM2SHORT(0,SB_LINEUP));
                  }
                  else {
                    PaintLine(hwnd,ad->hps,ad->cursored - 1,ad->topfile,&rcl);
                    PaintLine(hwnd,ad->hps,ad->cursored,ad->topfile,&rcl);
                  }
                  PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
                }
                break;
              case VK_DOWN:
                if(ad->cursored < ad->afifiles && ad->cursored < ad->topfile + numlines) {
                  if(shiftstate & KC_SHIFT)
                    WinSendMsg(hwnd,WM_BUTTON1CLICK,
                               MPFROM2SHORT(ad->fattrs.lAveCharWidth + 2,
                                            ((rcl.yTop - (ad->lMaxHeight *
                                            ((ad->cursored) - ad->topfile))) -
                                            ad->lMaxDescender) - 1),
                               MPFROM2SHORT(TRUE,0));
                  ad->cursored++;
                  if(ad->cursored >= ad->topfile + numlines) {
                    PaintLine(hwnd,ad->hps,ad->cursored - 2,ad->topfile,&rcl);
                    WinSendMsg(hwnd,WM_VSCROLL,MPFROM2SHORT(FID_VERTSCROLL,0),
                               MPFROM2SHORT(0,SB_LINEDOWN));
                  }
                  else {
                    PaintLine(hwnd,ad->hps,ad->cursored - 1,ad->topfile,&rcl);
                    PaintLine(hwnd,ad->hps,ad->cursored - 2,ad->topfile,&rcl);
                  }
                  PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
                }
                break;
              case VK_END:
                if((shiftstate & KC_CTRL) ||
                   ad->cursored == (ad->topfile - 1) + numlines) {
                  ad->cursored = ad->afifiles;
                  ad->topfile = (ad->afifiles + 1) - numlines;
                  if(ad->topfile > ad->afifiles)
                    ad->topfile = 1;
                  WinInvalidateRect(hwnd,NULL,FALSE);
                }
                else {
                  ad->cursored = (ad->topfile - 1) + numlines;
                  if(ad->cursored > ad->afifiles)
                    ad->cursored = ad->afifiles;
                  PaintLine(hwnd,ad->hps,ad->cursored - 1,ad->topfile,&rcl);
                  PaintLine(hwnd,ad->hps,wascursored - 1,ad->topfile,&rcl);
                  PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
                }
                break;
              case VK_HOME:
                if((shiftstate & KC_CTRL) ||
                   ad->cursored == ad->topfile) {
                  ad->topfile = 1;
                  ad->cursored = 1;
                  WinInvalidateRect(hwnd,NULL,FALSE);
                }
                else {
                  ad->cursored = ad->topfile;
                  PaintLine(hwnd,ad->hps,ad->cursored - 1,ad->topfile,&rcl);
                  PaintLine(hwnd,ad->hps,wascursored - 1,ad->topfile,&rcl);
                  PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
                }
                break;
              case VK_SPACE:
                WinSendMsg(hwnd,WM_BUTTON1CLICK,
                           MPFROM2SHORT(ad->fattrs.lAveCharWidth + 2,
                                        ((rcl.yTop - (ad->lMaxHeight *
                                        ((ad->cursored) - ad->topfile))) -
                                        ad->lMaxDescender) - 1),
                           MPFROM2SHORT(TRUE,0));
                break;
              case VK_NEWLINE:
              case VK_ENTER:
                WinSendMsg(hwnd,WM_BUTTON1DBLCLK,
                           MPFROM2SHORT(ad->fattrs.lAveCharWidth + 2,
                                        ((rcl.yTop - (ad->lMaxHeight *
                                        ((ad->cursored) - ad->topfile))) -
                                        ad->lMaxDescender) - 1),
                           MPFROM2SHORT(0,0));
                break;
            }
          }
          else if(SHORT1FROMMP(mp1) & KC_CHAR) {
            switch(SHORT1FROMMP(mp2)) {
              case '\x1b':
              case '\r':
              case '\n':
                WinSendMsg(hwnd,WM_BUTTON1DBLCLK,
                           MPFROM2SHORT(ad->fattrs.lAveCharWidth + 2,
                                        (rcl.yTop - (ad->lMaxHeight *
                                        ((ad->cursored) - ad->topfile))) - 1),
                           MPFROM2SHORT(0,0));
                ad->lasttime = 0;
                *ad->comnam = 0;
                break;
              default:
                thistime = WinQueryMsgTime(WinQueryAnchorBlock(hwnd));
                if(thistime > ad->lasttime + 1000)
                  *ad->comnam = 0;
                ad->lasttime = thistime;
KbdRetry:
                len = strlen(ad->comnam);
                if(len >= CCHMAXPATH - 1) {
                  *ad->comnam = 0;
                  len = 0;
                }
                ad->comnam[len] = toupper(SHORT1FROMMP(mp2));
                ad->comnam[len + 1] = 0;
                for(x = ad->cursored - (len > 0);x < ad->afifiles;x++) {
                  y = (ad->invertsort) ? (ad->afifiles - 1) - x : x;
                  if(ad->fullnames) {
                    if(!strnicmp(ad->afindex[y]->fullname,ad->comnam,
                                 len + 1)) {
                      found = TRUE;
                      break;
                    }
                  }
                  else {
                    if(!strnicmp(ad->afindex[y]->filename,ad->comnam,
                                 len + 1)) {
                      found = TRUE;
                      break;
                    }
                  }
                }
                if(!found) {
                  for(x = 0;x < ad->cursored - (len > 0);x++) {
                    y = (ad->invertsort) ? (ad->afifiles - 1) - x : x;
                    if(ad->fullnames) {
                      if(!strnicmp(ad->afindex[y]->fullname,ad->comnam,
                                   len + 1)) {
                        found = TRUE;
                        break;
                      }
                    }
                    else {
                      if(!strnicmp(ad->afindex[y]->filename,ad->comnam,
                                   len + 1)) {
                        found = TRUE;
                        break;
                      }
                    }
                  }
                }
                if(found) {
                  if(x + 1 != ad->cursored) {
                    ad->cursored = x + 1;
                    if(ad->cursored >= ad->topfile &&
                       ad->cursored < ad->topfile + numlines &&
                       wascursored != ad->cursored) {
                      PaintLine(hwnd,ad->hps,ad->cursored - 1,ad->topfile,&rcl);
                      PaintLine(hwnd,ad->hps,wascursored - 1,ad->topfile,&rcl);
                    }
                    else {
                      if(ad->cursored < numlines)
                        ad->topfile = 1;
                      else if(ad->cursored > (ad->afifiles + 1) - (numlines / 2))
                        ad->topfile = (ad->afifiles + 1) - numlines;
                      else
                        ad->topfile = ad->cursored - (numlines / 2);
                      WinInvalidateRect(hwnd,NULL,FALSE);
                    }
                  }
                }
                else {
                  *ad->comnam = 0;
                  ad->lasttime = 0;
                  if(len)           // retry as first letter if no match
                    goto KbdRetry;
                }
                break;
            }
          }
        }
      }
      break;

    case DM_PRINTOBJECT:
      return MRFROMLONG(DRR_TARGET);

    case DM_DISCARDOBJECT:
      return MRFROMLONG(DRR_TARGET);

    case WM_BEGINDRAG:
      {
        CHAR **list;

        list = BuildAList(hwnd);
        if(list) {
          WinSetWindowText(ad->hwndStatus,
                           GetPString(IDS_DRAGGINGFILESTEXT));
          DragList(hwnd,
                   (HWND)0,
                   list,
                   TRUE);
          FreeList(list);
          PostMsg(hwnd,
                  UM_RESCAN,
                  MPVOID,
                  MPVOID);
        }
        else
          DosBeep(50,100);
      }
      break;

    case WM_BUTTON1MOTIONSTART:
      if(ad && !ad->stopflag &&
         !DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN)) {
        ad->mousecaptured = TRUE;
        ad->lastselected = (ULONG)-1;
        ad->lastdirection = 0;
        WinSetCapture(HWND_DESKTOP,hwnd);
        DosReleaseMutexSem(ad->ScanSem);
        WinSendMsg(hwnd,WM_BUTTON1CLICK,mp1,MPFROM2SHORT(TRUE,0));
      }
      break;

    case WM_MOUSEMOVE:
      shiftstate = (SHORT2FROMMP(mp2) & (KC_SHIFT | KC_ALT | KC_CTRL));
      if(ad && ad->mousecaptured) {

        ULONG   numlines,whichfile,y,x;
        LONG    inc;
        RECTL   Rectl;
        POINTS  pts;
        BOOL    outofwindow = FALSE;

        WinQueryWindowRect(hwnd,&Rectl);
        numlines = NumLines(&Rectl,ad);
        if(numlines) {
          pts.x = SHORT1FROMMP(mp1);
          pts.y = SHORT2FROMMP(mp1);
          if(pts.y < 0) {
            WinSendMsg(hwnd,WM_VSCROLL,MPFROM2SHORT(FID_VERTSCROLL,0),
                       MPFROM2SHORT(0,SB_LINEDOWN));
            pts.y = 1;
            outofwindow = TRUE;
          }
          else if(pts.y > Rectl.yTop - Rectl.yBottom) {
            WinSendMsg(hwnd,WM_VSCROLL,MPFROM2SHORT(FID_VERTSCROLL,0),
                       MPFROM2SHORT(0,SB_LINEUP));
            pts.y = (Rectl.yTop - Rectl.yBottom) - 1;
            outofwindow = TRUE;
          }
          whichfile = ((Rectl.yTop - Rectl.yBottom) -
                       ((LONG)pts.y + ad->lMaxDescender)) /
                       ad->lMaxHeight;
          if(whichfile > numlines - 1)
            whichfile = numlines - 1;
          whichfile += (ad->topfile - 1);
          y = (ad->invertsort) ? (ad->afifiles - 1) - whichfile : whichfile;
          if(y < ad->afifiles && ad->lastselected != whichfile) {
            if(ad->lastselected != (ULONG)-1) {
              inc = (ad->lastselected < whichfile) ? 1 : -1;
              for(x = ad->lastselected + inc;
                  x != whichfile && x < ad->afifiles;
                  (ad->lastselected < whichfile) ? x++ : x--) {
                y = (ad->invertsort) ? (ad->afifiles - 1) - x : x;
                if(ad->afindex[y]->flags & AF_SELECTED) {
                  ad->afindex[y]->flags &= (~AF_SELECTED);
                  ad->selected--;
                  ad->selbytes -= ad->afindex[y]->cbFile;
                }
                else {
                  ad->afindex[y]->flags |= AF_SELECTED;
                  ad->selected++;
                  ad->selbytes += ad->afindex[y]->cbFile;
                }
                PaintLine(hwnd,ad->hps,x,ad->topfile,&Rectl);
              }
            }
            WinSendMsg(hwnd,WM_BUTTON1CLICK,MPFROM2SHORT(pts.x,pts.y),
                       MPFROM2SHORT(TRUE,0));
          }
        }
        if(outofwindow) {

          POINTL ptl;

          WinQueryPointerPos(HWND_DESKTOP,&ptl);
          WinMapWindowPoints(HWND_DESKTOP,hwnd,&ptl,1L);
          if((SHORT)ptl.y == (SHORT)SHORT2FROMMP(mp1) &&
             (SHORT)ptl.x == (SHORT)SHORT1FROMMP(mp1) &&
             ((SHORT)ptl.y < 0 || ptl.y > (Rectl.yTop - Rectl.yBottom))) {
            PostMsg(hwnd,UM_MOUSEMOVE,mp1,MPVOID);
            DosSleep(1L);
          }
        }
      }
      break;

    case UM_MOUSEMOVE:
      if(ad && ad->mousecaptured) {

        POINTL ptl;
        RECTL  Rectl;

        WinQueryWindowRect(hwnd,&Rectl);
        WinQueryPointerPos(HWND_DESKTOP,&ptl);
        WinMapWindowPoints(HWND_DESKTOP,hwnd,&ptl,1L);
        if((SHORT)ptl.y == (SHORT)SHORT2FROMMP(mp1) &&
           (SHORT)ptl.x == (SHORT)SHORT1FROMMP(mp1) &&
           ((SHORT)ptl.y < 0 || ptl.y > (Rectl.yTop - Rectl.yBottom))) {
          DosSleep(1L);
          PostMsg(hwnd,WM_MOUSEMOVE,mp1,MPFROM2SHORT(TRUE,0));
        }
      }
      return 0;

    case WM_BUTTON1UP:
    case WM_BUTTON1MOTIONEND:
      if(ad) {
        ad->mousecaptured = FALSE;
        ad->lastselected = (ULONG)-1;
        ad->lastdirection = 0;
        WinSetCapture(HWND_DESKTOP,NULLHANDLE);
      }
      break;

    case WM_BUTTON1CLICK:
    case WM_BUTTON1DBLCLK:
      shiftstate = (SHORT2FROMMP(mp2) & (KC_SHIFT | KC_ALT | KC_CTRL));
      if(ad && !ad->stopflag &&
         !DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN)) {

        ULONG   numlines,whichfile,y,wascursored;
        RECTL   Rectl;
        POINTS  pts;

        if(ad->afifiles) {
          WinQueryWindowRect(hwnd,&Rectl);
          numlines = NumLines(&Rectl,ad);
          if(numlines) {
            pts.x = SHORT1FROMMP(mp1);
            pts.y = SHORT2FROMMP(mp1);
            whichfile = ((Rectl.yTop - Rectl.yBottom) -
                         ((LONG)pts.y + ad->lMaxDescender)) /
                         ad->lMaxHeight;
            if(whichfile > numlines - 1)
              whichfile = numlines - 1;
            whichfile += (ad->topfile - 1);
            if(whichfile + 1 > ad->afifiles)
              break;
            y = (ad->invertsort) ? (ad->afifiles - 1) - whichfile : whichfile;
            wascursored = ad->cursored;
            ad->cursored = whichfile + 1;
            if(ad->cursored != wascursored)
              PaintLine(hwnd,ad->hps,wascursored - 1,ad->topfile,&Rectl);
            if(y < ad->afifiles) {
              if(msg == WM_BUTTON1CLICK || fUnHilite) {
                if(ad->afindex[y]->flags & AF_SELECTED) {
                  ad->afindex[y]->flags &= (~AF_SELECTED);
                  ad->selected--;
                  ad->selbytes -= ad->afindex[y]->cbFile;
                }
                else {
                  ad->afindex[y]->flags |= AF_SELECTED;
                  ad->selected++;
                  ad->selbytes += ad->afindex[y]->cbFile;
                }
                PaintLine(hwnd,ad->hps,whichfile,ad->topfile,&Rectl);
                PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
              }
            }
            if(msg == WM_BUTTON1CLICK) {
              if(ad->lastselected != (ULONG)-1) {
                if(whichfile > ad->lastselected)
                  ad->lastdirection = 1;
                else
                  ad->lastdirection = 2;
              }
              else
                ad->lastdirection = 0;
              ad->lastselected = whichfile;
            }
            else
              DefaultViewKeys(hwnd,ad->hwndFrame,HWND_DESKTOP,NULL,
                              ad->afindex[y]->fullname);
          }
        }
        DosReleaseMutexSem(ad->ScanSem);
      }
      break;

    case WM_MENUEND:
      if(ad && (HWND)mp2 == ad->hwndPopup) {
        WinDestroyWindow(ad->hwndPopup);
        ad->hwndPopup = (HWND)0;
      }
      break;

    case WM_CONTEXTMENU:
      if(ad) {
        if(!ad->hwndPopup) {
          ad->hwndPopup = WinLoadMenu(HWND_DESKTOP,FM3ModHandle,SEEALL_POPUP);
          if(ad->hwndPopup) {
            WinSetPresParam(ad->hwndPopup,PP_FONTNAMESIZE,
                            (ULONG)strlen(GetPString(IDS_8HELVTEXT)) + 1,
                            (PVOID)GetPString(IDS_8HELVTEXT));
            SetConditionalCascade(ad->hwndPopup,
                                  IDM_DELETESUBMENU,
                                  (fDefaultDeletePerm) ?
                                   IDM_PERMDELETE :
                                   IDM_DELETE);
            SetConditionalCascade(ad->hwndPopup,IDM_MOVEMENU,IDM_MOVE);
            SetConditionalCascade(ad->hwndPopup,IDM_COPYMENU,IDM_COPY);
            SetConditionalCascade(ad->hwndPopup,IDM_OPENSUBMENU,
                                  IDM_OPENDEFAULT);
            SetConditionalCascade(ad->hwndMenu,IDM_OBJECTSUBMENU,
                                  IDM_SHADOW);
            if(fWorkPlace) {
              WinSendMsg(ad->hwndPopup,MM_DELETEITEM,
                         MPFROM2SHORT(IDM_OPENSUBMENU,TRUE),MPVOID);
              WinSendMsg(ad->hwndPopup,MM_DELETEITEM,
                         MPFROM2SHORT(IDM_OBJECTSUBMENU,TRUE),MPVOID);
            }
          }
        }
        if(ad->hwndPopup) {

          APIRET rc;

          rc = DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN);
          WinEnableMenuItem(ad->hwndPopup,IDM_EAS,(rc == 0 &&
                                                   ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_UUDECODE,(rc == 0 &&
                                                       ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_EXTRACT,(rc == 0 &&
                                                       ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_ARCHIVE,(rc == 0 &&
                                                       ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_MOVEMENU,(rc == 0 &&
                                                        ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_COPYMENU,(rc == 0 &&
                                                        ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_RENAME,(rc == 0 &&
                                                      ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_PRINT,(rc == 0 &&
                                                     ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_SUBJECT,(rc == 0 &&
                                                       ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_OPENSUBMENU,(rc == 0 &&
                                                           ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_OBJECTSUBMENU,(rc == 0 &&
                                                             ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_DELETESUBMENU,(rc == 0 &&
                                                             ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_INFO,(rc == 0 &&
                                                    ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_ATTRS,(rc == 0 &&
                                                     ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_COLLECT,(rc == 0 &&
                                                       ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_SAVETOCLIP,(rc == 0 &&
                                                          ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_APPENDTOCLIP,(rc == 0 &&
                                                            ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_SAVETOLIST,(rc == 0 &&
                                                          ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_REMOVE,(rc == 0 &&
                                                      ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_HIDEALL,(rc == 0 &&
                                                      ad->selected != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_SELECTALL,(rc == 0 &&
                                                         ad->afifiles != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_SELECTMASK,(rc == 0 &&
                                                          ad->afifiles != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_DESELECTALL,(rc == 0 &&
                                                           ad->afifiles != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_DESELECTMASK,(rc == 0 &&
                                                            ad->afifiles != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_INVERT,(rc == 0 &&
                                                      ad->afifiles != 0));
          WinEnableMenuItem(ad->hwndPopup,IDM_FILTER,(rc == 0 &&
                                                      ad->affiles != 0));
          if(!rc)
            DosReleaseMutexSem(ad->ScanSem);
          if(WinPopupMenu(hwnd,hwnd,ad->hwndPopup,SHORT1FROMMP(mp1),
                          SHORT2FROMMP(mp1),0,
                          PU_HCONSTRAIN | PU_VCONSTRAIN |
                          PU_KEYBOARD   | PU_MOUSEBUTTON1))
            CenterOverWindow(ad->hwndPopup);
        }
      }
      break;

    case UM_CONTAINER_FILLED:
      if(ad) {
        ad->stopflag = 0;
        ad->topfile = 1;
        ad->cursored = 1;
        ad->multiplier = 1;
        if(!ad->afifiles) {
          DosBeep(250,50);
          PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
        }
        else {
          DosBeep(1000,25);
          WinInvalidateRect(hwnd,NULL,FALSE);
          PostMsg(hwnd,UM_SETUP3,MPVOID,MPVOID);
        }
        WinSetWindowPos(WinQueryWindow(hwnd,QW_PARENT),HWND_TOP,0,0,0,0,
                        SWP_SHOW | SWP_RESTORE | SWP_ACTIVATE | SWP_ZORDER);
      }
      return 0;

    case WM_ERASEBACKGROUND:
      WinFillRect((HPS)mp1,(PRECTL)mp2,
                  standardcolors[Colors[COLORS_NORMALBACK]]);
      return 0;

    case WM_PAINT:
// fprintf(stderr,"Seeall: WM_PAINT\n");
      if(ad) {

        HPS       hpsp;
        RECTL     Rectl;
        POINTL    ptl;
        register ULONG x;
        ULONG     y,len,numlines;
        CHAR      szBuff[CCHMAXPATH + 80];
        BOOL      inverted,hidsys,reado,wascursored;

        hpsp = WinBeginPaint(hwnd,ad->hps,&Rectl);
        WinFillRect(hpsp,&Rectl,standardcolors[Colors[COLORS_NORMALBACK]]);
        if(!ad->stopflag &&
           !DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN)) {
          WinQueryWindowRect(hwnd,&Rectl);
          numlines = NumLines(&Rectl,ad);
          if(ad->afifiles && numlines) {
            if(ad->topfile > (ad->afifiles + 1) - numlines)
              ad->topfile = (ad->afifiles + 1) - numlines;
            if(ad->topfile > ad->afifiles)
              ad->topfile = 1;
            if(!ad->topfile)
              ad->topfile = 1;
            if(ad->cursored < ad->topfile)
              ad->cursored = ad->topfile;
            else if(ad->cursored > (ad->topfile + numlines) - 1)
              ad->cursored = (ad->topfile + numlines) - 1;
            if(ad->cursored > ad->afifiles)
              ad->cursored = ad->afifiles;
          }
          else
            ad->topfile = ad->cursored = 1;
          if(numlines && ad->afifiles) {
            GpiSetBackMix(hpsp,BM_OVERPAINT);
            wascursored = TRUE;
            for(x = ad->topfile - 1;x < ad->afifiles;x++) {
              ptl.x = ad->horzscroll;
              if(wascursored) { /* reestablish normal colors */
                GpiSetColor(ad->hps,
                            standardcolors[Colors[COLORS_NORMALFORE]]);
                GpiSetBackColor(ad->hps,
                                standardcolors[Colors[COLORS_NORMALBACK]]);
                wascursored = inverted = hidsys = reado = FALSE;
              }
              if(x == ad->cursored - 1)
                wascursored = TRUE;
              y = (ad->invertsort) ? (ad->afifiles - 1) - x : x;
              ptl.y = (Rectl.yTop -
                       (ad->lMaxHeight * (((x + 1) - ad->topfile) + 1)));
              if(ptl.y - ad->lMaxDescender <= 0)
                break;
              if(ad->afindex[y]->flags & AF_SELECTED) {
                if(!inverted) {
                  GpiSetColor(ad->hps,standardcolors[Colors[COLORS_SELECTEDNORMALFORE]]);
                  GpiSetBackColor(ad->hps,(wascursored) ?
                                  standardcolors[Colors[COLORS_CURSOREDSELECTEDBACK]] :
                                  standardcolors[Colors[COLORS_SELECTEDBACK]]);
                  inverted = TRUE;
                }
              }
              else if(inverted ||
                      ((ad->afindex[y]->attrFile &
                       (FILE_SYSTEM | FILE_HIDDEN)) != 0) != hidsys ||
                      ((ad->afindex[y]->attrFile & FILE_READONLY) != 0) !=
                      reado) {
                if(ad->afindex[y]->attrFile & (FILE_SYSTEM | FILE_HIDDEN)) {
                  GpiSetColor(ad->hps,
                              standardcolors[Colors[COLORS_SYSTEMFORE]]);
                  hidsys = TRUE;
                }
                else if((ad->afindex[y]->attrFile & FILE_READONLY) != 0) {
                  GpiSetColor(ad->hps,
                              standardcolors[Colors[COLORS_READONLYFORE]]);
                  reado = TRUE;
                }
                else
                  GpiSetColor(ad->hps,standardcolors[Colors[COLORS_NORMALFORE]]);
                GpiSetBackColor(ad->hps,(wascursored) ?
                                standardcolors[Colors[COLORS_CURSOREDNORMALBACK]] :
                                standardcolors[Colors[COLORS_NORMALBACK]]);
                inverted = FALSE;
              }
              else if(wascursored)
                GpiSetBackColor(ad->hps,
                                standardcolors[Colors[COLORS_CURSOREDNORMALBACK]]);
              len = sprintf(szBuff,
                            "%c%-*.*s  %-12lu  %c%c%c%c%c  %04u/%02u/%02u %02u:%02u:%02u ",
                            (wascursored) ? '>': ' ',
                            (ad->fullnames) ? ad->longestw : ad->longest,
                            (ad->fullnames) ? ad->longestw : ad->longest,
                            (ad->fullnames) ? ad->afindex[y]->fullname :
                                              ad->afindex[y]->filename,
                            ad->afindex[y]->cbFile,
                            "-A"[((ad->afindex[y]->attrFile & FILE_ARCHIVED) != 0)],
                            "-R"[((ad->afindex[y]->attrFile & FILE_READONLY) != 0)],
                            "-H"[((ad->afindex[y]->attrFile & FILE_HIDDEN) != 0)],
                            "-S"[((ad->afindex[y]->attrFile & FILE_SYSTEM) != 0)],
                            "-D"[((ad->afindex[y]->attrFile & FILE_DIRECTORY) != 0)],
                            ad->afindex[y]->date.year + 1980,
                            ad->afindex[y]->date.month,
                            ad->afindex[y]->date.day,
                            ad->afindex[y]->time.hours,
                            ad->afindex[y]->time.minutes,
                            ad->afindex[y]->time.twosecs * 2);
              GpiCharStringAt(hpsp,&ptl,len,szBuff);
              GpiQueryCurrentPosition(hpsp,&ptl);
              if(ptl.x + abs(ad->horzscroll) > ad->maxx) {
                ad->maxx = ptl.x + abs(ad->horzscroll);
                WinSendMsg(ad->hhscroll,SBM_SETTHUMBSIZE,
                           MPFROM2SHORT((SHORT)Rectl.xRight,(SHORT)ad->maxx),
                           MPVOID);
              }
            }
          }
          DosReleaseMutexSem(ad->ScanSem);
        }
        WinEndPaint(hpsp);
        PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
        if(!ad->stopflag)
          WinSendMsg(ad->hvscroll,SBM_SETSCROLLBAR,
                     MPFROMSHORT((SHORT)(ad->topfile / ad->multiplier)),
                     MPFROM2SHORT(1,
                                  (SHORT)(ad->afifiles / ad->multiplier) -
                                          (numlines - 1)));
        WinSendMsg(ad->hhscroll,SBM_SETSCROLLBAR,
                   MPFROMSHORT((SHORT)abs(ad->horzscroll)),
                   MPFROM2SHORT(0,(SHORT)(ad->maxx - Rectl.xRight)));
        WinSendMsg(ad->hhscroll,SBM_SETTHUMBSIZE,
                   MPFROM2SHORT((SHORT)Rectl.xRight,(SHORT)ad->maxx),
                   MPVOID);
      }
      break;

    case WM_HSCROLL:
      {
        RECTL rectl;
        BOOL  invalidate = TRUE;

        WinQueryWindowRect(hwnd,&rectl);
        switch(SHORT2FROMMP(mp2)) {
          case SB_PAGERIGHT:
            if(abs(ad->horzscroll) < ad->maxx - rectl.xRight) {
              ad->horzscroll -= rectl.xRight;
              if(abs(ad->horzscroll) > ad->maxx - rectl.xRight)
                ad->horzscroll = -(ad->maxx - rectl.xRight);
            }
            break;

          case SB_PAGELEFT:
            if(ad->horzscroll < 0) {
              ad->horzscroll += rectl.xRight;
              if(ad->horzscroll > 0)
                ad->horzscroll = 0;
            }
            break;

          case SB_LINERIGHT:
            if(abs(ad->horzscroll) < ad->maxx - rectl.xRight)
              ad->horzscroll -= ad->fattrs.lAveCharWidth;
            break;

          case SB_LINELEFT:
            if(ad->horzscroll < 0)
              ad->horzscroll += ad->fattrs.lAveCharWidth;
            break;

          case SB_SLIDERTRACK:
            ad->horzscroll = SHORT1FROMMP(mp2);
            ad->horzscroll = -(ad->horzscroll);
            if(ad->horzscroll > 0)
              ad->horzscroll = 0;
            if(abs(ad->horzscroll) > ad->maxx - rectl.xRight)
              ad->horzscroll = -(ad->maxx - rectl.xRight);
            break;

          default:
            invalidate = FALSE;
            break;
        }
        if(invalidate)
          WinInvalidateRect(hwnd,NULL,FALSE);
      }
      break;

    case WM_VSCROLL:
// fprintf(stderr,"Seeall: WM_VSCROLL\n");
      if(ad && !ad->stopflag &&
         !DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN)) {

        ULONG numlines,wascursored;
        RECTL rcl;

        if(ad->afifiles) {
          WinQueryWindowRect(hwnd,&rcl);
          numlines = NumLines(&rcl,ad);
          if(numlines) {
            wascursored = ad->cursored;
            switch(SHORT2FROMMP(mp2)) {
              case SB_PAGEUP:
                if(ad->topfile > 1) {
                  ad->topfile -= numlines;
                  if(ad->topfile > ad->afifiles ||
                     ad->topfile > (ad->afifiles + 1) - numlines)
                    ad->topfile = 1;
                  if(ad->cursored > ad->topfile + numlines)
                    ad->cursored = ad->topfile + numlines;
                  if(ad->cursored > ad->afifiles)
                    ad->cursored = ad->afifiles;
                  WinInvalidateRect(hwnd,NULL,FALSE);
                }
                break;
              case SB_PAGEDOWN:
                if(ad->topfile <= ad->afifiles - numlines) {
                  ad->topfile += numlines;
                  if(ad->topfile > (ad->afifiles + 1) - numlines)
                    ad->topfile = (ad->afifiles + 1) - numlines;
                  if(ad->cursored < ad->topfile)
                    ad->cursored = ad->topfile;
                  if(ad->cursored > (ad->topfile + numlines) - 1)
                    ad->cursored = (ad->topfile + numlines) - 1;
                  if(ad->cursored > ad->afifiles)
                    ad->cursored = ad->afifiles;
                  WinInvalidateRect(hwnd,NULL,FALSE);
                }
                break;
              case SB_LINEDOWN:
                if(ad->topfile <= ad->afifiles - numlines) {

                  RECTL Rectl,iRectl;

                  ad->topfile++;
                  if(ad->cursored < ad->topfile)
                    ad->cursored = ad->topfile;
                  else if(ad->cursored > (ad->topfile + numlines) - 1)
                    ad->cursored = (ad->topfile + numlines) - 1;
                  if(ad->cursored > ad->afifiles)
                    ad->cursored = ad->afifiles;
                  WinQueryWindowRect(hwnd,&Rectl);
                  WinScrollWindow(hwnd,0,ad->lMaxHeight,
                                  NULL,NULL,NULLHANDLE,&iRectl,0);
                  WinFillRect(ad->hps,&iRectl,
                              standardcolors[Colors[COLORS_NORMALBACK]]);
                  PaintLine(hwnd,ad->hps,(ad->topfile + numlines) - 2,
                            ad->topfile,&Rectl);
                  if(ad->cursored != ad->topfile + numlines)
                    PaintLine(hwnd,ad->hps,ad->cursored - 1,ad->topfile,&Rectl);
                  if(wascursored != ad->cursored &&
                     wascursored < ad->topfile + numlines &&
                     wascursored >= ad->topfile)
                    PaintLine(hwnd,ad->hps,wascursored - 1,ad->topfile,&Rectl);
                  if(wascursored != ad->cursored)
                    PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
                  WinSendMsg(ad->hhscroll,SBM_SETSCROLLBAR,
                             MPFROMSHORT((SHORT)abs(ad->horzscroll)),
                             MPFROM2SHORT(0,(SHORT)(ad->maxx - Rectl.xRight)));
                  WinSendMsg(ad->hvscroll,SBM_SETSCROLLBAR,
                             MPFROMSHORT((SHORT)(ad->topfile /
                                                 ad->multiplier)),
                             MPFROM2SHORT(1,(SHORT)(ad->afifiles /
                                                    ad->multiplier) -
                                                    (numlines - 1)));
                }
                break;
              case SB_LINEUP:
                if(ad->topfile > 1) {

                  RECTL Rectl,iRectl;

                  ad->topfile--;
                  if(ad->cursored < ad->topfile)
                    ad->cursored = ad->topfile;
                  else if(ad->cursored > (ad->topfile + numlines) - 1)
                    ad->cursored = (ad->topfile + numlines) - 1;
                  if(ad->cursored > ad->afifiles)
                    ad->cursored = ad->afifiles;
                  WinQueryWindowRect(hwnd,&Rectl);
                  WinScrollWindow(hwnd,0,-ad->lMaxHeight,
                                  NULL,NULL,NULLHANDLE,&iRectl,0);
                  WinFillRect(ad->hps,&iRectl,
                              standardcolors[Colors[COLORS_NORMALBACK]]);
                  iRectl = Rectl;
                  iRectl.yTop -= ((numlines * ad->lMaxHeight) +
                                  ad->lMaxDescender);
                  WinFillRect(ad->hps,&iRectl,
                              standardcolors[ad->colors[COLORS_NORMALBACK]]);
                  PaintLine(hwnd,ad->hps,ad->topfile - 1,ad->topfile,&Rectl);
                  if(ad->cursored != ad->topfile)
                    PaintLine(hwnd,ad->hps,ad->cursored - 1,ad->topfile,&Rectl);
                  if(ad->cursored != wascursored &&
                     wascursored >= ad->topfile &&
                     wascursored < ad->topfile + numlines)
                    PaintLine(hwnd,ad->hps,wascursored - 1,ad->topfile,&Rectl);
                  if(ad->cursored != wascursored)
                    PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
                  WinSendMsg(ad->hhscroll,SBM_SETSCROLLBAR,
                             MPFROMSHORT((SHORT)abs(ad->horzscroll)),
                             MPFROM2SHORT(0,(SHORT)(ad->maxx - Rectl.xRight)));
                  WinSendMsg(ad->hvscroll,SBM_SETSCROLLBAR,
                             MPFROMSHORT((SHORT)(ad->topfile /
                                                 ad->multiplier)),
                             MPFROM2SHORT(1,(SHORT)(ad->afifiles /
                                                    ad->multiplier) -
                                                    (numlines - 1)));
                }
                break;
              case SB_SLIDERTRACK:
                if((SHORT1FROMMP(mp2) >= 1) ||
                   (SHORT1FROMMP(mp2)) <= ad->afifiles) {
                  ad->topfile = (ULONG)SHORT1FROMMP(mp2) * ad->multiplier;
                  if(ad->topfile > (ad->afifiles + 1) - numlines)
                    ad->topfile = (ad->afifiles + 1) - numlines;
                  if(!ad->topfile)
                    ad->topfile = 1;
                  if(ad->cursored < ad->topfile)
                    ad->cursored = ad->topfile;
                  else if(ad->cursored > ad->topfile + numlines)
                    ad->cursored = ad->topfile + numlines;
                  if(ad->cursored > ad->afifiles)
                    ad->cursored = ad->afifiles;
                  WinInvalidateRect(hwnd,NULL,FALSE);
                }
                else
                  WinAlarm(HWND_DESKTOP,WA_NOTE);
                break;
            }
          }
        }
        DosReleaseMutexSem(ad->ScanSem);
      }
      break;

    case WM_INITMENU:
      if(ad) {
        switch(SHORT1FROMMP(mp1)) {
          case IDM_FILESMENU:
            {
              APIRET rc;

              rc = DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN);
              WinEnableMenuItem((HWND)mp2,IDM_DUPES,(rc == 0));
              WinEnableMenuItem((HWND)mp2,IDM_COLLECT,(rc == 0 &&
                                                       ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_SAVETOCLIP,(rc == 0 &&
                                                       ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_APPENDTOCLIP,(rc == 0 &&
                                                       ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_SAVETOLIST,(rc == 0 &&
                                                       ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_REMOVE,(rc == 0 &&
                                                      ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_HIDEALL,(rc == 0 &&
                                                      ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_DELETESUBMENU,(rc == 0 &&
                                                             ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_INFO,(rc == 0 &&
                                                    ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_ATTRS,(rc == 0 &&
                                                     ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_EAS,(rc == 0 &&
                                                   ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_UUDECODE,(rc == 0 &&
                                                       ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_EXTRACT,(rc == 0 &&
                                                       ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_ARCHIVE,(rc == 0 &&
                                                       ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_MOVEMENU,(rc == 0 &&
                                                        ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_COPYMENU,(rc == 0 &&
                                                        ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_RENAME,(rc == 0 &&
                                                      ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_PRINT,(rc == 0 &&
                                                     ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_SUBJECT,(rc == 0 &&
                                                       ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_OPENSUBMENU,(rc == 0 &&
                                                           ad->selected != 0));
              WinEnableMenuItem((HWND)mp2,IDM_OBJECTSUBMENU,(rc == 0 &&
                                                             ad->selected != 0));
              if(!rc)
                DosReleaseMutexSem(ad->ScanSem);
            }
            break;

          case IDM_SELECTSUBMENU:
            {
              APIRET rc;

              rc = DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN);
              WinEnableMenuItem((HWND)mp2,IDM_SELECTALL,(rc == 0 &&
                                                         ad->afifiles != 0 &&
                                                         (ad->afifiles !=
                                                           ad->selected ||
                                                           !ad->selected)));
              WinEnableMenuItem((HWND)mp2,IDM_SELECTMASK,(rc == 0 &&
                                                          ad->afifiles != 0 &&
                                                          (ad->afifiles !=
                                                           ad->selected ||
                                                           !ad->selected)));
              WinEnableMenuItem((HWND)mp2,IDM_DESELECTALL,(rc == 0 &&
                                                           ad->afifiles != 0 &&
                                                           ad->selected));
              WinEnableMenuItem((HWND)mp2,IDM_DESELECTMASK,(rc == 0 &&
                                                            ad->afifiles != 0) &&
                                                            ad->selected);
              WinEnableMenuItem((HWND)mp2,IDM_INVERT,(rc == 0 &&
                                                      ad->afifiles != 0));
              if(!rc)
                DosReleaseMutexSem(ad->ScanSem);
            }
            break;

          case IDM_SORTSUBMENU:
            {
              APIRET rc;

              rc = DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN);
              WinEnableMenuItem((HWND)mp2,IDM_SORTNAME,(rc == 0));
              WinEnableMenuItem((HWND)mp2,IDM_SORTEASIZE,(rc == 0));
              WinEnableMenuItem((HWND)mp2,IDM_SORTSIZE,(rc == 0));
              WinEnableMenuItem((HWND)mp2,IDM_SORTLWDATE,(rc == 0));
              WinEnableMenuItem((HWND)mp2,IDM_SORTFILENAME,(rc == 0));
              WinEnableMenuItem((HWND)mp2,IDM_SORTFIRST,(rc == 0));
              if(!rc)
                DosReleaseMutexSem(ad->ScanSem);
            }
            WinCheckMenuItem((HWND)mp2,IDM_SORTNAME,
                             (ad->compare == comparefullnames));
            WinCheckMenuItem((HWND)mp2,IDM_SORTEASIZE,
                             (ad->compare == (PFNSORT)NULL));
            WinCheckMenuItem((HWND)mp2,IDM_SORTSIZE,
                             (ad->compare == comparesizes));
            WinCheckMenuItem((HWND)mp2,IDM_SORTLWDATE,
                             (ad->compare == comparedates));
            WinCheckMenuItem((HWND)mp2,IDM_SORTFILENAME,
                             (ad->compare == comparenames));
            WinCheckMenuItem((HWND)mp2,IDM_SORTREVERSE,ad->invertsort);
            WinCheckMenuItem((HWND)mp2,IDM_SORTFIRST,
                             (ad->compare == compareexts));
            break;

          case IDM_VIEWSMENU:
            {
              APIRET rc;

              rc = DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN);
              WinEnableMenuItem((HWND)mp2,IDM_RESCAN,(rc == 0));
              WinEnableMenuItem((HWND)mp2,IDM_FILTER,(rc == 0 &&
                                                      ad->affiles != 0));
              if(!rc)
                DosReleaseMutexSem(ad->ScanSem);
            }
            WinCheckMenuItem((HWND)mp2,IDM_SHOWLNAMES,ad->fullnames);
            break;
        }
      }
      break;

    case WM_COMMAND:
      if(!ad)
        return 0;
      switch(SHORT1FROMMP(mp1)) {
        case IDM_SETTARGET:
          SetTargetDir(hwnd,FALSE);
          break;

        case IDM_DUPES:
          if(!ad->stopflag &&
             !DosRequestMutexSem(ad->ScanSem,
                                 SEM_IMMEDIATE_RETURN)) {
            ad->dupeflags = (USHORT)WinDlgBox(HWND_DESKTOP,
                                              hwnd,
                                              DupeDlgProc,
                                              FM3ModHandle,
                                              DUPE_FRAME,
                                              MPFROM2SHORT(ad->dupeflags,0));
            if(ad->dupeflags) {
              if(_beginthread(FindDupes,
                              NULL,
                              65536,
                              (PVOID)hwnd) == -1)
                DosBeep(50,100);
            }
            DosReleaseMutexSem(ad->ScanSem);
          }
          break;

        case IDM_COLORPALETTE:
          {
            COLORS co;
            LONG   temp[COLORS_MAX];

            memset(&co,0,sizeof(co));
            co.size = sizeof(co);
            co.numcolors = COLORS_MAX;
            co.colors = ad->colors;
            co.descriptions = IDS_SACOLORS1TEXT;
            co.origs = temp;
            co.prompt = IDS_SACOLORSPROMPTTEXT;
            memcpy(temp,
                   ad->colors,
                   sizeof(LONG) * COLORS_MAX);
            if(WinDlgBox(HWND_DESKTOP,
                         hwnd,
                         ColorDlgProc,
                         FM3ModHandle,
                         COLOR_FRAME,
                         (PVOID)&co)) {
              memcpy(Colors,
                     ad->colors,
                     sizeof(LONG) * COLORS_MAX);
              PrfWriteProfileData(fmprof,
                                  appname,
                                  "Seeall.Colors",
                                  &ad->colors,
                                  sizeof(LONG) * COLORS_MAX);
              WinInvalidateRect(hwnd,
                                NULL,
                                FALSE);
            }
          }
          break;

        case IDM_CODEPAGE:
          {
            INT cp;

            cp = PickCodepage(hwnd);
            if(cp != -1) {
              ad->fattrs.usCodePage = (USHORT)cp;
              Codepage = ad->fattrs.usCodePage;
              PrfWriteProfileData(fmprof,
                                  appname,
                                  "Seeall.Codepage",
                                  &ad->fattrs.usCodePage,
                                  sizeof(USHORT));
              GpiDeleteSetId(ad->hps,FIXED_FONT_LCID);
              GpiAssociate(ad->hps,0);
              GpiDestroyPS(ad->hps);
              ad->hps = InitWindow(hwnd);
              ad->maxx = ad->horzscroll = 0;
              WinInvalidateRect(hwnd,NULL,FALSE);
            }
          }
          break;

        case IDM_FONTPALETTE:
          SetMLEFont(hwnd,&ad->fattrs,11);
          PrfWriteProfileData(fmprof,
                              appname,
                              "Seeall.Fattrs",
                              &ad->fattrs,
                              sizeof(FATTRS));
          Fattrs = ad->fattrs;
          GpiDeleteSetId(ad->hps,FIXED_FONT_LCID);
          GpiAssociate(ad->hps,0);
          GpiDestroyPS(ad->hps);
          ad->hps = InitWindow(hwnd);
          ad->maxx = ad->horzscroll = 0;
          WinInvalidateRect(hwnd,NULL,FALSE);
          break;

        case IDM_SHOWLNAMES:
          ad->fullnames = (ad->fullnames) ? FALSE : TRUE;
          PrfWriteProfileData(fmprof,
                              appname,
                              "Seeall.Fullnames",
                              &ad->fullnames,
                              sizeof(BOOL));
          Fullnames = ad->fullnames;
          ad->maxx = ad->horzscroll = 0;
          WinInvalidateRect(hwnd,NULL,FALSE);
          break;

        case IDM_SORTREVERSE:
          ad->invertsort = (ad->invertsort) ? FALSE : TRUE;
          SortReverse = ad->invertsort;
          PrfWriteProfileData(fmprof,
                              appname,
                              "Seeall.SortReverse",
                              (PVOID)&ad->invertsort,
                              sizeof(BOOL));
          WinInvalidateRect(hwnd,NULL,FALSE);
          break;

        case IDM_SORTEASIZE:
        case IDM_SORTNAME:
        case IDM_SORTFILENAME:
        case IDM_SORTSIZE:
        case IDM_SORTLWDATE:
        case IDM_SORTFIRST:
          if(!ad->stopflag &&
             !DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN)) {
            {
              USHORT dummy = SHORT1FROMMP(mp1);

              PrfWriteProfileData(fmprof,
                                  appname,
                                  "Seeall.Sort",
                                  (PVOID)&dummy,
                                  sizeof(USHORT));
              SortType = SHORT1FROMMP(mp1);
            }
            WinSetPointer(HWND_DESKTOP,hptrBusy);
            WinSendMsg(hwnd,UM_RESCAN,MPFROMLONG(1L),MPVOID);
            switch(SHORT1FROMMP(mp1)) {
              case IDM_SORTEASIZE:
                ad->compare = (PFNSORT)NULL;
                ReSort(hwnd);
                break;

              case IDM_SORTNAME:
                ad->compare = comparefullnames;
                ReSort(hwnd);
                break;

              case IDM_SORTFILENAME:
                ad->compare = comparenames;
                ReSort(hwnd);
                break;

              case IDM_SORTSIZE:
                ad->compare = comparesizes;
                ReSort(hwnd);
                break;

              case IDM_SORTLWDATE:
                ad->compare = comparedates;
                ReSort(hwnd);
                break;

              case IDM_SORTFIRST:
                ad->compare = compareexts;
                ReSort(hwnd);
                break;
            }
            WinSetPointer(HWND_DESKTOP,hptrArrow);
            DosReleaseMutexSem(ad->ScanSem);
            WinInvalidateRect(hwnd,NULL,FALSE);
          }
          break;

        case IDM_FILTER:
          if(!ad->stopflag &&
             !DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN)) {
            FilterList(hwnd);
            DosReleaseMutexSem(ad->ScanSem);
          }
          break;

        case IDM_RESCAN:
          if(!ad->stopflag &&
             !DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN)) {

            CHAR tempflags[26];

            memcpy(tempflags,ad->drvsflags,sizeof(tempflags));
            if(!WinDlgBox(HWND_DESKTOP,hwnd,AFDrvsWndProc,FM3ModHandle,
                          DRVS_FRAME,(PVOID)ad)) {
              memcpy(ad->drvsflags,tempflags,sizeof(tempflags));
              *ad->findpath = 0;
              DosReleaseMutexSem(ad->ScanSem);
              break;
            }
            WinSendMsg(ad->hhscroll,SBM_SETTHUMBSIZE,MPFROM2SHORT(1,1),
                       MPVOID);
            WinSendMsg(ad->hvscroll,SBM_SETTHUMBSIZE,MPFROM2SHORT(1,1),
                       MPVOID);
            ad->topfile = 1;
            ad->cursored = 1;
            ad->selected = ad->selbytes = 0;
            ad->maxx = ad->horzscroll = 0;
            FreeAllFilesList(hwnd);
            ad->stopflag = 0;
            if(_beginthread(FindAll,NULL,524288,(PVOID)hwnd) != -1) {
              DosReleaseMutexSem(ad->ScanSem);
              DosSleep(100);
              WinInvalidateRect(hwnd,NULL,FALSE);
              PostMsg(hwnd,UM_SETUP2,MPVOID,MPVOID);
              PostMsg(hwnd,UM_RESCAN,MPVOID,MPVOID);
            }
            else {
              DosBeep(250,100);
              WinDestroyWindow(WinQueryWindow(hwnd,QW_PARENT));
              DosReleaseMutexSem(ad->ScanSem);
            }
          }
          break;

        case IDM_DELETE:
        case IDM_PERMDELETE:
        case IDM_SELECTALL:
        case IDM_DESELECTALL:
        case IDM_INVERT:
        case IDM_SELECTMASK:
        case IDM_DESELECTMASK:
        case IDM_REMOVE:
        case IDM_HIDEALL:
        case IDM_COLLECT:
        case IDM_COLLECTOR:
        case IDM_SAVETOCLIP:
        case IDM_APPENDTOCLIP:
        case IDM_SAVETOLIST:
        case IDM_INFO:
        case IDM_ATTRS:
        case IDM_MOVE:
        case IDM_COPY:
        case IDM_RENAME:
        case IDM_MOVEPRESERVE:
        case IDM_COPYPRESERVE:
        case IDM_WILDMOVE:
        case IDM_WILDCOPY:
        case IDM_SUBJECT:
        case IDM_EAS:
        case IDM_PRINT:
        case IDM_ARCHIVE:
        case IDM_EXTRACT:
        case IDM_UUDECODE:
        case IDM_SHADOW:
        case IDM_OBJECT:
        case IDM_OPENSETTINGS:
        case IDM_OPENDEFAULT:
          if(!ad->stopflag &&
             !DosRequestMutexSem(ad->ScanSem,SEM_IMMEDIATE_RETURN)) {
            switch(SHORT1FROMMP(mp1)) {
              case IDM_SELECTALL:
              case IDM_DESELECTALL:
              case IDM_INVERT:
              case IDM_HIDEALL:
              case IDM_REMOVE:
                Mark(hwnd,(SHORT1FROMMP(mp1) == IDM_DESELECTALL) ?
                     AFM_UNMARK : (SHORT1FROMMP(mp1) == IDM_INVERT) ?
                     AFM_INVERT : (SHORT1FROMMP(mp1) == IDM_HIDEALL) ?
                     AFM_FILTER : (SHORT1FROMMP(mp1) == IDM_REMOVE) ?
                     AFM_MARKDELETED : 0,NULL);
                if(SHORT1FROMMP(mp1) == IDM_REMOVE ||
                   SHORT1FROMMP(mp1) == IDM_HIDEALL) {
                  if(SHORT1FROMMP(mp1) == IDM_REMOVE)
                    RemoveDeleted(hwnd);
                  else
                    ReSort(hwnd);
                }
                WinInvalidateRect(hwnd,NULL,FALSE);
                break;

              case IDM_SELECTMASK:
              case IDM_DESELECTMASK:
                SelectMask(hwnd,(SHORT1FROMMP(mp1) == IDM_DESELECTMASK));
                WinInvalidateRect(hwnd,NULL,FALSE);
                break;

              case IDM_DELETE:
              case IDM_PERMDELETE:
              case IDM_APPENDTOCLIP:
              case IDM_SAVETOCLIP:
              case IDM_SAVETOLIST:
              case IDM_COLLECT:
              case IDM_INFO:
              case IDM_ATTRS:
              case IDM_MOVE:
              case IDM_COPY:
              case IDM_RENAME:
              case IDM_MOVEPRESERVE:
              case IDM_COPYPRESERVE:
              case IDM_WILDMOVE:
              case IDM_WILDCOPY:
              case IDM_SUBJECT:
              case IDM_PRINT:
              case IDM_EAS:
              case IDM_ARCHIVE:
              case IDM_EXTRACT:
              case IDM_SHADOW:
              case IDM_OBJECT:
              case IDM_OPENSETTINGS:
              case IDM_OPENDEFAULT:
              case IDM_UUDECODE:
                {
                  CHAR **list = BuildAList(hwnd);

                  if(list) {
                    switch(SHORT1FROMMP(mp1)) {
                      case IDM_COLLECT:
                        CollectList(hwnd,list);
                        break;
                      case IDM_DELETE:
                      case IDM_PERMDELETE:
                      case IDM_APPENDTOCLIP:
                      case IDM_SAVETOCLIP:
                      case IDM_SAVETOLIST:
                      case IDM_INFO:
                      case IDM_ATTRS:
                      case IDM_MOVE:
                      case IDM_COPY:
                      case IDM_RENAME:
                      case IDM_MOVEPRESERVE:
                      case IDM_COPYPRESERVE:
                      case IDM_WILDMOVE:
                      case IDM_WILDCOPY:
                      case IDM_SUBJECT:
                      case IDM_PRINT:
                      case IDM_EAS:
                      case IDM_ARCHIVE:
                      case IDM_EXTRACT:
                      case IDM_UUDECODE:
                      case IDM_OBJECT:
                      case IDM_SHADOW:
                      case IDM_OPENSETTINGS:
                      case IDM_OPENDEFAULT:
                        if(!PostMsg(ad->hwndObj,UM_MASSACTION,mp1,
                                       MPFROMP(list)))
                          FreeList(list);
                        break;
                    }
                    if(fUnHilite) {
                      Mark(hwnd,AFM_UNMARK,NULL);
                      WinInvalidateRect(hwnd,NULL,FALSE);
                    }
                  }
                  else
                    DosBeep(50,100);
                }
                break;

              case IDM_COLLECTOR:
                if(mp2) {

                  CHAR **list = mp2;

                  if(Collector) {
                    if(!PostMsg(Collector,WM_COMMAND,
                                   MPFROM2SHORT(IDM_COLLECTOR,0),
                                   MPFROMP(list)))
                      FreeList(list);
                    else if(fUnHilite) {
                      Mark(hwnd,AFM_UNMARK,NULL);
                      WinInvalidateRect(hwnd,NULL,FALSE);
                    }
                  }
                  else
                    FreeList(list);
                }
                break;
            }
            DosReleaseMutexSem(ad->ScanSem);
          }
          else if(SHORT1FROMMP(mp1) == IDM_COLLECTOR) {
            DosSleep(100L);
            if(!PostMsg(hwnd,msg,mp1,mp2))
              WinSendMsg(hwnd,msg,mp1,mp2);
          }
          break;

        case IDM_HELP:
          if(hwndHelp)
            WinSendMsg(hwndHelp,
                       HM_DISPLAY_HELP,
                       MPFROM2SHORT(HELP_SEEALL,0),
                       MPFROMSHORT(HM_RESOURCEID));
          break;
      }
      return 0;

    case WM_SIZE:
// fprintf(stderr,"Seeall: WM_SIZE\n");
      PostMsg(hwnd,
              UM_SETUP3,
              MPVOID,
              MPVOID);
      break;

    case WM_CLOSE:
// fprintf(stderr,"Seeall: WM_CLOSE\n");
      if(ad)
        ad->stopflag = 1;
      WinDestroyWindow(WinQueryWindow(hwnd,QW_PARENT));
      return 0;

    case WM_DESTROY:
// fprintf(stderr,"Seeall: WM_DESTROY\n");
      if(ad) {
        ad->stopflag = 1;
        if(ad->ScanSem) {
          DosRequestMutexSem(ad->ScanSem,15000L);
          DosCloseMutexSem(ad->ScanSem);
        }
        if(ad->hwndPopup)
          WinDestroyWindow(ad->hwndPopup);
        if(ad->hwndObj) {
          if(!PostMsg(ad->hwndObj,
                      WM_CLOSE,
                      MPVOID,
                      MPVOID))
            WinSendMsg(ad->hwndObj,
                       WM_CLOSE,
                       MPVOID,
                       MPVOID);
        }
        if(ad->hps) {
          GpiDeleteSetId(ad->hps,
                         FIXED_FONT_LCID);
          GpiAssociate(ad->hps,0);
          GpiDestroyPS(ad->hps);
        }
        if(ad->killme) {
          if(!PostMsg((HWND)0,
                      WM_QUIT,
                      MPVOID,
                      MPVOID))
            WinSendMsg((HWND)0,
                       WM_QUIT,
                       MPVOID,
                       MPVOID);
        }
        FreeAllFilesList(hwnd);
        free(ad);
      }
      break;
  }

  return WinDefWindowProc(hwnd,msg,mp1,mp2);
}


HWND StartSeeAll (HWND hwndParent,BOOL standalone,CHAR *startpath) {

  HWND          hwndFrame = (HWND)0,hwndClient;
  ULONG         FrameFlags = FCF_TITLEBAR    | FCF_SYSMENU     |
                             FCF_SIZEBORDER  | FCF_MINMAX      |
                             FCF_NOBYTEALIGN | FCF_VERTSCROLL  |
                             FCF_MENU        | FCF_ICON        |
                             FCF_ACCELTABLE  | FCF_HORZSCROLL;

  if(ParentIsDesktop(hwndParent,hwndParent))
    FrameFlags |= (FCF_TASKLIST | FCF_SHELLPOSITION);
  hwndFrame = WinCreateStdWindow(hwndParent,
                                 WS_VISIBLE,
                                 &FrameFlags,
                                 GetPString(IDS_WCSEEALL),
                                 GetPString(IDS_SEEALLTITLETEXT),
                                 WS_VISIBLE | fwsAnimate,
                                 FM3ModHandle,
                                 SEEALL_FRAME,
                                 &hwndClient);
  if(hwndFrame) {
    if(standalone) {
      if(!PostMsg(WinWindowFromID(hwndFrame,FID_CLIENT),
                  UM_SETUP4,
                  MPVOID,
                  MPVOID)) {
        PostMsg((HWND)0,
                WM_QUIT,
                MPVOID,
                MPVOID);
        return (HWND)0;
      }
    }
    PostMsg(WinWindowFromID(hwndFrame,FID_CLIENT),
            UM_SETUP5,
            MPFROMP(startpath),
            MPVOID);
  }
  else if(standalone)
    PostMsg((HWND)0,
            WM_QUIT,
            MPVOID,
            MPVOID);
  return hwndFrame;
}
