source: trunk/dll/flesh.c@ 1409

Last change on this file since 1409 was 1409, checked in by Gregg Young, 16 years ago

Rename some container ini keys consolidate inline code in WriteDetailsSwitches, LoadDetailsSwitches and RemoveCnrSwitches (Ticket 343, 345, 347) Save changes to detail switches for compare directories (Ticket 346). Move additional messages to PCSZs (Ticket 6). Comments and minor code clean up.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.9 KB
Line 
1
2/***********************************************************************
3
4 $Id: flesh.c 1409 2009-03-19 23:35:30Z gyoung $
5
6 Flesh
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2005, 2008 Steven H. Levine
10
11 24 May 05 SHL Rework Win_Error usage
12 25 May 05 SHL Rework for ProcessDirectory
13 28 May 05 SHL Clean while reading code
14 24 Oct 05 SHL Delete obsolete code
15 22 Jul 06 SHL Check more run time errors
16 19 Oct 06 SHL Stubby - correct . and .. detect
17 22 Mar 07 GKY Use QWL_USER
18 01 Aug 07 SHL Sync with CNRITEM mods
19 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
20 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
21 29 Feb 08 GKY Use xfree where appropriate
22 24 Nov 08 GKY remove redundant code and minor speed up of Stubby
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.
26 08 Mar 09 GKY Additional strings move to PCSZs in init.c
27
28***********************************************************************/
29
30#include <stdlib.h>
31#include <string.h>
32#include <ctype.h>
33
34#define INCL_DOS
35#define INCL_DOSERRORS
36#define INCL_WIN
37#define INCL_LONGLONG // dircnrs.h
38
39#include "fm3dll.h"
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)
45#include "fm3str.h"
46#include "filldir.h" // FileAttrToString...
47#include "errutil.h" // Dos_Error...
48#include "strutil.h" // GetPString
49#include "flesh.h"
50#include "valid.h" // IsValidDir
51#include "misc.h" // LoadLibPath
52#include "findrec.h" // FindCnrRecord
53#include "notify.h" // Notify
54#include "wrappers.h" // xfree
55#include "excputil.h" // xbeginthread
56
57// Data definitions
58#pragma data_seg(DATA1)
59
60static PSZ pszSrcFile = __FILE__;
61
62#pragma data_seg(GLOBAL1)
63ULONG NoBrokenNotify;
64BOOL fFilesInTree;
65
66BOOL FleshEnv(HWND hwndCnr, PCNRITEM pciParent)
67{
68 PCNRITEM pciL;
69 DIRCNRDATA *dcd;
70 CHAR path[CCHMAXPATH + 12],
71 fullpath[CCHMAXPATH + 12], *env, *p, *pp, *var = NULL;
72
73 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
74 return FALSE;
75 dcd = (DIRCNRDATA *) WinQueryWindowPtr(hwndCnr, QWL_USER);
76 if (!dcd)
77 return FALSE;
78
79 strcpy(path, pciParent->pszFileName + 1);
80 if (stricmp(path, GetPString(IDS_ENVVARSTEXT) + 1))
81 UnFlesh(hwndCnr, pciParent);
82 if (*path) {
83 path[strlen(path) - 1] = 0;
84 if (!stricmp(path, PCSZ_LIBPATH)) {
85 var = xmalloc(65536, pszSrcFile, __LINE__);
86 if (var)
87 LoadLibPath(var, 65536);
88 env = var;
89 }
90 else
91 env = getenv(path);
92 if (env && *env) {
93 p = env;
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) {
124
125 RECORDINSERT ri;
126
127 pciL = WinSendMsg(hwndCnr,
128 CM_ALLOCRECORD,
129 MPFROMLONG(EXTRA_RECORD_BYTES),
130 MPFROMLONG(1));
131 if (pciL) {
132 pciL->pszFileName = xstrdup(fullpath, pszSrcFile, __LINE__);
133 pciL->rc.pszIcon = pciL->pszFileName;
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;
142 pciL->pszDispAttr = FileAttrToString(pciL->attrFile);
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)))
152 FreeCnrItem(hwndCnr, pciL);
153 }
154 }
155 }
156 }
157 }
158 }
159 xfree(var, pszSrcFile, __LINE__);
160 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
161 CM_QUERYRECORD,
162 MPFROMP(pciParent),
163 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
164 while (pciL && (INT) pciL != -1) {
165 pciL->flags |= (RECFLAGS_NODRAG | RECFLAGS_UNDERENV);
166 WinSendMsg(hwndCnr,
167 CM_INVALIDATERECORD, MPFROMP(&pciL), MPFROM2SHORT(1, 0));
168 pciL = WinSendMsg(hwndCnr,
169 CM_QUERYRECORD,
170 MPFROMP(pciL), MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
171 }
172 }
173 return TRUE;
174}
175
176BOOL Flesh(HWND hwndCnr, PCNRITEM pciParent)
177{
178 PCNRITEM pciL;
179 DIRCNRDATA *dcd;
180 BOOL includefiles = fFilesInTree;
181
182 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
183 return FALSE;
184 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
185 CM_QUERYRECORD,
186 MPFROMP(pciParent),
187 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
188 if (!pciL || !*pciL->pszFileName) {
189 if (pciL && (INT) pciL != -1)
190 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
191 dcd = INSTDATA(hwndCnr);
192 if (dcd && dcd->size != sizeof(DIRCNRDATA))
193 dcd = NULL;
194 if (driveflags[toupper(*pciParent->pszFileName) - 'A'] &
195 DRIVE_INCLUDEFILES)
196 includefiles = TRUE;
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 }
235 }
236 driveflags[*pciParent->pszFileName - 'A'] |= DRIVE_RSCANNED;
237 return TRUE;
238}
239
240BOOL UnFlesh(HWND hwndCnr, PCNRITEM pciParent)
241{
242 BOOL ret = FALSE;
243 PCNRITEM pciL;
244
245 if (!pciParent || !hwndCnr)
246 return FALSE;
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) {
253 ret = TRUE;
254 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
255 }
256 else
257 break;
258 }
259 if (ret) {
260 WinSendMsg(hwndCnr,
261 CM_INVALIDATERECORD,
262 MPFROMP(&pciParent),
263 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
264 }
265 return ret;
266}
267
268#define DDEPTH 16
269
270BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent)
271{
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
278 BOOL ret = FALSE;
279 FILEFINDBUF3 ffb[DDEPTH];
280 PFILEFINDBUF3 pffb;
281 HDIR hDir = HDIR_CREATE;
282 ULONG nm, ulM = 1, total = 0, fl = MUST_HAVE_DIRECTORY;
283 CHAR str[CCHMAXPATH];
284 register INT len;
285 APIRET rc, prc;
286 BOOL isadir = FALSE, isremote = FALSE, includefiles = fFilesInTree;
287 ULONG ddepth = 3;
288 ULONG drvNum;
289 ULONG flags;
290 static BOOL brokenlan = FALSE, isbroken = FALSE;
291
292 if (!pciParent || !*pciParent->pszFileName || !hwndCnr)
293 return FALSE;
294
295 len = strlen(pciParent->pszFileName);
296 memcpy(str, pciParent->pszFileName, len + 1);
297 if (str[len - 1] != '\\')
298 str[len++] = '\\';
299 str[len++] = '*';
300 str[len] = 0;
301
302 if (!isalpha(*str) || str[1] != ':' || str[2] != '\\')
303 MakeFullName(str);
304
305 drvNum = toupper(*pciParent->pszFileName) - 'A';
306 flags = driveflags[drvNum];
307 if (!isalpha(*str) ||
308 str[1] != ':' ||
309 str[2] != '\\' || ((flags & DRIVE_IGNORE)))
310 return FALSE;
311
312 //if (isalpha(*str) && // redundant check GKY 11/24/08
313 if (flags & DRIVE_INCLUDEFILES)
314 includefiles = TRUE;
315
316#if 0
317 if (!isalpha(*str) || // redundant check GKY 11/24/08
318 str[1] != ':' ||
319 str[2] != '\\' ||
320#endif
321 if (flags & DRIVE_REMOTE)
322 isremote = TRUE;
323
324 if (isremote) {
325 ddepth = 14;
326 if (fRemoteBug) {
327 if (brokenlan) {
328 ddepth = (ULONG) - 1;
329 ddepth--;
330 }
331 ulM = 1;
332 }
333 }
334 else if (isbroken)
335 ddepth = 14;
336
337 if (!isremote || !fRemoteBug)
338 ulM = (ddepth < 16) ? ddepth : 1;
339
340 nm = ulM;
341
342 DosError(FERR_DISABLEHARDERR);
343 if (includefiles)
344 fl = FILE_DIRECTORY;
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);
351 if (ulM == 1 && !rc) {
352 do {
353 pffb = &ffb[0];
354 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY) && !brokenlan) {
355 brokenlan = TRUE;
356 ddepth = (ULONG) - 1;
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));
368 NoBrokenNotify = 255;
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 }
382 }
383 if (*pffb->achName &&
384 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
385 // Skip . and ..
386 (pffb->achName[0] != '.' ||
387 (pffb->achName[1] &&
388 (pffb->achName[1] != '.' || pffb->achName[2])))) {
389 DosFindClose(hDir);
390 isadir = TRUE;
391 goto Interruptus;
392 }
393 nm = 1;
394 DosError(FERR_DISABLEHARDERR);
395 } while (++total < ddepth && !(rc = (DosFindNext(hDir,
396 &ffb,
397 sizeof(FILEFINDBUF3),
398 &nm))));
399 DosFindClose(hDir);
400 if (toupper(*pciParent->pszFileName) > 'B' &&
401 (*(pciParent->pszFileName + 1)) == ':' &&
402 (*(pciParent->pszFileName + 2)) == '\\' && !(*(pciParent->pszFileName + 3))) {
403
404 CHAR s[132];
405 sprintf(s,
406 GetPString(IDS_NOSUBDIRSTEXT),
407 total, toupper(*pciParent->pszFileName));
408 if (rc && rc != ERROR_NO_MORE_FILES)
409 sprintf(&s[strlen(s)], GetPString(IDS_SEARCHERRORTEXT), rc, str);
410 else if (ddepth < 16)
411 brokenlan = TRUE;
412 Notify(s);
413 }
414 goto None;
415 }
416
417 if (!rc) {
418 DosFindClose(hDir);
419 if (nm) {
420 PBYTE fb = (PBYTE)&ffb[0];
421 for (len = 0; len < nm; len++) {
422 pffb = (PFILEFINDBUF3) fb;
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));
439 NoBrokenNotify = 255;
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)) &&
457 // Skip . and ..
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;
465 } // for
466
467 Interruptus:
468
469 if (isadir) {
470
471 PCNRITEM pci;
472
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;
491 ri.cRecordsInsert = 1;
492 ri.fInvalidateRecord = TRUE;
493 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD \"%s\" %.255s", hwndCnr, pci->pszFileName, pffb->achName); // 18 Dec 08 SHL fixme debug
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)) {
499 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD %s", hwndCnr, pci->pszFileName); // 18 Dec 08 SHL fixme debug
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 }
514 }
515 else if (toupper(*str) > 'B' && str[1] == ':' && str[2] == '\\' &&
516 !str[3]) {
517
518 CHAR s[162];
519
520 sprintf(s,
521 GetPString(IDS_NOSUBDIRS2TEXT),
522 nm,
523 toupper(*pciParent->pszFileName),
524 (isremote) ? GetPString(IDS_NOSUBDIRS3TEXT) : NullStr);
525 Notify(s);
526 }
527 }
528 }
529 else if (toupper(*str) > 'B' && rc != ERROR_NO_MORE_FILES) {
530
531 CHAR s[CCHMAXPATH + 80];
532
533 sprintf(s, GetPString(IDS_SEARCHERRORTEXT), rc, str);
534 Notify(s);
535 }
536
537None:
538
539 DosError(FERR_DISABLEHARDERR);
540 return ret;
541}
542
543#pragma alloc_text(FLESH,Flesh,FleshEnv,UnFlesh,Stubby)
Note: See TracBrowser for help on using the repository browser.