source: trunk/dll/flesh.c@ 1400

Last change on this file since 1400 was 1400, checked in by Gregg Young, 17 years ago

Remainder of changes to rename commafmt.h/c (Ticket 28, 82); Additional strings moved to PCSZs in init.c (Ticket 6); Added WriteDetailsSwitches used it and LoadDetailsSwitches to consolidate inline code (Ticket 343, 344)

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