source: trunk/dll/flesh.c@ 1489

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

Fixed separate parameters; added the ability to set it either globally or for just one app; some files only contain white space changes.

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