source: trunk/dll/flesh.c@ 1831

Last change on this file since 1831 was 1831, checked in by Gregg Young, 10 years ago

Additional #if 0-ed PMPrintf stuff

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.4 KB
Line 
1
2/***********************************************************************
3
4 $Id: flesh.c 1831 2015-07-12 22:38:39Z gyoung $
5
6 Flesh
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2005-2012 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 04 Aug 12 GKY Fix trap on close during drive scan
34
35***********************************************************************/
36
37#include <stdlib.h>
38#include <string.h>
39#include <ctype.h>
40//#include <malloc.h>
41
42#define INCL_DOS
43#define INCL_DOSERRORS
44#define INCL_WIN
45#define INCL_LONGLONG // dircnrs.h
46
47#include "fm3dll.h"
48#include "draglist.h" // Data declaration(s)
49#include "notebook.h" // Data declaration(s)
50#include "info.h" // Data declaration(s)
51#include "init.h" // Data declaration(s)
52#include "mainwnd.h" // Data declaration(s)
53#include "fm3str.h"
54#include "filldir.h" // FileAttrToString...
55#include "errutil.h" // Dos_Error...
56#include "strutil.h" // GetPString
57#include "flesh.h"
58#include "valid.h" // IsValidDir
59#include "misc.h" // LoadLibPath
60#include "findrec.h" // FindCnrRecord
61#include "notify.h" // Notify
62#include "wrappers.h" // xfree
63#include "excputil.h" // xbeginthread
64#if 0
65#define __PMPRINTF__
66#include "PMPRINTF.H"
67#endif
68
69// Data definitions
70#pragma data_seg(DATA1)
71
72static PSZ pszSrcFile = __FILE__;
73
74#pragma data_seg(GLOBAL1)
75ULONG NoBrokenNotify;
76BOOL fFilesInTree;
77
78BOOL FleshEnv(HWND hwndCnr, PCNRITEM pciParent)
79{
80 PCNRITEM pciL;
81 DIRCNRDATA *dcd;
82 CHAR path[CCHMAXPATH + 12],
83 fullpath[CCHMAXPATH + 12], *env, *p, *pp, *var = NULL;
84
85 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
86 return FALSE;
87 dcd = (DIRCNRDATA *) WinQueryWindowPtr(hwndCnr, QWL_USER);
88 if (!dcd)
89 return FALSE;
90
91 strcpy(path, pciParent->pszFileName + 1);
92 if (stricmp(path, GetPString(IDS_ENVVARSTEXT) + 1))
93 UnFlesh(hwndCnr, pciParent);
94 if (*path) {
95 path[strlen(path) - 1] = 0;
96 if (!stricmp(path, PCSZ_LIBPATH)) {
97 var = xmalloc(65536, pszSrcFile, __LINE__);
98 if (var)
99 LoadLibPath(var, 65536);
100 env = var;
101 }
102 else
103 env = getenv(path);
104 if (env && *env) {
105 p = env;
106 while (*p) {
107 pp = path;
108 while (*p == ';')
109 p++;
110 while (*p && *p != ';') {
111 *pp = *p;
112 p++;
113 pp++;
114 }
115 *pp = 0;
116 if (*path &&
117 strcmp(path, ".") &&
118 strcmp(path, ".\\") &&
119 strcmp(path, "..") &&
120 strcmp(path, "..\\") &&
121 strncmp(path, ".\\", 2) && strncmp(path, "..\\", 3)) {
122 if (!DosQueryPathInfo(path,
123 FIL_QUERYFULLNAME,
124 fullpath,
125 sizeof(fullpath)) && IsValidDir(fullpath)) {
126 pciL = FindCnrRecord(hwndCnr,
127 fullpath, pciParent, FALSE, FALSE, FALSE);
128 if (pciL) {
129 while (pciL && pciL != (PCNRITEM) - 1 && pciL != pciParent)
130 pciL = WinSendMsg(hwndCnr,
131 CM_QUERYRECORD,
132 MPFROMP(pciL),
133 MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
134 }
135 if (!pciL) {
136
137 RECORDINSERT ri;
138
139 pciL = WinSendMsg(hwndCnr,
140 CM_ALLOCRECORD,
141 MPFROMLONG(EXTRA_RECORD_BYTES),
142 MPFROMLONG(1));
143 if (pciL) {
144 pciL->pszFileName = xstrdup(fullpath, pszSrcFile, __LINE__);
145 pciL->rc.pszIcon = pciL->pszFileName;
146 if (!fNoIconsDirs &&
147 (!isalpha(*fullpath) ||
148 !(driveflags[toupper(*fullpath) - 'A'] &
149 DRIVE_NOLOADICONS)))
150 pciL->rc.hptrIcon = WinLoadFileIcon(fullpath, FALSE);
151 if (!pciL->rc.hptrIcon)
152 pciL->rc.hptrIcon = hptrDir;
153 pciL->attrFile = FILE_DIRECTORY;
154 pciL->pszDispAttr = FileAttrToString(pciL->attrFile);
155 memset(&ri, 0, sizeof(ri));
156 ri.cb = sizeof(ri);
157 ri.pRecordOrder = (PRECORDCORE) CMA_END;
158 ri.pRecordParent = (PRECORDCORE) pciParent;
159 ri.zOrder = (ULONG) CMA_TOP;
160 ri.cRecordsInsert = 1;
161 ri.fInvalidateRecord = FALSE;
162 if (!WinSendMsg(hwndCnr,
163 CM_INSERTRECORD, MPFROMP(pciL), MPFROMP(&ri)))
164 FreeCnrItem(hwndCnr, pciL);
165 }
166 }
167 }
168 }
169 }
170 }
171 xfree(var, pszSrcFile, __LINE__);
172 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
173 CM_QUERYRECORD,
174 MPFROMP(pciParent),
175 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
176 while (pciL && (INT) pciL != -1) {
177 pciL->flags |= (RECFLAGS_NODRAG | RECFLAGS_UNDERENV);
178 WinSendMsg(hwndCnr,
179 CM_INVALIDATERECORD, MPFROMP(&pciL), MPFROM2SHORT(1, 0));
180 pciL = WinSendMsg(hwndCnr,
181 CM_QUERYRECORD,
182 MPFROMP(pciL), MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
183 }
184 }
185 return TRUE;
186}
187
188BOOL Flesh(HWND hwndCnr, PCNRITEM pciParent)
189{
190 PCNRITEM pciL;
191 DIRCNRDATA *dcd;
192 BOOL includefiles = fFilesInTree;
193
194 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
195 return FALSE;
196 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
197 CM_QUERYRECORD,
198 MPFROMP(pciParent),
199 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
200 if (!pciL || !*pciL->pszFileName) {
201 if (pciL && (INT) pciL != -1)
202 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
203 dcd = INSTDATA(hwndCnr);
204 if (dcd && dcd->size != sizeof(DIRCNRDATA))
205 dcd = NULL;
206 if (driveflags[toupper(*pciParent->pszFileName) - 'A'] & DRIVE_INCLUDEFILES)
207 includefiles = TRUE;
208 ProcessDirectory(hwndCnr,
209 pciParent,
210 pciParent->pszFileName,
211 includefiles, // filestoo
212 TRUE, // recurse
213 TRUE, // partial
214 NULL, // stop flag
215 dcd,
216 NULL, // total files
217 NULL); // total bytes
218 if (pciParent && pciParent->pszFileName && !(driveflags[toupper(*pciParent->pszFileName) - 'A'] & DRIVE_RSCANNED))
219 driveflags[toupper(*pciParent->pszFileName) - 'A'] |= DRIVE_RSCANNED;
220 return TRUE;
221 }
222 return FALSE;
223}
224
225BOOL UnFlesh(HWND hwndCnr, PCNRITEM pciParent)
226{
227 BOOL ret = FALSE;
228 PCNRITEM pciL;
229
230 if (!pciParent || !hwndCnr)
231 return FALSE;
232 for (;;) {
233 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
234 CM_QUERYRECORD,
235 MPFROMP(pciParent),
236 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
237 if (pciL && (INT) pciL != -1) {
238 ret = TRUE;
239 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
240 }
241 else
242 break;
243 }
244 if (ret) {
245 WinSendMsg(hwndCnr,
246 CM_INVALIDATERECORD,
247 MPFROMP(&pciParent),
248 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
249 }
250 return ret;
251}
252
253#define DDEPTH 64
254
255/**
256 * Fill in drive tree subtree
257 * @return TRUE if OK, else FALSE
258 * This only scans the root directory and adds the first level directories
259 * Flesh does a recursive scan and should be used on fast hardware.
260 */
261
262BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent)
263{
264 /**
265 * this code is full of workarounds for screwed up LANs.
266 * let's hope all the current LAN programmers fall into
267 * a black hole and make way for people who can get it right...
268 */
269
270 BOOL ok = FALSE;
271 FILEFINDBUF3 ffb[DDEPTH];
272 PFILEFINDBUF3 pffb;
273 HDIR hDir = HDIR_CREATE;
274 ULONG nm, ulM = 1, total = 0, fl = MUST_HAVE_DIRECTORY;
275 CHAR str[CCHMAXPATH];
276 register INT len;
277 APIRET rc, prc;
278 BOOL isadir = FALSE, isremote = FALSE, includefiles = fFilesInTree;
279 ULONG ddepth = DDEPTH;
280 ULONG drvNum;
281 ULONG flags;
282 static BOOL brokenlan = FALSE, isbroken = FALSE;
283
284 if (!pciParent || !*pciParent->pszFileName || !hwndCnr)
285 return FALSE;
286
287 len = strlen(pciParent->pszFileName);
288 memcpy(str, pciParent->pszFileName, len + 1);
289 if (str[len - 1] != '\\')
290 str[len++] = '\\';
291 str[len++] = '*';
292 str[len] = 0;
293
294 if (!isalpha(*str) || str[1] != ':' || str[2] != '\\')
295 MakeFullName(str);
296
297 drvNum = toupper(*pciParent->pszFileName) - 'A';
298 flags = driveflags[drvNum];
299 if (!isalpha(*str) ||
300 str[1] != ':' ||
301 str[2] != '\\' || ((flags & DRIVE_IGNORE)))
302 return FALSE; // Not a directory
303
304 if (flags & DRIVE_INCLUDEFILES)
305 includefiles = TRUE;
306
307 if (flags & DRIVE_REMOTE)
308 isremote = TRUE;
309
310 if (isremote) {
311 if (fRemoteBug) {
312 if (brokenlan) {
313 ddepth = (ULONG) - 1;
314 ddepth--;
315 }
316 ulM = 1;
317 }
318 }
319 else if (isbroken)
320 ddepth = 14;
321
322 if (!fRemoteBug)
323 ulM = (ddepth <= DDEPTH) ? ddepth : 1;
324
325 nm = ulM;
326
327 DosError(FERR_DISABLEHARDERR);
328 if (includefiles)
329 fl = FILE_DIRECTORY;
330 rc = DosFindFirst(str,
331 &hDir,
332 FILE_NORMAL | fl |
333 FILE_READONLY | FILE_ARCHIVED |
334 FILE_SYSTEM | FILE_HIDDEN,
335 &ffb, ulM * sizeof(FILEFINDBUF3), &nm, FIL_STANDARD);
336 if (ulM == 1 && !rc) {
337 do {
338 pffb = &ffb[0];
339 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY) && !brokenlan) {
340 brokenlan = TRUE;
341 ddepth = (ULONG) - 1;
342 ddepth--;
343 if (!NoBrokenNotify) {
344 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
345 HWND_DESKTOP,
346 GetPString(IDS_LANERRORTITLETEXT),
347 GetPString(IDS_LANERRORTEXT));
348 if (prc == MBID_NO) {
349 saymsg(MB_ENTER,
350 HWND_DESKTOP,
351 GetPString(IDS_LANERROR2TITLETEXT),
352 GetPString(IDS_LANERROR2TEXT));
353 NoBrokenNotify = 255;
354 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
355 &NoBrokenNotify, sizeof(ULONG));
356 }
357 }
358 else {
359 NoBrokenNotify--;
360 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
361 &NoBrokenNotify, sizeof(ULONG));
362 }
363 }
364 if (*pffb->achName &&
365 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
366 // Skip . and ..
367 (pffb->achName[0] != '.' ||
368 (pffb->achName[1] &&
369 (pffb->achName[1] != '.' || pffb->achName[2])))) {
370 DosFindClose(hDir);
371 isadir = TRUE;
372 goto Interruptus;
373 }
374 nm = 1;
375 DosError(FERR_DISABLEHARDERR);
376 }
377 while (++total < ddepth && !(rc = (DosFindNext(hDir,
378 &ffb,
379 sizeof(FILEFINDBUF3),
380 &nm))));
381 DosFindClose(hDir);
382 // If drive B:
383 if (toupper(*pciParent->pszFileName) > 'B' &&
384 (*(pciParent->pszFileName + 1)) == ':' &&
385 (*(pciParent->pszFileName + 2)) == '\\' && !(*(pciParent->pszFileName + 3))) {
386
387 CHAR s[132];
388 sprintf(s,
389 GetPString(IDS_NOSUBDIRSTEXT),
390 total, toupper(*pciParent->pszFileName));
391 if (rc && rc != ERROR_NO_MORE_FILES)
392 sprintf(&s[strlen(s)], GetPString(IDS_SEARCHERRORTEXT), rc, str);
393 else if (ddepth < 16)
394 brokenlan = TRUE;
395 Notify(s);
396 }
397 goto None;
398 }
399
400 if (!rc) {
401 DosFindClose(hDir);
402 if (nm) {
403 PBYTE fb = (PBYTE)&ffb[0];
404 for (len = 0; len < nm; len++) {
405 pffb = (PFILEFINDBUF3) fb;
406 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY)) {
407 if (!isbroken) {
408 isbroken = TRUE;
409 if (!NoBrokenNotify) {
410 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
411 HWND_DESKTOP,
412 GetPString(IDS_FSDERRORTITLETEXT),
413 GetPString(IDS_FSDERRORTEXT),
414 isremote ? GetPString(IDS_REMOTETEXT) :
415 GetPString(IDS_LOCALTEXT),
416 *str);
417 if (prc == MBID_NO) {
418 saymsg(MB_ENTER,
419 HWND_DESKTOP,
420 GetPString(IDS_FSDERROR2TITLETEXT),
421 GetPString(IDS_FSDERROR2TEXT));
422 NoBrokenNotify = 255;
423 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
424 &NoBrokenNotify, sizeof(ULONG));
425 }
426 }
427 else {
428 NoBrokenNotify--;
429 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
430 &NoBrokenNotify, sizeof(ULONG));
431 }
432 }
433 }
434 if (*pffb->achName &&
435 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
436 // Skip . and ..
437 (pffb->achName[0] != '.' || (pffb->achName[1]
438 && (pffb->achName[1] != '.'
439 || pffb->achName[2])))) {
440 isadir = TRUE;
441 break;
442 }
443 fb += pffb->oNextEntryOffset;
444 } // for
445
446 Interruptus:
447
448 if (isadir) {
449
450 PCNRITEM pci;
451
452 if (WinIsWindow((HAB)0, hwndCnr)) {
453 pci = WinSendMsg(hwndCnr,
454 CM_ALLOCRECORD,
455 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
456 if (!pci) {
457 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
458 GetPString(IDS_RECORDALLOCFAILEDTEXT));
459 }
460 else {
461 RECORDINSERT ri;
462 pci->pszFileName = NullStr;
463 pci->pszDisplayName = pci->pszFileName;
464 pci->rc.pszIcon = pci->pszDisplayName;
465 memset(&ri, 0, sizeof(RECORDINSERT));
466 ri.cb = sizeof(RECORDINSERT);
467 ri.pRecordOrder = (PRECORDCORE) CMA_END;
468 ri.pRecordParent = (PRECORDCORE) pciParent;
469 ri.zOrder = (ULONG) CMA_TOP;
470 ri.cRecordsInsert = 1;
471 ri.fInvalidateRecord = TRUE;
472 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD \"%s\" %.255s", hwndCnr, pci->pszFileName, pffb->achName); // 18 Dec 08 SHL fixme debug
473 if (!WinSendMsg(hwndCnr,
474 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
475 DosSleep(50); //05 Aug 07 GKY 100
476 WinSetFocus(HWND_DESKTOP, hwndCnr);
477 if (WinIsWindow((HAB)0, hwndCnr)) {
478 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD %s", hwndCnr, pci->pszFileName); // 18 Dec 08 SHL fixme debug
479 if (!WinSendMsg(hwndCnr,
480 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
481 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
482 GetPString(IDS_RECORDINSERTFAILEDTEXT));
483 FreeCnrItem(hwndCnr, pci);
484 }
485 else
486 ok = TRUE;
487 }
488 }
489 else
490 ok = TRUE;
491 }
492 }
493 }
494 else if (toupper(*str) > 'B' && str[1] == ':' && str[2] == '\\' &&
495 !str[3]) {
496
497 CHAR s[162];
498
499 sprintf(s,
500 GetPString(IDS_NOSUBDIRS2TEXT),
501 nm,
502 toupper(*pciParent->pszFileName),
503 (isremote) ? GetPString(IDS_NOSUBDIRS3TEXT) : NullStr);
504 Notify(s);
505 }
506 }
507 }
508 else if (toupper(*str) > 'B' && rc != ERROR_NO_MORE_FILES) {
509 CHAR s[CCHMAXPATH + 80];
510 sprintf(s, GetPString(IDS_SEARCHERRORTEXT), rc, str);
511 Notify(s);
512 }
513
514None:
515
516 DosError(FERR_DISABLEHARDERR);
517 return ok;
518}
519
520#pragma alloc_text(FLESH,Flesh,FleshEnv,UnFlesh,Stubby)
Note: See TracBrowser for help on using the repository browser.