source: trunk/dll/flesh.c@ 1550

Last change on this file since 1550 was 1550, checked in by Gregg Young, 15 years ago

This actually fixes the double names in the tree container. It also streamlines the initial scan code by eliminating multiple redundant scans.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.7 KB
Line 
1
2/***********************************************************************
3
4 $Id: flesh.c 1550 2010-11-03 02:50:42Z gyoung $
5
6 Flesh
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2005, 2010 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 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
32 17 JAN 10 GKY Changes to get working with Watcom 1.9 Beta (1/16/10). Mostly cast CHAR CONSTANT * as CHAR *.
33
34***********************************************************************/
35
36#include <stdlib.h>
37#include <string.h>
38#include <ctype.h>
39
40#define INCL_DOS
41#define INCL_DOSERRORS
42#define INCL_WIN
43#define INCL_LONGLONG // dircnrs.h
44
45#include "fm3dll.h"
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)
51#include "fm3str.h"
52#include "filldir.h" // FileAttrToString...
53#include "errutil.h" // Dos_Error...
54#include "strutil.h" // GetPString
55#include "flesh.h"
56#include "valid.h" // IsValidDir
57#include "misc.h" // LoadLibPath
58#include "findrec.h" // FindCnrRecord
59#include "notify.h" // Notify
60#include "wrappers.h" // xfree
61#include "excputil.h" // xbeginthread
62
63// Data definitions
64#pragma data_seg(DATA1)
65
66static PSZ pszSrcFile = __FILE__;
67
68#pragma data_seg(GLOBAL1)
69ULONG NoBrokenNotify;
70BOOL fFilesInTree;
71
72BOOL FleshEnv(HWND hwndCnr, PCNRITEM pciParent)
73{
74 PCNRITEM pciL;
75 DIRCNRDATA *dcd;
76 CHAR path[CCHMAXPATH + 12],
77 fullpath[CCHMAXPATH + 12], *env, *p, *pp, *var = NULL;
78
79 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
80 return FALSE;
81 dcd = (DIRCNRDATA *) WinQueryWindowPtr(hwndCnr, QWL_USER);
82 if (!dcd)
83 return FALSE;
84
85 strcpy(path, pciParent->pszFileName + 1);
86 if (stricmp(path, GetPString(IDS_ENVVARSTEXT) + 1))
87 UnFlesh(hwndCnr, pciParent);
88 if (*path) {
89 path[strlen(path) - 1] = 0;
90 if (!stricmp(path, PCSZ_LIBPATH)) {
91 var = xmalloc(65536, pszSrcFile, __LINE__);
92 if (var)
93 LoadLibPath(var, 65536);
94 env = var;
95 }
96 else
97 env = getenv(path);
98 if (env && *env) {
99 p = env;
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) {
130
131 RECORDINSERT ri;
132
133 pciL = WinSendMsg(hwndCnr,
134 CM_ALLOCRECORD,
135 MPFROMLONG(EXTRA_RECORD_BYTES),
136 MPFROMLONG(1));
137 if (pciL) {
138 pciL->pszFileName = xstrdup(fullpath, pszSrcFile, __LINE__);
139 pciL->rc.pszIcon = pciL->pszFileName;
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;
148 pciL->pszDispAttr = FileAttrToString(pciL->attrFile);
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)))
158 FreeCnrItem(hwndCnr, pciL);
159 }
160 }
161 }
162 }
163 }
164 }
165 xfree(var, pszSrcFile, __LINE__);
166 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
167 CM_QUERYRECORD,
168 MPFROMP(pciParent),
169 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
170 while (pciL && (INT) pciL != -1) {
171 pciL->flags |= (RECFLAGS_NODRAG | RECFLAGS_UNDERENV);
172 WinSendMsg(hwndCnr,
173 CM_INVALIDATERECORD, MPFROMP(&pciL), MPFROM2SHORT(1, 0));
174 pciL = WinSendMsg(hwndCnr,
175 CM_QUERYRECORD,
176 MPFROMP(pciL), MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
177 }
178 }
179 return TRUE;
180}
181
182BOOL Flesh(HWND hwndCnr, PCNRITEM pciParent)
183{
184 PCNRITEM pciL;
185 DIRCNRDATA *dcd;
186 BOOL includefiles = fFilesInTree;
187
188 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
189 return FALSE;
190 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
191 CM_QUERYRECORD,
192 MPFROMP(pciParent),
193 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
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#if 0
204 if (fInitialDriveScan) {
205 PROCESSDIR *ProcessDir;
206
207 ProcessDir = xmallocz(sizeof(PROCESSDIR), pszSrcFile, __LINE__);
208 if (!ProcessDir)
209 return FALSE;
210 ProcessDir->hwndCnr = hwndCnr;
211 ProcessDir->pciParent = pciParent;
212 ProcessDir->szDirBase = pciParent->pszFileName;
213 ProcessDir->filestoo = includefiles;
214 ProcessDir->recurse = TRUE;
215 ProcessDir->partial = TRUE;
216 ProcessDir->stopflag = NULL;
217 ProcessDir->dcd = dcd;
218 ProcessDir->pulTotalFiles = NULL;
219 ProcessDir->pullTotalBytes = NULL;
220
221 if (xbeginthread(ProcessDirectoryThread,
222 65536,
223 ProcessDir,
224 pszSrcFile,
225 __LINE__) == -1)
226 {
227 xfree(ProcessDir, pszSrcFile, __LINE__);
228 }
229 }
230 else {
231# endif
232 ProcessDirectory(hwndCnr,
233 pciParent,
234 pciParent->pszFileName,
235 includefiles, // filestoo
236 TRUE, // recurse
237 TRUE, // partial
238 NULL, // stop flag
239 dcd,
240 NULL, // total files
241 NULL); // total bytes
242 //}
243 }
244 driveflags[*pciParent->pszFileName - 'A'] |= DRIVE_RSCANNED;
245 return TRUE;
246}
247
248BOOL UnFlesh(HWND hwndCnr, PCNRITEM pciParent)
249{
250 BOOL ret = FALSE;
251 PCNRITEM pciL;
252
253 if (!pciParent || !hwndCnr)
254 return FALSE;
255 for (;;) {
256 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
257 CM_QUERYRECORD,
258 MPFROMP(pciParent),
259 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
260 if (pciL && (INT) pciL != -1) {
261 ret = TRUE;
262 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
263 }
264 else
265 break;
266 }
267 if (ret) {
268 WinSendMsg(hwndCnr,
269 CM_INVALIDATERECORD,
270 MPFROMP(&pciParent),
271 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
272 }
273 return ret;
274}
275
276#define DDEPTH 64
277
278/**
279 * Fill in drive tree subtree
280 * @return TRUE if OK, else FALSE
281 */
282
283BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent)
284{
285 /**
286 * this code is full of workarounds for screwed up LANs.
287 * let's hope all the current LAN programmers fall into
288 * a black hole and make way for people who can get it right...
289 */
290
291 BOOL ok = FALSE;
292 FILEFINDBUF3 ffb[DDEPTH];
293 PFILEFINDBUF3 pffb;
294 HDIR hDir = HDIR_CREATE;
295 ULONG nm, ulM = 1, total = 0, fl = MUST_HAVE_DIRECTORY;
296 CHAR str[CCHMAXPATH];
297 register INT len;
298 APIRET rc, prc;
299 BOOL isadir = FALSE, isremote = FALSE, includefiles = fFilesInTree;
300 ULONG ddepth = DDEPTH;
301 ULONG drvNum;
302 ULONG flags;
303 static BOOL brokenlan = FALSE, isbroken = FALSE;
304
305 if (!pciParent || !*pciParent->pszFileName || !hwndCnr)
306 return FALSE;
307
308 len = strlen(pciParent->pszFileName);
309 memcpy(str, pciParent->pszFileName, len + 1);
310 if (str[len - 1] != '\\')
311 str[len++] = '\\';
312 str[len++] = '*';
313 str[len] = 0;
314
315 if (!isalpha(*str) || str[1] != ':' || str[2] != '\\')
316 MakeFullName(str);
317
318 drvNum = toupper(*pciParent->pszFileName) - 'A';
319 flags = driveflags[drvNum];
320 if (!isalpha(*str) ||
321 str[1] != ':' ||
322 str[2] != '\\' || ((flags & DRIVE_IGNORE)))
323 return FALSE; // Not a directory
324
325 if (flags & DRIVE_INCLUDEFILES)
326 includefiles = TRUE;
327
328 if (flags & DRIVE_REMOTE)
329 isremote = TRUE;
330
331 if (isremote) {
332 if (fRemoteBug) {
333 if (brokenlan) {
334 ddepth = (ULONG) - 1;
335 ddepth--;
336 }
337 ulM = 1;
338 }
339 }
340 else if (isbroken)
341 ddepth = 14;
342
343 if (!fRemoteBug)
344 ulM = (ddepth <= DDEPTH) ? ddepth : 1;
345
346 nm = ulM;
347
348 DosError(FERR_DISABLEHARDERR);
349 if (includefiles)
350 fl = FILE_DIRECTORY;
351 rc = DosFindFirst(str,
352 &hDir,
353 FILE_NORMAL | fl |
354 FILE_READONLY | FILE_ARCHIVED |
355 FILE_SYSTEM | FILE_HIDDEN,
356 &ffb, ulM * sizeof(FILEFINDBUF3), &nm, FIL_STANDARD);
357 if (ulM == 1 && !rc) {
358 do {
359 pffb = &ffb[0];
360 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY) && !brokenlan) {
361 brokenlan = TRUE;
362 ddepth = (ULONG) - 1;
363 ddepth--;
364 if (!NoBrokenNotify) {
365 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
366 HWND_DESKTOP,
367 GetPString(IDS_LANERRORTITLETEXT),
368 GetPString(IDS_LANERRORTEXT));
369 if (prc == MBID_NO) {
370 saymsg(MB_ENTER,
371 HWND_DESKTOP,
372 GetPString(IDS_LANERROR2TITLETEXT),
373 GetPString(IDS_LANERROR2TEXT));
374 NoBrokenNotify = 255;
375 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
376 &NoBrokenNotify, sizeof(ULONG));
377 }
378 }
379 else {
380 NoBrokenNotify--;
381 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
382 &NoBrokenNotify, sizeof(ULONG));
383 }
384 }
385 if (*pffb->achName &&
386 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
387 // Skip . and ..
388 (pffb->achName[0] != '.' ||
389 (pffb->achName[1] &&
390 (pffb->achName[1] != '.' || pffb->achName[2])))) {
391 DosFindClose(hDir);
392 isadir = TRUE;
393 goto Interruptus;
394 }
395 nm = 1;
396 DosError(FERR_DISABLEHARDERR);
397 }
398 while (++total < ddepth && !(rc = (DosFindNext(hDir,
399 &ffb,
400 sizeof(FILEFINDBUF3),
401 &nm))));
402 DosFindClose(hDir);
403 // If drive B:
404 if (toupper(*pciParent->pszFileName) > 'B' &&
405 (*(pciParent->pszFileName + 1)) == ':' &&
406 (*(pciParent->pszFileName + 2)) == '\\' && !(*(pciParent->pszFileName + 3))) {
407
408 CHAR s[132];
409 sprintf(s,
410 GetPString(IDS_NOSUBDIRSTEXT),
411 total, toupper(*pciParent->pszFileName));
412 if (rc && rc != ERROR_NO_MORE_FILES)
413 sprintf(&s[strlen(s)], GetPString(IDS_SEARCHERRORTEXT), rc, str);
414 else if (ddepth < 16)
415 brokenlan = TRUE;
416 Notify(s);
417 }
418 goto None;
419 }
420
421 if (!rc) {
422 DosFindClose(hDir);
423 if (nm) {
424 PBYTE fb = (PBYTE)&ffb[0];
425 for (len = 0; len < nm; len++) {
426 pffb = (PFILEFINDBUF3) fb;
427 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY)) {
428 if (!isbroken) {
429 isbroken = TRUE;
430 if (!NoBrokenNotify) {
431 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
432 HWND_DESKTOP,
433 GetPString(IDS_FSDERRORTITLETEXT),
434 GetPString(IDS_FSDERRORTEXT),
435 isremote ? GetPString(IDS_REMOTETEXT) :
436 GetPString(IDS_LOCALTEXT),
437 *str);
438 if (prc == MBID_NO) {
439 saymsg(MB_ENTER,
440 HWND_DESKTOP,
441 GetPString(IDS_FSDERROR2TITLETEXT),
442 GetPString(IDS_FSDERROR2TEXT));
443 NoBrokenNotify = 255;
444 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
445 &NoBrokenNotify, sizeof(ULONG));
446 }
447 }
448 else {
449 NoBrokenNotify--;
450 PrfWriteProfileData(fmprof, FM3Str, "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 ok = TRUE;
508 }
509 }
510 else
511 ok = 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 CHAR s[CCHMAXPATH + 80];
531 sprintf(s, GetPString(IDS_SEARCHERRORTEXT), rc, str);
532 Notify(s);
533 }
534
535None:
536
537 DosError(FERR_DISABLEHARDERR);
538 return ok;
539}
540
541#pragma alloc_text(FLESH,Flesh,FleshEnv,UnFlesh,Stubby)
Note: See TracBrowser for help on using the repository browser.