/*********************************************************************** $Id: objcnr.c 1673 2012-12-30 18:51:01Z gyoung $ Object containers Copyright (c) 1993-98 M. Kimes Copyright (c) 2005, 2009 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 10 Dec 08 SHL Integrate exception handler support 08 Mar 09 GKY Additional strings move to PCSZs 28 Jun 09 GKY Added AddBackslashToPath() to remove repeatative code. ***********************************************************************/ #include #include #include // #include // _beginthread #define INCL_DOS #define INCL_WIN #define INCL_DOSERRORS #define INCL_LONGLONG #include "fm3dll.h" #include "fm3dll2.h" // #define's for UM_*, control id's, etc. #include "draglist.h" // Data declaration(s) #include "info.h" // Data declaration(s) #include "init.h" // Data declaration(s) #include "notebook.h" // Data declaration(s) #include "newview.h" // Data declarations #include "fm3dlg.h" #include "fm3str.h" #include "errutil.h" // Dos_Error... #include "strutil.h" // GetPString #include "objcnr.h" #include "notify.h" // Notify #include "wrappers.h" // xDosFindNext #include "select.h" // ExpandAll #include "valid.h" // IsRoot #include "misc.h" // PostMsg #include "fortify.h" #include "excputil.h" // xbeginthread #include "pathutil.h" // AddBackslashToPath 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); AddBackslashToPath(maskstr); //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__, PCSZ_CM_ALLOCRECORD); free(pffbArray); 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 { free(pffbArray); 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))) { free(pffbArray); 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); } free(pffbArray); WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPFROMP(&pciP), MPFROM2SHORT(1, 0)); } static VOID FillCnrsThread(VOID * args) { HAB hab; HMQ hmq; DIRSIZE *dirsize = (DIRSIZE *)args; # ifdef FORTIFY Fortify_EnterScope(); # endif if (!dirsize) { Runtime_Error(pszSrcFile, __LINE__, NULL); 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); free(dirsize); # ifdef FORTIFY Fortify_LeaveScope(); # endif } 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; # ifdef FORTIFY Fortify_EnterScope(); # endif 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 (xbeginthread(FillCnrsThread, 65536 * 8, dirsize, pszSrcFile, __LINE__) == -1) { free(dirsize); # ifdef FORTIFY Fortify_LeaveScope(); # endif 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 = (PSZ)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)