source: trunk/dll/flesh.c@ 1650

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

It helps if you actually save the file after you clean it up. See previous commit

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