source: trunk/dll/flesh.c@ 1570

Last change on this file since 1570 was 1551, checked in by Gregg Young, 15 years ago

This code adds the semaphores to prevent a rescan from starting before the current one is finished; it fixes the double directory listing in the tree container and streamlines scanning. It update mapsym.pl to the latest version. Some code cleanup is included

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 KB
RevLine 
[145]1
2/***********************************************************************
3
4 $Id: flesh.c 1551 2010-11-15 03:33:25Z 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));
[730]194 if (!pciL || !*pciL->pszFileName) {
[751]195 if (pciL && (INT) pciL != -1)
196 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
[2]197 dcd = INSTDATA(hwndCnr);
[166]198 if (dcd && dcd->size != sizeof(DIRCNRDATA))
[2]199 dcd = NULL;
[730]200 if (driveflags[toupper(*pciParent->pszFileName) - 'A'] &
[551]201 DRIVE_INCLUDEFILES)
[2]202 includefiles = TRUE;
[1550]203#if 0
[1354]204 if (fInitialDriveScan) {
205 PROCESSDIR *ProcessDir;
206
207 ProcessDir = xmallocz(sizeof(PROCESSDIR), pszSrcFile, __LINE__);
208 if (!ProcessDir)
[1471]209 return FALSE;
[1354]210 ProcessDir->hwndCnr = hwndCnr;
211 ProcessDir->pciParent = pciParent;
212 ProcessDir->szDirBase = pciParent->pszFileName;
213 ProcessDir->filestoo = includefiles;
214 ProcessDir->recurse = TRUE;
215 ProcessDir->partial = TRUE;
216 ProcessDir->stopflag = NULL;
217 ProcessDir->dcd = dcd;
218 ProcessDir->pulTotalFiles = NULL;
219 ProcessDir->pullTotalBytes = NULL;
220
221 if (xbeginthread(ProcessDirectoryThread,
[1471]222 65536,
223 ProcessDir,
224 pszSrcFile,
225 __LINE__) == -1)
[1354]226 {
[1471]227 xfree(ProcessDir, pszSrcFile, __LINE__);
[1354]228 }
229 }
[1471]230 else {
[1550]231# endif
[1354]232 ProcessDirectory(hwndCnr,
[1471]233 pciParent,
234 pciParent->pszFileName,
235 includefiles, // filestoo
236 TRUE, // recurse
237 TRUE, // partial
238 NULL, // stop flag
239 dcd,
240 NULL, // total files
241 NULL); // total bytes
[1550]242 //}
[2]243 }
[1354]244 driveflags[*pciParent->pszFileName - 'A'] |= DRIVE_RSCANNED;
[2]245 return TRUE;
246}
247
[551]248BOOL UnFlesh(HWND hwndCnr, PCNRITEM pciParent)
[175]249{
[551]250 BOOL ret = FALSE;
[2]251 PCNRITEM pciL;
252
[175]253 if (!pciParent || !hwndCnr)
[2]254 return FALSE;
[551]255 for (;;) {
256 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
257 CM_QUERYRECORD,
258 MPFROMP(pciParent),
259 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
260 if (pciL && (INT) pciL != -1) {
[2]261 ret = TRUE;
[751]262 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
[2]263 }
264 else
265 break;
266 }
[551]267 if (ret) {
[2]268 WinSendMsg(hwndCnr,
[551]269 CM_INVALIDATERECORD,
270 MPFROMP(&pciParent),
271 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
[175]272 }
[2]273 return ret;
274}
275
[1482]276#define DDEPTH 64
[2]277
[1471]278/**
279 * Fill in drive tree subtree
280 * @return TRUE if OK, else FALSE
[1551]281 * This only scans the root directory and adds the first level directories
282 * Flesh does a recursive scan and should be used on fast hardware.
[1471]283 */
284
[551]285BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent)
[175]286{
[1409]287 /**
[2]288 * this code is full of workarounds for screwed up LANs.
289 * let's hope all the current LAN programmers fall into
290 * a black hole and make way for people who can get it right...
291 */
292
[1471]293 BOOL ok = FALSE;
[847]294 FILEFINDBUF3 ffb[DDEPTH];
295 PFILEFINDBUF3 pffb;
[551]296 HDIR hDir = HDIR_CREATE;
[761]297 ULONG nm, ulM = 1, total = 0, fl = MUST_HAVE_DIRECTORY;
[551]298 CHAR str[CCHMAXPATH];
299 register INT len;
300 APIRET rc, prc;
301 BOOL isadir = FALSE, isremote = FALSE, includefiles = fFilesInTree;
[1482]302 ULONG ddepth = DDEPTH;
[1299]303 ULONG drvNum;
304 ULONG flags;
[551]305 static BOOL brokenlan = FALSE, isbroken = FALSE;
[2]306
[730]307 if (!pciParent || !*pciParent->pszFileName || !hwndCnr)
[2]308 return FALSE;
309
[730]310 len = strlen(pciParent->pszFileName);
311 memcpy(str, pciParent->pszFileName, len + 1);
[551]312 if (str[len - 1] != '\\')
[2]313 str[len++] = '\\';
314 str[len++] = '*';
315 str[len] = 0;
316
[551]317 if (!isalpha(*str) || str[1] != ':' || str[2] != '\\')
[2]318 MakeFullName(str);
319
[1299]320 drvNum = toupper(*pciParent->pszFileName) - 'A';
321 flags = driveflags[drvNum];
[551]322 if (!isalpha(*str) ||
323 str[1] != ':' ||
[1299]324 str[2] != '\\' || ((flags & DRIVE_IGNORE)))
[1471]325 return FALSE; // Not a directory
[2]326
[1299]327 if (flags & DRIVE_INCLUDEFILES)
[2]328 includefiles = TRUE;
329
[1299]330 if (flags & DRIVE_REMOTE)
[2]331 isremote = TRUE;
332
[551]333 if (isremote) {
334 if (fRemoteBug) {
335 if (brokenlan) {
336 ddepth = (ULONG) - 1;
337 ddepth--;
[2]338 }
[761]339 ulM = 1;
[2]340 }
341 }
[551]342 else if (isbroken)
[2]343 ddepth = 14;
344
[1482]345 if (!fRemoteBug)
346 ulM = (ddepth <= DDEPTH) ? ddepth : 1;
[2]347
348 nm = ulM;
349
350 DosError(FERR_DISABLEHARDERR);
[551]351 if (includefiles)
[2]352 fl = FILE_DIRECTORY;
[847]353 rc = DosFindFirst(str,
354 &hDir,
355 FILE_NORMAL | fl |
356 FILE_READONLY | FILE_ARCHIVED |
357 FILE_SYSTEM | FILE_HIDDEN,
358 &ffb, ulM * sizeof(FILEFINDBUF3), &nm, FIL_STANDARD);
[761]359 if (ulM == 1 && !rc) {
[2]360 do {
361 pffb = &ffb[0];
[551]362 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY) && !brokenlan) {
363 brokenlan = TRUE;
[847]364 ddepth = (ULONG) - 1;
[551]365 ddepth--;
366 if (!NoBrokenNotify) {
367 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
368 HWND_DESKTOP,
369 GetPString(IDS_LANERRORTITLETEXT),
370 GetPString(IDS_LANERRORTEXT));
371 if (prc == MBID_NO) {
372 saymsg(MB_ENTER,
373 HWND_DESKTOP,
374 GetPString(IDS_LANERROR2TITLETEXT),
375 GetPString(IDS_LANERROR2TEXT));
[847]376 NoBrokenNotify = 255;
[1505]377 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]378 &NoBrokenNotify, sizeof(ULONG));
379 }
380 }
381 else {
382 NoBrokenNotify--;
[1505]383 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]384 &NoBrokenNotify, sizeof(ULONG));
385 }
[2]386 }
[515]387 if (*pffb->achName &&
[551]388 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
[515]389 // Skip . and ..
[551]390 (pffb->achName[0] != '.' ||
[515]391 (pffb->achName[1] &&
[551]392 (pffb->achName[1] != '.' || pffb->achName[2])))) {
393 DosFindClose(hDir);
394 isadir = TRUE;
395 goto Interruptus;
[2]396 }
[761]397 nm = 1;
[2]398 DosError(FERR_DISABLEHARDERR);
[1482]399 }
400 while (++total < ddepth && !(rc = (DosFindNext(hDir,
401 &ffb,
402 sizeof(FILEFINDBUF3),
403 &nm))));
404 DosFindClose(hDir);
[1471]405 // If drive B:
[730]406 if (toupper(*pciParent->pszFileName) > 'B' &&
[751]407 (*(pciParent->pszFileName + 1)) == ':' &&
[730]408 (*(pciParent->pszFileName + 2)) == '\\' && !(*(pciParent->pszFileName + 3))) {
[2]409
410 CHAR s[132];
411 sprintf(s,
[551]412 GetPString(IDS_NOSUBDIRSTEXT),
[730]413 total, toupper(*pciParent->pszFileName));
[551]414 if (rc && rc != ERROR_NO_MORE_FILES)
415 sprintf(&s[strlen(s)], GetPString(IDS_SEARCHERRORTEXT), rc, str);
[847]416 else if (ddepth < 16)
[551]417 brokenlan = TRUE;
[2]418 Notify(s);
419 }
420 goto None;
421 }
422
[551]423 if (!rc) {
[2]424 DosFindClose(hDir);
[551]425 if (nm) {
[1353]426 PBYTE fb = (PBYTE)&ffb[0];
[551]427 for (len = 0; len < nm; len++) {
[847]428 pffb = (PFILEFINDBUF3) fb;
[551]429 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY)) {
430 if (!isbroken) {
431 isbroken = TRUE;
432 if (!NoBrokenNotify) {
433 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
434 HWND_DESKTOP,
435 GetPString(IDS_FSDERRORTITLETEXT),
436 GetPString(IDS_FSDERRORTEXT),
[1471]437 isremote ? GetPString(IDS_REMOTETEXT) :
438 GetPString(IDS_LOCALTEXT),
439 *str);
[551]440 if (prc == MBID_NO) {
441 saymsg(MB_ENTER,
442 HWND_DESKTOP,
443 GetPString(IDS_FSDERROR2TITLETEXT),
444 GetPString(IDS_FSDERROR2TEXT));
[847]445 NoBrokenNotify = 255;
[1505]446 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]447 &NoBrokenNotify, sizeof(ULONG));
448 }
449 }
450 else {
451 NoBrokenNotify--;
[1505]452 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]453 &NoBrokenNotify, sizeof(ULONG));
454 }
455 }
456 }
457 if (*pffb->achName &&
458 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
[515]459 // Skip . and ..
[551]460 (pffb->achName[0] != '.' || (pffb->achName[1]
461 && (pffb->achName[1] != '.'
462 || pffb->achName[2])))) {
463 isadir = TRUE;
464 break;
465 }
466 fb += pffb->oNextEntryOffset;
[1353]467 } // for
[2]468
[551]469 Interruptus:
[2]470
[551]471 if (isadir) {
[2]472
[1471]473 PCNRITEM pci;
[2]474
[1471]475 if (WinIsWindow((HAB)0, hwndCnr)) {
476 pci = WinSendMsg(hwndCnr,
477 CM_ALLOCRECORD,
478 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
479 if (!pci) {
480 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
481 GetPString(IDS_RECORDALLOCFAILEDTEXT));
482 }
483 else {
484 RECORDINSERT ri;
485 pci->pszFileName = NullStr;
486 pci->pszDisplayName = pci->pszFileName;
487 pci->rc.pszIcon = pci->pszDisplayName;
488 memset(&ri, 0, sizeof(RECORDINSERT));
489 ri.cb = sizeof(RECORDINSERT);
490 ri.pRecordOrder = (PRECORDCORE) CMA_END;
491 ri.pRecordParent = (PRECORDCORE) pciParent;
492 ri.zOrder = (ULONG) CMA_TOP;
493 ri.cRecordsInsert = 1;
494 ri.fInvalidateRecord = TRUE;
495 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD \"%s\" %.255s", hwndCnr, pci->pszFileName, pffb->achName); // 18 Dec 08 SHL fixme debug
496 if (!WinSendMsg(hwndCnr,
497 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
498 DosSleep(50); //05 Aug 07 GKY 100
499 WinSetFocus(HWND_DESKTOP, hwndCnr);
500 if (WinIsWindow((HAB)0, hwndCnr)) {
501 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD %s", hwndCnr, pci->pszFileName); // 18 Dec 08 SHL fixme debug
502 if (!WinSendMsg(hwndCnr,
503 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
504 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
505 GetPString(IDS_RECORDINSERTFAILEDTEXT));
506 FreeCnrItem(hwndCnr, pci);
507 }
508 else
509 ok = TRUE;
510 }
511 }
512 else
513 ok = TRUE;
514 }
515 }
[2]516 }
[551]517 else if (toupper(*str) > 'B' && str[1] == ':' && str[2] == '\\' &&
518 !str[3]) {
[2]519
[551]520 CHAR s[162];
[2]521
[551]522 sprintf(s,
523 GetPString(IDS_NOSUBDIRS2TEXT),
524 nm,
[730]525 toupper(*pciParent->pszFileName),
[551]526 (isremote) ? GetPString(IDS_NOSUBDIRS3TEXT) : NullStr);
527 Notify(s);
[2]528 }
529 }
530 }
[551]531 else if (toupper(*str) > 'B' && rc != ERROR_NO_MORE_FILES) {
[2]532 CHAR s[CCHMAXPATH + 80];
[551]533 sprintf(s, GetPString(IDS_SEARCHERRORTEXT), rc, str);
[2]534 Notify(s);
535 }
536
537None:
538
539 DosError(FERR_DISABLEHARDERR);
[1471]540 return ok;
[2]541}
[793]542
[1353]543#pragma alloc_text(FLESH,Flesh,FleshEnv,UnFlesh,Stubby)
Note: See TracBrowser for help on using the repository browser.