/*********************************************************************** $Id: objcnr.c 1009 2008-05-10 07:51:58Z stevenhl $ Object containers Copyright (c) 1993-98 M. Kimes Copyright (c) 2005, 2007 Steven H. Levine 24 May 05 SHL Rework for CNRITEM.szSubject 13 Jul 06 SHL Use Runtime_Error 01 Sep 06 SHL Do not complain for normal cancel 19 Oct 06 SHL Correct . and .. detect 03 Nov 06 SHL Renames 22 Mar 07 GKY Use QWL_USER 01 Aug 07 SHL Rework to sync with CNRITEM mods 03 Aug 07 GKY Enlarged and made setable everywhere Findbuf (speed file loading) 06 Aug 07 GKY Reduce DosSleep times (ticket 148) 13 Aug 07 SHL Avoid realloc - not needed; sanitize code 13 Aug 07 SHL Move #pragma alloc_text to end for OpenWatcom compat 14 Aug 07 SHL Revert ProcessDir DosSleep to 0 29 Feb 08 GKY Use xfree where appropriate ***********************************************************************/ #include #include #include #include // _beginthread #define INCL_DOS #define INCL_WIN #define INCL_DOSERRORS #define INCL_LONGLONG #include "fm3dlg.h" #include "fm3str.h" #include "errutil.h" // Dos_Error... #include "strutil.h" // GetPString #include "fm3dll.h" typedef struct { CHAR *filename; HWND hwndCnr; CHAR *stopflag; } DIRSIZE; typedef struct { CHAR *dirname; CHAR stopflag; BOOL dying; BOOL working; } TEMP; #pragma data_seg(DATA1) static PSZ pszSrcFile = __FILE__; static HWND objcnrwnd; static VOID ProcessDir(HWND hwndCnr, CHAR *filename, PCNRITEM pciParent, CHAR *stopflag) { CHAR maskstr[CCHMAXPATH], *endpath, *p; ULONG ulFindCnt, ulFindMax; ULONG ulBufBytes; HDIR hdir; PFILEFINDBUF3L pffbArray; APIRET rc; RECORDINSERT ri; PCNRITEM pciP; HPOINTER hptr; ulBufBytes = sizeof(FILEFINDBUF3L) * FilesToGet; pffbArray = xmalloc(ulBufBytes, pszSrcFile, __LINE__); if (!pffbArray) return; // Error already reported strcpy(maskstr, filename); if (maskstr[strlen(maskstr) - 1] != '\\') strcat(maskstr, "\\"); endpath = &maskstr[strlen(maskstr)]; strcat(maskstr, "*"); hdir = HDIR_CREATE; ulFindCnt = 1; rc = xDosFindFirst(filename, &hdir, FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED | FILE_SYSTEM | FILE_HIDDEN | MUST_HAVE_DIRECTORY, pffbArray, ulBufBytes, &ulFindCnt, FIL_STANDARDL); if (!rc) DosFindClose(hdir); // work around furshluginer FAT root bug else if (IsRoot(filename)) rc = 0; if ((!rc && (pffbArray->attrFile & FILE_DIRECTORY))) { pciP = WinSendMsg(hwndCnr, CM_ALLOCRECORD, MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1)); if (!pciP) { Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__, "CM_ALLOCRECORD"); xfree(pffbArray, pszSrcFile, __LINE__); return; } pciP->pszFileName = xstrdup(filename, pszSrcFile, __LINE__); pciP->pszDispAttr = NullStr; pciP->pszSubject = NullStr; pciP->pszLongName = NullStr; if (strlen(filename) < 4) pciP->pszDisplayName = pciP->pszFileName; else { p = strrchr(pciP->pszFileName, '\\'); if (!p) pciP->pszDisplayName = pciP->pszFileName; else if (*(p + 1)) p++; pciP->pszDisplayName = p; } pciP->rc.pszIcon = pciP->pszDisplayName; if (fForceUpper) strupr(pciP->pszFileName); else if (fForceLower) strlwr(pciP->pszFileName); pciP->rc.flRecordAttr |= CRA_RECORDREADONLY; } else { xfree(pffbArray, pszSrcFile, __LINE__); Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, GetPString(IDS_CANTFINDDIRTEXT), filename); return; } hptr = WinLoadFileIcon(pciP->pszFileName, FALSE); if (hptr) pciP->rc.hptrIcon = hptr; if (!pciP->rc.hptrIcon || pciP->rc.hptrIcon == hptrFile) /* OS/2 bug bug bug bug */ pciP->rc.hptrIcon = hptrDir; memset(&ri, 0, sizeof(RECORDINSERT)); ri.cb = sizeof(RECORDINSERT); ri.pRecordOrder = (PRECORDCORE) CMA_END; ri.pRecordParent = (PRECORDCORE) pciParent; ri.zOrder = (USHORT) CMA_TOP; ri.cRecordsInsert = 1; ri.fInvalidateRecord = TRUE; if (!WinSendMsg(hwndCnr, CM_INSERTRECORD, MPFROMP(pciP), MPFROMP(&ri))) { xfree(pffbArray, pszSrcFile, __LINE__); return; } hdir = HDIR_CREATE; if (!isalpha(*maskstr) || maskstr[1] != ':' || maskstr[2] != '\\' || ((driveflags[toupper(*maskstr) - 'A'] & DRIVE_REMOTE) && fRemoteBug)) ulFindMax = 1; else ulFindMax = FilesToGet; ulFindCnt = ulFindMax; rc = xDosFindFirst(maskstr, &hdir, FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED | FILE_SYSTEM | FILE_HIDDEN | MUST_HAVE_DIRECTORY, pffbArray, ulBufBytes, &ulFindCnt, FIL_STANDARDL); if (!rc) { PFILEFINDBUF3L pffbFile; ULONG x; while (!rc) { pffbFile = pffbArray; for (x = 0; x < ulFindCnt; x++) { if (*stopflag) break; if ((pffbFile->attrFile & FILE_DIRECTORY) && // Skip . and .. (pffbFile->achName[0] != '.' || (pffbFile->achName[1] && (pffbFile->achName[1] != '.' || pffbFile->achName[2])))) { strcpy(endpath, pffbFile->achName); ProcessDir(hwndCnr, maskstr, pciP, stopflag); } if (!pffbFile->oNextEntryOffset) break; pffbFile = (PFILEFINDBUF3L)((PBYTE)pffbFile + pffbFile->oNextEntryOffset); } // for DosSleep(0); // Let's others at same priority get some work done if (*stopflag) break; ulFindCnt = ulFindMax; rc = xDosFindNext(hdir, pffbArray, ulBufBytes, &ulFindCnt, FIL_STANDARDL); } // while DosFindClose(hdir); } if (rc && rc != ERROR_NO_MORE_FILES) { Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, GetPString(IDS_CANTFINDDIRTEXT), filename); } xfree(pffbArray, pszSrcFile, __LINE__); WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPFROMP(&pciP), MPFROM2SHORT(1, 0)); } static VOID FillCnrsThread(VOID * args) { HAB hab; HMQ hmq; DIRSIZE *dirsize = (DIRSIZE *)args; if (!dirsize) { Runtime_Error(pszSrcFile, __LINE__, "no data"); return; } DosError(FERR_DISABLEHARDERR); hab = WinInitialize(0); if (hab) { hmq = WinCreateMsgQueue(hab, 0); if (hmq) { WinCancelShutdown(hmq, TRUE); ProcessDir(dirsize->hwndCnr, dirsize->filename, (PCNRITEM) NULL, dirsize->stopflag); DosPostEventSem(CompactSem); WinDestroyMsgQueue(hmq); } WinTerminate(hab); } PostMsg(WinQueryWindow(dirsize->hwndCnr, QW_PARENT), UM_CONTAINER_FILLED, MPVOID, MPVOID); xfree(dirsize, pszSrcFile, __LINE__); } MRESULT EXPENTRY ObjCnrDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { TEMP *data; switch (msg) { case WM_INITDLG: if (objcnrwnd) { Runtime_Error(pszSrcFile, __LINE__, "objcnrwnd set"); WinSetWindowPos(objcnrwnd, HWND_TOP, 0, 0, 0, 0, SWP_RESTORE | SWP_SHOW | SWP_ACTIVATE | SWP_ZORDER); WinDismissDlg(hwnd, 0); break; } if (!mp2) { Runtime_Error(pszSrcFile, __LINE__, "mp2 NULL"); WinDismissDlg(hwnd, 0); break; } objcnrwnd = hwnd; data = xmallocz(sizeof(TEMP), pszSrcFile, __LINE__); if (!data) { WinDismissDlg(hwnd, 0); break; } data->dirname = (CHAR *)mp2; WinSetWindowPtr(hwnd, QWL_USER, (PVOID) data); if (*data->dirname) WinSetDlgItemText(hwnd, OBJCNR_DIR, data->dirname); { DIRSIZE *dirsize; dirsize = xmalloc(sizeof(DIRSIZE), pszSrcFile, __LINE__); if (!dirsize) { WinDismissDlg(hwnd, 0); break; } dirsize->stopflag = (CHAR *)&data->stopflag; dirsize->filename = data->dirname; dirsize->hwndCnr = WinWindowFromID(hwnd, OBJCNR_CNR); if (_beginthread(FillCnrsThread, NULL, 65536 * 8, (PVOID) dirsize) == -1) { Runtime_Error(pszSrcFile, __LINE__, GetPString(IDS_COULDNTSTARTTHREADTEXT)); xfree(dirsize, pszSrcFile, __LINE__); WinDismissDlg(hwnd, 0); break; } else data->working = TRUE; } PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID); break; case UM_SETUP: // WinEnableWindowUpdate(WinWindowFromID(hwnd,OBJCNR_CNR),FALSE); { CNRINFO cnri; memset(&cnri, 0, sizeof(CNRINFO)); cnri.cb = sizeof(CNRINFO); WinSendDlgItemMsg(hwnd, OBJCNR_CNR, CM_QUERYCNRINFO, MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO))); cnri.cyLineSpacing = 0; cnri.cxTreeIndent = 12L; cnri.pszCnrTitle = GetPString(IDS_WORKINGTEXT); cnri.flWindowAttr = CV_TREE | CV_FLOW | CA_CONTAINERTITLE | CA_TITLESEPARATOR | CA_TREELINE; if (WinQueryWindowUShort(hwnd, QWS_ID) == QTREE_FRAME) cnri.flWindowAttr |= CV_MINI; WinSendDlgItemMsg(hwnd, OBJCNR_CNR, CM_SETCNRINFO, MPFROMP(&cnri), MPFROMLONG(CMA_FLWINDOWATTR | CMA_LINESPACING | CMA_CXTREEINDENT)); } return 0; case UM_CONTAINER_FILLED: WinSetDlgItemText(hwnd, OBJCNR_NOTE, NullStr); // WinEnableWindowUpdate(WinWindowFromID(hwnd,OBJCNR_CNR),TRUE); WinSendDlgItemMsg(hwnd, OBJCNR_CNR, CM_INVALIDATERECORD, MPVOID, MPFROM2SHORT(0, CMA_ERASE | CMA_INVALIDATE)); data = INSTDATA(hwnd); if (data) { data->working = FALSE; if (data->dying) WinDismissDlg(hwnd, 0); { PCNRITEM pci; USHORT id; id = WinQueryWindowUShort(hwnd, QWS_ID); pci = (PCNRITEM) WinSendDlgItemMsg(hwnd, OBJCNR_CNR, CM_QUERYRECORD, MPVOID, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)); if (pci && (INT) pci != -1) { ExpandAll(WinWindowFromID(hwnd, OBJCNR_CNR), TRUE, pci); if (id == QTREE_FRAME) pci = (PCNRITEM) WinSendDlgItemMsg(hwnd, OBJCNR_CNR, CM_QUERYRECORD, MPFROMP(pci), MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER)); } if ((!pci || (INT) pci == -1) && id == QTREE_FRAME) { Notify(GetPString(IDS_NODIRSUNDERTEXT)); WinDismissDlg(hwnd, 0); break; } } } return 0; case WM_CONTROL: switch (SHORT1FROMMP(mp1)) { case OBJCNR_CNR: if (SHORT2FROMMP(mp1) == CN_ENTER) { PCNRITEM pci = (PCNRITEM) ((PNOTIFYRECORDENTER) mp2)->pRecord; if (pci && (INT) pci != -1) WinSendDlgItemMsg(hwnd, DID_OK, BM_CLICK, MPVOID, MPVOID); } break; } return 0; case WM_COMMAND: switch (SHORT1FROMMP(mp1)) { case IDM_HELP: if (hwndHelp) { USHORT id; id = WinQueryWindowUShort(hwnd, QWS_ID); if (id == QTREE_FRAME) WinSendMsg(hwndHelp, HM_DISPLAY_HELP, MPFROM2SHORT(HELP_QUICKTREE, 0), MPFROMSHORT(HM_RESOURCEID)); else WinSendMsg(hwndHelp, HM_DISPLAY_HELP, MPFROM2SHORT(HELP_OBJECTPATH, 0), MPFROMSHORT(HM_RESOURCEID)); } break; case OBJCNR_DESKTOP: case DID_OK: data = INSTDATA(hwnd); if (data) { PCNRITEM pci; if (data->working) { Runtime_Error(pszSrcFile, __LINE__, "working unexpected"); break; } if (SHORT1FROMMP(mp1) == OBJCNR_DESKTOP) { WinDismissDlg(hwnd, 2); break; } pci = (PCNRITEM) WinSendDlgItemMsg(hwnd, OBJCNR_CNR, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_CURSORED)); if (pci && (INT) pci != -1) strcpy(data->dirname, pci->pszFileName); WinDismissDlg(hwnd, 1); } break; case DID_CANCEL: data = INSTDATA(hwnd); if (data) { if (data->working) { data->dying = (CHAR)TRUE; data->stopflag = (CHAR)0xff; break; } WinDismissDlg(hwnd, 0); } break; } return 0; case WM_DESTROY: objcnrwnd = (HWND) 0; data = INSTDATA(hwnd); xfree(data, pszSrcFile, __LINE__); break; } return WinDefDlgProc(hwnd, msg, mp1, mp2); } #pragma alloc_text(OBJCNR,ProcessDir,FillCnrsThread,ObjCnrDlgProc)