source: trunk/dll/flesh.c@ 1655

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

Cleanup and added comments

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