source: trunk/dll/flesh.c@ 1471

Last change on this file since 1471 was 1471, checked in by Steven Levine, 16 years ago

Remember last filter mask selection
Use Ctrl-click to select state or commonly used directory quicklist entry without activating.
Use Ctrl-click to select walk dialog user list entry without activating.
Avoid drivebar MB2 exception
Remember last seek and scan mask selection across runs
Avoid traps when changing tree container display style
Restore missing drives to drive list dropdown
Minor documentation updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
Line 
1
2/***********************************************************************
3
4 $Id: flesh.c 1471 2009-10-13 23:43:04Z stevenhl $
5
6 Flesh
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2005, 2009 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
270/**
271 * Fill in drive tree subtree
272 * @return TRUE if OK, else FALSE
273 */
274
275BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent)
276{
277 /**
278 * this code is full of workarounds for screwed up LANs.
279 * let's hope all the current LAN programmers fall into
280 * a black hole and make way for people who can get it right...
281 */
282
283 BOOL ok = FALSE;
284 FILEFINDBUF3 ffb[DDEPTH];
285 PFILEFINDBUF3 pffb;
286 HDIR hDir = HDIR_CREATE;
287 ULONG nm, ulM = 1, total = 0, fl = MUST_HAVE_DIRECTORY;
288 CHAR str[CCHMAXPATH];
289 register INT len;
290 APIRET rc, prc;
291 BOOL isadir = FALSE, isremote = FALSE, includefiles = fFilesInTree;
292 ULONG ddepth = 3;
293 ULONG drvNum;
294 ULONG flags;
295 static BOOL brokenlan = FALSE, isbroken = FALSE;
296
297 if (!pciParent || !*pciParent->pszFileName || !hwndCnr)
298 return FALSE;
299
300 len = strlen(pciParent->pszFileName);
301 memcpy(str, pciParent->pszFileName, len + 1);
302 if (str[len - 1] != '\\')
303 str[len++] = '\\';
304 str[len++] = '*';
305 str[len] = 0;
306
307 if (!isalpha(*str) || str[1] != ':' || str[2] != '\\')
308 MakeFullName(str);
309
310 drvNum = toupper(*pciParent->pszFileName) - 'A';
311 flags = driveflags[drvNum];
312 if (!isalpha(*str) ||
313 str[1] != ':' ||
314 str[2] != '\\' || ((flags & DRIVE_IGNORE)))
315 return FALSE; // Not a directory
316
317 //if (isalpha(*str) && // redundant check GKY 11/24/08
318 if (flags & DRIVE_INCLUDEFILES)
319 includefiles = TRUE;
320
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 drive B:
401 if (toupper(*pciParent->pszFileName) > 'B' &&
402 (*(pciParent->pszFileName + 1)) == ':' &&
403 (*(pciParent->pszFileName + 2)) == '\\' && !(*(pciParent->pszFileName + 3))) {
404
405 CHAR s[132];
406 sprintf(s,
407 GetPString(IDS_NOSUBDIRSTEXT),
408 total, toupper(*pciParent->pszFileName));
409 if (rc && rc != ERROR_NO_MORE_FILES)
410 sprintf(&s[strlen(s)], GetPString(IDS_SEARCHERRORTEXT), rc, str);
411 else if (ddepth < 16)
412 brokenlan = TRUE;
413 Notify(s);
414 }
415 goto None;
416 }
417
418 if (!rc) {
419 DosFindClose(hDir);
420 if (nm) {
421 PBYTE fb = (PBYTE)&ffb[0];
422 for (len = 0; len < nm; len++) {
423 pffb = (PFILEFINDBUF3) fb;
424 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY)) {
425 if (!isbroken) {
426 isbroken = TRUE;
427 if (!NoBrokenNotify) {
428 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
429 HWND_DESKTOP,
430 GetPString(IDS_FSDERRORTITLETEXT),
431 GetPString(IDS_FSDERRORTEXT),
432 isremote ? GetPString(IDS_REMOTETEXT) :
433 GetPString(IDS_LOCALTEXT),
434 *str);
435 if (prc == MBID_NO) {
436 saymsg(MB_ENTER,
437 HWND_DESKTOP,
438 GetPString(IDS_FSDERROR2TITLETEXT),
439 GetPString(IDS_FSDERROR2TEXT));
440 NoBrokenNotify = 255;
441 PrfWriteProfileData(fmprof,
442 FM3Str,
443 "NoBrokenNotify",
444 &NoBrokenNotify, sizeof(ULONG));
445 }
446 }
447 else {
448 NoBrokenNotify--;
449 PrfWriteProfileData(fmprof,
450 FM3Str,
451 "NoBrokenNotify",
452 &NoBrokenNotify, sizeof(ULONG));
453 }
454 }
455 }
456 if (*pffb->achName &&
457 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
458 // Skip . and ..
459 (pffb->achName[0] != '.' || (pffb->achName[1]
460 && (pffb->achName[1] != '.'
461 || pffb->achName[2])))) {
462 isadir = TRUE;
463 break;
464 }
465 fb += pffb->oNextEntryOffset;
466 } // for
467
468 Interruptus:
469
470 if (isadir) {
471
472 PCNRITEM pci;
473
474 if (WinIsWindow((HAB)0, hwndCnr)) {
475 pci = WinSendMsg(hwndCnr,
476 CM_ALLOCRECORD,
477 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
478 if (!pci) {
479 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
480 GetPString(IDS_RECORDALLOCFAILEDTEXT));
481 }
482 else {
483 RECORDINSERT ri;
484 pci->pszFileName = NullStr;
485 pci->pszDisplayName = pci->pszFileName;
486 pci->rc.pszIcon = pci->pszDisplayName;
487 memset(&ri, 0, sizeof(RECORDINSERT));
488 ri.cb = sizeof(RECORDINSERT);
489 ri.pRecordOrder = (PRECORDCORE) CMA_END;
490 ri.pRecordParent = (PRECORDCORE) pciParent;
491 ri.zOrder = (ULONG) CMA_TOP;
492 ri.cRecordsInsert = 1;
493 ri.fInvalidateRecord = TRUE;
494 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD \"%s\" %.255s", hwndCnr, pci->pszFileName, pffb->achName); // 18 Dec 08 SHL fixme debug
495 if (!WinSendMsg(hwndCnr,
496 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
497 DosSleep(50); //05 Aug 07 GKY 100
498 WinSetFocus(HWND_DESKTOP, hwndCnr);
499 if (WinIsWindow((HAB)0, hwndCnr)) {
500 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD %s", hwndCnr, pci->pszFileName); // 18 Dec 08 SHL fixme debug
501 if (!WinSendMsg(hwndCnr,
502 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
503 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
504 GetPString(IDS_RECORDINSERTFAILEDTEXT));
505 FreeCnrItem(hwndCnr, pci);
506 }
507 else
508 ok = TRUE;
509 }
510 }
511 else
512 ok = TRUE;
513 }
514 }
515 }
516 else if (toupper(*str) > 'B' && str[1] == ':' && str[2] == '\\' &&
517 !str[3]) {
518
519 CHAR s[162];
520
521 sprintf(s,
522 GetPString(IDS_NOSUBDIRS2TEXT),
523 nm,
524 toupper(*pciParent->pszFileName),
525 (isremote) ? GetPString(IDS_NOSUBDIRS3TEXT) : NullStr);
526 Notify(s);
527 }
528 }
529 }
530 else if (toupper(*str) > 'B' && rc != ERROR_NO_MORE_FILES) {
531 CHAR s[CCHMAXPATH + 80];
532 sprintf(s, GetPString(IDS_SEARCHERRORTEXT), rc, str);
533 Notify(s);
534 }
535
536None:
537
538 DosError(FERR_DISABLEHARDERR);
539 return ok;
540}
541
542#pragma alloc_text(FLESH,Flesh,FleshEnv,UnFlesh,Stubby)
Note: See TracBrowser for help on using the repository browser.