source: trunk/dll/flesh.c@ 1649

Last change on this file since 1649 was 1649, checked in by Gregg Young, 14 years ago

Cleanup the scanning code to try to improve scan times.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.9 KB
RevLine 
[145]1
2/***********************************************************************
3
4 $Id: flesh.c 1649 2011-11-19 20:38:33Z gyoung $
5
6 Flesh
7
8 Copyright (c) 1993-98 M. Kimes
[1498]9 Copyright (c) 2005, 2010 Steven H. Levine
[145]10
11 24 May 05 SHL Rework Win_Error usage
[166]12 25 May 05 SHL Rework for ProcessDirectory
[284]13 28 May 05 SHL Clean while reading code
14 24 Oct 05 SHL Delete obsolete code
[340]15 22 Jul 06 SHL Check more run time errors
[515]16 19 Oct 06 SHL Stubby - correct . and .. detect
[574]17 22 Mar 07 GKY Use QWL_USER
[751]18 01 Aug 07 SHL Sync with CNRITEM mods
[775]19 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
[793]20 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
[985]21 29 Feb 08 GKY Use xfree where appropriate
[1299]22 24 Nov 08 GKY remove redundant code and minor speed up of Stubby
[1358]23 25 Dec 08 GKY Add ProcessDirectoryThread to allow optional recursive drive scan at startup.
24 25 Dec 08 GKY Add DRIVE_RSCANNED flag to monitor for the first recursive drive scan per session
[1471]25 to prevent duplicate directory names in tree following a copy before initial scan.
[1400]26 08 Mar 09 GKY Additional strings move to PCSZs in init.c
[1482]27 13 Dec 09 GKY Fixed separate paramenters. Please note that appname should be used in
28 profile calls for user settings that work and are setable in more than one
29 miniapp; FM3Str should be used for setting only relavent to FM/2 or that
30 aren't user settable; realappname should be used for setting applicable to
31 one or more miniapp but not to FM/2
[1498]32 17 JAN 10 GKY Changes to get working with Watcom 1.9 Beta (1/16/10). Mostly cast CHAR CONSTANT * as CHAR *.
[145]33
34***********************************************************************/
35
[907]36#include <stdlib.h>
37#include <string.h>
38#include <ctype.h>
39
[2]40#define INCL_DOS
41#define INCL_DOSERRORS
42#define INCL_WIN
[907]43#define INCL_LONGLONG // dircnrs.h
[2]44
[1177]45#include "fm3dll.h"
[1207]46#include "draglist.h" // Data declaration(s)
47#include "notebook.h" // Data declaration(s)
48#include "info.h" // Data declaration(s)
49#include "init.h" // Data declaration(s)
50#include "mainwnd.h" // Data declaration(s)
[907]51#include "fm3str.h"
52#include "filldir.h" // FileAttrToString...
53#include "errutil.h" // Dos_Error...
54#include "strutil.h" // GetPString
[1155]55#include "flesh.h"
56#include "valid.h" // IsValidDir
57#include "misc.h" // LoadLibPath
[1177]58#include "findrec.h" // FindCnrRecord
59#include "notify.h" // Notify
60#include "wrappers.h" // xfree
[1354]61#include "excputil.h" // xbeginthread
[2]62
[1207]63// Data definitions
[2]64#pragma data_seg(DATA1)
[340]65
66static PSZ pszSrcFile = __FILE__;
67
[1207]68#pragma data_seg(GLOBAL1)
69ULONG NoBrokenNotify;
70BOOL fFilesInTree;
71
[551]72BOOL FleshEnv(HWND hwndCnr, PCNRITEM pciParent)
[175]73{
[551]74 PCNRITEM pciL;
[2]75 DIRCNRDATA *dcd;
[551]76 CHAR path[CCHMAXPATH + 12],
77 fullpath[CCHMAXPATH + 12], *env, *p, *pp, *var = NULL;
[2]78
[551]79 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
[2]80 return FALSE;
[574]81 dcd = (DIRCNRDATA *) WinQueryWindowPtr(hwndCnr, QWL_USER);
[551]82 if (!dcd)
[2]83 return FALSE;
84
[730]85 strcpy(path, pciParent->pszFileName + 1);
[551]86 if (stricmp(path, GetPString(IDS_ENVVARSTEXT) + 1))
87 UnFlesh(hwndCnr, pciParent);
88 if (*path) {
[2]89 path[strlen(path) - 1] = 0;
[1400]90 if (!stricmp(path, PCSZ_LIBPATH)) {
[551]91 var = xmalloc(65536, pszSrcFile, __LINE__);
92 if (var)
93 LoadLibPath(var, 65536);
[2]94 env = var;
95 }
96 else
97 env = getenv(path);
[551]98 if (env && *env) {
[2]99 p = env;
[551]100 while (*p) {
101 pp = path;
102 while (*p == ';')
103 p++;
104 while (*p && *p != ';') {
105 *pp = *p;
106 p++;
107 pp++;
108 }
109 *pp = 0;
110 if (*path &&
111 strcmp(path, ".") &&
112 strcmp(path, ".\\") &&
113 strcmp(path, "..") &&
114 strcmp(path, "..\\") &&
115 strncmp(path, ".\\", 2) && strncmp(path, "..\\", 3)) {
116 if (!DosQueryPathInfo(path,
117 FIL_QUERYFULLNAME,
118 fullpath,
119 sizeof(fullpath)) && IsValidDir(fullpath)) {
120 pciL = FindCnrRecord(hwndCnr,
121 fullpath, pciParent, FALSE, FALSE, FALSE);
122 if (pciL) {
123 while (pciL && pciL != (PCNRITEM) - 1 && pciL != pciParent)
124 pciL = WinSendMsg(hwndCnr,
125 CM_QUERYRECORD,
126 MPFROMP(pciL),
127 MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
128 }
129 if (!pciL) {
[2]130
[551]131 RECORDINSERT ri;
[2]132
[551]133 pciL = WinSendMsg(hwndCnr,
134 CM_ALLOCRECORD,
[751]135 MPFROMLONG(EXTRA_RECORD_BYTES),
[551]136 MPFROMLONG(1));
137 if (pciL) {
[730]138 pciL->pszFileName = xstrdup(fullpath, pszSrcFile, __LINE__);
[751]139 pciL->rc.pszIcon = pciL->pszFileName;
[551]140 if (!fNoIconsDirs &&
141 (!isalpha(*fullpath) ||
142 !(driveflags[toupper(*fullpath) - 'A'] &
143 DRIVE_NOLOADICONS)))
144 pciL->rc.hptrIcon = WinLoadFileIcon(fullpath, FALSE);
145 if (!pciL->rc.hptrIcon)
146 pciL->rc.hptrIcon = hptrDir;
147 pciL->attrFile = FILE_DIRECTORY;
[751]148 pciL->pszDispAttr = FileAttrToString(pciL->attrFile);
[551]149 memset(&ri, 0, sizeof(ri));
150 ri.cb = sizeof(ri);
151 ri.pRecordOrder = (PRECORDCORE) CMA_END;
152 ri.pRecordParent = (PRECORDCORE) pciParent;
153 ri.zOrder = (ULONG) CMA_TOP;
154 ri.cRecordsInsert = 1;
155 ri.fInvalidateRecord = FALSE;
156 if (!WinSendMsg(hwndCnr,
157 CM_INSERTRECORD, MPFROMP(pciL), MPFROMP(&ri)))
[751]158 FreeCnrItem(hwndCnr, pciL);
[551]159 }
160 }
161 }
162 }
[2]163 }
164 }
[1009]165 xfree(var, pszSrcFile, __LINE__);
[551]166 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
167 CM_QUERYRECORD,
168 MPFROMP(pciParent),
169 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
170 while (pciL && (INT) pciL != -1) {
[2]171 pciL->flags |= (RECFLAGS_NODRAG | RECFLAGS_UNDERENV);
172 WinSendMsg(hwndCnr,
[551]173 CM_INVALIDATERECORD, MPFROMP(&pciL), MPFROM2SHORT(1, 0));
[2]174 pciL = WinSendMsg(hwndCnr,
[551]175 CM_QUERYRECORD,
176 MPFROMP(pciL), MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
[2]177 }
178 }
179 return TRUE;
180}
181
[551]182BOOL Flesh(HWND hwndCnr, PCNRITEM pciParent)
[166]183{
[551]184 PCNRITEM pciL;
[2]185 DIRCNRDATA *dcd;
[551]186 BOOL includefiles = fFilesInTree;
[2]187
[551]188 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
[2]189 return FALSE;
[551]190 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
191 CM_QUERYRECORD,
192 MPFROMP(pciParent),
193 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
[1649]194 if (pciL && (INT) pciL != -1 &&* pciL->pszFileName) //{
195 UnFlesh( hwndCnr, pciParent);
196 //if (pciL && (INT) pciL != -1)
197 // RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
[2]198 dcd = INSTDATA(hwndCnr);
[166]199 if (dcd && dcd->size != sizeof(DIRCNRDATA))
[2]200 dcd = NULL;
[730]201 if (driveflags[toupper(*pciParent->pszFileName) - 'A'] &
[551]202 DRIVE_INCLUDEFILES)
[2]203 includefiles = TRUE;
[1550]204#if 0
[1354]205 if (fInitialDriveScan) {
206 PROCESSDIR *ProcessDir;
207
208 ProcessDir = xmallocz(sizeof(PROCESSDIR), pszSrcFile, __LINE__);
209 if (!ProcessDir)
[1471]210 return FALSE;
[1354]211 ProcessDir->hwndCnr = hwndCnr;
212 ProcessDir->pciParent = pciParent;
213 ProcessDir->szDirBase = pciParent->pszFileName;
214 ProcessDir->filestoo = includefiles;
215 ProcessDir->recurse = TRUE;
216 ProcessDir->partial = TRUE;
217 ProcessDir->stopflag = NULL;
218 ProcessDir->dcd = dcd;
219 ProcessDir->pulTotalFiles = NULL;
220 ProcessDir->pullTotalBytes = NULL;
221
222 if (xbeginthread(ProcessDirectoryThread,
[1471]223 65536,
224 ProcessDir,
225 pszSrcFile,
226 __LINE__) == -1)
[1354]227 {
[1471]228 xfree(ProcessDir, pszSrcFile, __LINE__);
[1354]229 }
230 }
[1471]231 else {
[1550]232# endif
[1354]233 ProcessDirectory(hwndCnr,
[1471]234 pciParent,
235 pciParent->pszFileName,
236 includefiles, // filestoo
237 TRUE, // recurse
238 TRUE, // partial
239 NULL, // stop flag
240 dcd,
241 NULL, // total files
[1649]242 NULL); // total bytes
243#if 0
244 }
245#endif
246 driveflags[*pciParent->pszFileName - 'A'] |= DRIVE_RSCANNED;
247 //}
[2]248 return TRUE;
249}
250
[551]251BOOL UnFlesh(HWND hwndCnr, PCNRITEM pciParent)
[175]252{
[551]253 BOOL ret = FALSE;
[2]254 PCNRITEM pciL;
255
[175]256 if (!pciParent || !hwndCnr)
[2]257 return FALSE;
[551]258 for (;;) {
259 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
260 CM_QUERYRECORD,
261 MPFROMP(pciParent),
262 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
263 if (pciL && (INT) pciL != -1) {
[2]264 ret = TRUE;
[751]265 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
[2]266 }
267 else
268 break;
269 }
[551]270 if (ret) {
[2]271 WinSendMsg(hwndCnr,
[551]272 CM_INVALIDATERECORD,
273 MPFROMP(&pciParent),
274 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
[175]275 }
[2]276 return ret;
277}
278
[1482]279#define DDEPTH 64
[2]280
[1471]281/**
282 * Fill in drive tree subtree
283 * @return TRUE if OK, else FALSE
[1551]284 * This only scans the root directory and adds the first level directories
285 * Flesh does a recursive scan and should be used on fast hardware.
[1471]286 */
287
[551]288BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent)
[175]289{
[1409]290 /**
[2]291 * this code is full of workarounds for screwed up LANs.
292 * let's hope all the current LAN programmers fall into
293 * a black hole and make way for people who can get it right...
294 */
295
[1471]296 BOOL ok = FALSE;
[847]297 FILEFINDBUF3 ffb[DDEPTH];
298 PFILEFINDBUF3 pffb;
[551]299 HDIR hDir = HDIR_CREATE;
[761]300 ULONG nm, ulM = 1, total = 0, fl = MUST_HAVE_DIRECTORY;
[551]301 CHAR str[CCHMAXPATH];
302 register INT len;
303 APIRET rc, prc;
304 BOOL isadir = FALSE, isremote = FALSE, includefiles = fFilesInTree;
[1482]305 ULONG ddepth = DDEPTH;
[1299]306 ULONG drvNum;
307 ULONG flags;
[551]308 static BOOL brokenlan = FALSE, isbroken = FALSE;
[2]309
[730]310 if (!pciParent || !*pciParent->pszFileName || !hwndCnr)
[2]311 return FALSE;
312
[730]313 len = strlen(pciParent->pszFileName);
314 memcpy(str, pciParent->pszFileName, len + 1);
[551]315 if (str[len - 1] != '\\')
[2]316 str[len++] = '\\';
317 str[len++] = '*';
318 str[len] = 0;
319
[551]320 if (!isalpha(*str) || str[1] != ':' || str[2] != '\\')
[2]321 MakeFullName(str);
322
[1299]323 drvNum = toupper(*pciParent->pszFileName) - 'A';
324 flags = driveflags[drvNum];
[551]325 if (!isalpha(*str) ||
326 str[1] != ':' ||
[1299]327 str[2] != '\\' || ((flags & DRIVE_IGNORE)))
[1471]328 return FALSE; // Not a directory
[2]329
[1299]330 if (flags & DRIVE_INCLUDEFILES)
[2]331 includefiles = TRUE;
332
[1299]333 if (flags & DRIVE_REMOTE)
[2]334 isremote = TRUE;
335
[551]336 if (isremote) {
337 if (fRemoteBug) {
338 if (brokenlan) {
339 ddepth = (ULONG) - 1;
340 ddepth--;
[2]341 }
[761]342 ulM = 1;
[2]343 }
344 }
[551]345 else if (isbroken)
[2]346 ddepth = 14;
347
[1482]348 if (!fRemoteBug)
349 ulM = (ddepth <= DDEPTH) ? ddepth : 1;
[2]350
351 nm = ulM;
352
353 DosError(FERR_DISABLEHARDERR);
[551]354 if (includefiles)
[2]355 fl = FILE_DIRECTORY;
[847]356 rc = DosFindFirst(str,
357 &hDir,
358 FILE_NORMAL | fl |
359 FILE_READONLY | FILE_ARCHIVED |
360 FILE_SYSTEM | FILE_HIDDEN,
361 &ffb, ulM * sizeof(FILEFINDBUF3), &nm, FIL_STANDARD);
[761]362 if (ulM == 1 && !rc) {
[2]363 do {
364 pffb = &ffb[0];
[551]365 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY) && !brokenlan) {
366 brokenlan = TRUE;
[847]367 ddepth = (ULONG) - 1;
[551]368 ddepth--;
369 if (!NoBrokenNotify) {
370 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
371 HWND_DESKTOP,
372 GetPString(IDS_LANERRORTITLETEXT),
373 GetPString(IDS_LANERRORTEXT));
374 if (prc == MBID_NO) {
375 saymsg(MB_ENTER,
376 HWND_DESKTOP,
377 GetPString(IDS_LANERROR2TITLETEXT),
378 GetPString(IDS_LANERROR2TEXT));
[847]379 NoBrokenNotify = 255;
[1505]380 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]381 &NoBrokenNotify, sizeof(ULONG));
382 }
383 }
384 else {
385 NoBrokenNotify--;
[1505]386 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]387 &NoBrokenNotify, sizeof(ULONG));
388 }
[2]389 }
[515]390 if (*pffb->achName &&
[551]391 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
[515]392 // Skip . and ..
[551]393 (pffb->achName[0] != '.' ||
[515]394 (pffb->achName[1] &&
[551]395 (pffb->achName[1] != '.' || pffb->achName[2])))) {
396 DosFindClose(hDir);
397 isadir = TRUE;
398 goto Interruptus;
[2]399 }
[761]400 nm = 1;
[2]401 DosError(FERR_DISABLEHARDERR);
[1482]402 }
403 while (++total < ddepth && !(rc = (DosFindNext(hDir,
404 &ffb,
405 sizeof(FILEFINDBUF3),
406 &nm))));
407 DosFindClose(hDir);
[1471]408 // If drive B:
[730]409 if (toupper(*pciParent->pszFileName) > 'B' &&
[751]410 (*(pciParent->pszFileName + 1)) == ':' &&
[730]411 (*(pciParent->pszFileName + 2)) == '\\' && !(*(pciParent->pszFileName + 3))) {
[2]412
413 CHAR s[132];
414 sprintf(s,
[551]415 GetPString(IDS_NOSUBDIRSTEXT),
[730]416 total, toupper(*pciParent->pszFileName));
[551]417 if (rc && rc != ERROR_NO_MORE_FILES)
418 sprintf(&s[strlen(s)], GetPString(IDS_SEARCHERRORTEXT), rc, str);
[847]419 else if (ddepth < 16)
[551]420 brokenlan = TRUE;
[2]421 Notify(s);
422 }
423 goto None;
424 }
425
[551]426 if (!rc) {
[2]427 DosFindClose(hDir);
[551]428 if (nm) {
[1353]429 PBYTE fb = (PBYTE)&ffb[0];
[551]430 for (len = 0; len < nm; len++) {
[847]431 pffb = (PFILEFINDBUF3) fb;
[551]432 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY)) {
433 if (!isbroken) {
434 isbroken = TRUE;
435 if (!NoBrokenNotify) {
436 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
437 HWND_DESKTOP,
438 GetPString(IDS_FSDERRORTITLETEXT),
439 GetPString(IDS_FSDERRORTEXT),
[1471]440 isremote ? GetPString(IDS_REMOTETEXT) :
441 GetPString(IDS_LOCALTEXT),
442 *str);
[551]443 if (prc == MBID_NO) {
444 saymsg(MB_ENTER,
445 HWND_DESKTOP,
446 GetPString(IDS_FSDERROR2TITLETEXT),
447 GetPString(IDS_FSDERROR2TEXT));
[847]448 NoBrokenNotify = 255;
[1505]449 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]450 &NoBrokenNotify, sizeof(ULONG));
451 }
452 }
453 else {
454 NoBrokenNotify--;
[1505]455 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]456 &NoBrokenNotify, sizeof(ULONG));
457 }
458 }
459 }
460 if (*pffb->achName &&
461 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
[515]462 // Skip . and ..
[551]463 (pffb->achName[0] != '.' || (pffb->achName[1]
464 && (pffb->achName[1] != '.'
465 || pffb->achName[2])))) {
466 isadir = TRUE;
467 break;
468 }
469 fb += pffb->oNextEntryOffset;
[1353]470 } // for
[2]471
[551]472 Interruptus:
[2]473
[551]474 if (isadir) {
[2]475
[1471]476 PCNRITEM pci;
[2]477
[1471]478 if (WinIsWindow((HAB)0, hwndCnr)) {
479 pci = WinSendMsg(hwndCnr,
480 CM_ALLOCRECORD,
481 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
482 if (!pci) {
483 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
484 GetPString(IDS_RECORDALLOCFAILEDTEXT));
485 }
486 else {
487 RECORDINSERT ri;
488 pci->pszFileName = NullStr;
489 pci->pszDisplayName = pci->pszFileName;
490 pci->rc.pszIcon = pci->pszDisplayName;
491 memset(&ri, 0, sizeof(RECORDINSERT));
492 ri.cb = sizeof(RECORDINSERT);
493 ri.pRecordOrder = (PRECORDCORE) CMA_END;
494 ri.pRecordParent = (PRECORDCORE) pciParent;
495 ri.zOrder = (ULONG) CMA_TOP;
496 ri.cRecordsInsert = 1;
497 ri.fInvalidateRecord = TRUE;
498 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD \"%s\" %.255s", hwndCnr, pci->pszFileName, pffb->achName); // 18 Dec 08 SHL fixme debug
499 if (!WinSendMsg(hwndCnr,
500 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
501 DosSleep(50); //05 Aug 07 GKY 100
502 WinSetFocus(HWND_DESKTOP, hwndCnr);
503 if (WinIsWindow((HAB)0, hwndCnr)) {
504 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD %s", hwndCnr, pci->pszFileName); // 18 Dec 08 SHL fixme debug
505 if (!WinSendMsg(hwndCnr,
506 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
507 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
508 GetPString(IDS_RECORDINSERTFAILEDTEXT));
509 FreeCnrItem(hwndCnr, pci);
510 }
511 else
512 ok = TRUE;
513 }
514 }
515 else
516 ok = TRUE;
517 }
518 }
[2]519 }
[551]520 else if (toupper(*str) > 'B' && str[1] == ':' && str[2] == '\\' &&
521 !str[3]) {
[2]522
[551]523 CHAR s[162];
[2]524
[551]525 sprintf(s,
526 GetPString(IDS_NOSUBDIRS2TEXT),
527 nm,
[730]528 toupper(*pciParent->pszFileName),
[551]529 (isremote) ? GetPString(IDS_NOSUBDIRS3TEXT) : NullStr);
530 Notify(s);
[2]531 }
532 }
533 }
[551]534 else if (toupper(*str) > 'B' && rc != ERROR_NO_MORE_FILES) {
[2]535 CHAR s[CCHMAXPATH + 80];
[551]536 sprintf(s, GetPString(IDS_SEARCHERRORTEXT), rc, str);
[2]537 Notify(s);
538 }
539
540None:
541
542 DosError(FERR_DISABLEHARDERR);
[1471]543 return ok;
[2]544}
[793]545
[1353]546#pragma alloc_text(FLESH,Flesh,FleshEnv,UnFlesh,Stubby)
Note: See TracBrowser for help on using the repository browser.