source: trunk/dll/flesh.c@ 1505

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

Remove unnecessary type casts; minor formating cleanup.

  • 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 1505 2010-04-11 22:29:56Z 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 (fInitialDriveScan) {
204 PROCESSDIR *ProcessDir;
205
206 ProcessDir = xmallocz(sizeof(PROCESSDIR), pszSrcFile, __LINE__);
207 if (!ProcessDir)
208 return FALSE;
209 ProcessDir->hwndCnr = hwndCnr;
210 ProcessDir->pciParent = pciParent;
211 ProcessDir->szDirBase = pciParent->pszFileName;
212 ProcessDir->filestoo = includefiles;
213 ProcessDir->recurse = TRUE;
214 ProcessDir->partial = TRUE;
215 ProcessDir->stopflag = NULL;
216 ProcessDir->dcd = dcd;
217 ProcessDir->pulTotalFiles = NULL;
218 ProcessDir->pullTotalBytes = NULL;
219
220 if (xbeginthread(ProcessDirectoryThread,
221 65536,
222 ProcessDir,
223 pszSrcFile,
224 __LINE__) == -1)
225 {
226 xfree(ProcessDir, pszSrcFile, __LINE__);
227 }
228 }
229 else {
230 ProcessDirectory(hwndCnr,
231 pciParent,
232 pciParent->pszFileName,
233 includefiles, // filestoo
234 TRUE, // recurse
235 TRUE, // partial
236 NULL, // stop flag
237 dcd,
238 NULL, // total files
239 NULL); // total bytes
240 }
241 }
242 driveflags[*pciParent->pszFileName - 'A'] |= DRIVE_RSCANNED;
243 return TRUE;
244}
245
246BOOL UnFlesh(HWND hwndCnr, PCNRITEM pciParent)
247{
248 BOOL ret = FALSE;
249 PCNRITEM pciL;
250
251 if (!pciParent || !hwndCnr)
252 return FALSE;
253 for (;;) {
254 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
255 CM_QUERYRECORD,
256 MPFROMP(pciParent),
257 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
258 if (pciL && (INT) pciL != -1) {
259 ret = TRUE;
260 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
261 }
262 else
263 break;
264 }
265 if (ret) {
266 WinSendMsg(hwndCnr,
267 CM_INVALIDATERECORD,
268 MPFROMP(&pciParent),
269 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
270 }
271 return ret;
272}
273
274#define DDEPTH 64
275
276/**
277 * Fill in drive tree subtree
278 * @return TRUE if OK, else FALSE
279 */
280
281BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent)
282{
283 /**
284 * this code is full of workarounds for screwed up LANs.
285 * let's hope all the current LAN programmers fall into
286 * a black hole and make way for people who can get it right...
287 */
288
289 BOOL ok = FALSE;
290 FILEFINDBUF3 ffb[DDEPTH];
291 PFILEFINDBUF3 pffb;
292 HDIR hDir = HDIR_CREATE;
293 ULONG nm, ulM = 1, total = 0, fl = MUST_HAVE_DIRECTORY;
294 CHAR str[CCHMAXPATH];
295 register INT len;
296 APIRET rc, prc;
297 BOOL isadir = FALSE, isremote = FALSE, includefiles = fFilesInTree;
298 ULONG ddepth = DDEPTH;
299 ULONG drvNum;
300 ULONG flags;
301 static BOOL brokenlan = FALSE, isbroken = FALSE;
302
303 if (!pciParent || !*pciParent->pszFileName || !hwndCnr)
304 return FALSE;
305
306 len = strlen(pciParent->pszFileName);
307 memcpy(str, pciParent->pszFileName, len + 1);
308 if (str[len - 1] != '\\')
309 str[len++] = '\\';
310 str[len++] = '*';
311 str[len] = 0;
312
313 if (!isalpha(*str) || str[1] != ':' || str[2] != '\\')
314 MakeFullName(str);
315
316 drvNum = toupper(*pciParent->pszFileName) - 'A';
317 flags = driveflags[drvNum];
318 if (!isalpha(*str) ||
319 str[1] != ':' ||
320 str[2] != '\\' || ((flags & DRIVE_IGNORE)))
321 return FALSE; // Not a directory
322
323 if (flags & DRIVE_INCLUDEFILES)
324 includefiles = TRUE;
325
326 if (flags & DRIVE_REMOTE)
327 isremote = TRUE;
328
329 if (isremote) {
330 if (fRemoteBug) {
331 if (brokenlan) {
332 ddepth = (ULONG) - 1;
333 ddepth--;
334 }
335 ulM = 1;
336 }
337 }
338 else if (isbroken)
339 ddepth = 14;
340
341 if (!fRemoteBug)
342 ulM = (ddepth <= DDEPTH) ? ddepth : 1;
343
344 nm = ulM;
345
346 DosError(FERR_DISABLEHARDERR);
347 if (includefiles)
348 fl = FILE_DIRECTORY;
349 rc = DosFindFirst(str,
350 &hDir,
351 FILE_NORMAL | fl |
352 FILE_READONLY | FILE_ARCHIVED |
353 FILE_SYSTEM | FILE_HIDDEN,
354 &ffb, ulM * sizeof(FILEFINDBUF3), &nm, FIL_STANDARD);
355 if (ulM == 1 && !rc) {
356 do {
357 pffb = &ffb[0];
358 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY) && !brokenlan) {
359 brokenlan = TRUE;
360 ddepth = (ULONG) - 1;
361 ddepth--;
362 if (!NoBrokenNotify) {
363 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
364 HWND_DESKTOP,
365 GetPString(IDS_LANERRORTITLETEXT),
366 GetPString(IDS_LANERRORTEXT));
367 if (prc == MBID_NO) {
368 saymsg(MB_ENTER,
369 HWND_DESKTOP,
370 GetPString(IDS_LANERROR2TITLETEXT),
371 GetPString(IDS_LANERROR2TEXT));
372 NoBrokenNotify = 255;
373 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
374 &NoBrokenNotify, sizeof(ULONG));
375 }
376 }
377 else {
378 NoBrokenNotify--;
379 PrfWriteProfileData(fmprof, FM3Str, "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 }
396 while (++total < ddepth && !(rc = (DosFindNext(hDir,
397 &ffb,
398 sizeof(FILEFINDBUF3),
399 &nm))));
400 DosFindClose(hDir);
401 // If drive B:
402 if (toupper(*pciParent->pszFileName) > 'B' &&
403 (*(pciParent->pszFileName + 1)) == ':' &&
404 (*(pciParent->pszFileName + 2)) == '\\' && !(*(pciParent->pszFileName + 3))) {
405
406 CHAR s[132];
407 sprintf(s,
408 GetPString(IDS_NOSUBDIRSTEXT),
409 total, toupper(*pciParent->pszFileName));
410 if (rc && rc != ERROR_NO_MORE_FILES)
411 sprintf(&s[strlen(s)], GetPString(IDS_SEARCHERRORTEXT), rc, str);
412 else if (ddepth < 16)
413 brokenlan = TRUE;
414 Notify(s);
415 }
416 goto None;
417 }
418
419 if (!rc) {
420 DosFindClose(hDir);
421 if (nm) {
422 PBYTE fb = (PBYTE)&ffb[0];
423 for (len = 0; len < nm; len++) {
424 pffb = (PFILEFINDBUF3) fb;
425 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY)) {
426 if (!isbroken) {
427 isbroken = TRUE;
428 if (!NoBrokenNotify) {
429 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
430 HWND_DESKTOP,
431 GetPString(IDS_FSDERRORTITLETEXT),
432 GetPString(IDS_FSDERRORTEXT),
433 isremote ? GetPString(IDS_REMOTETEXT) :
434 GetPString(IDS_LOCALTEXT),
435 *str);
436 if (prc == MBID_NO) {
437 saymsg(MB_ENTER,
438 HWND_DESKTOP,
439 GetPString(IDS_FSDERROR2TITLETEXT),
440 GetPString(IDS_FSDERROR2TEXT));
441 NoBrokenNotify = 255;
442 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
443 &NoBrokenNotify, sizeof(ULONG));
444 }
445 }
446 else {
447 NoBrokenNotify--;
448 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
449 &NoBrokenNotify, sizeof(ULONG));
450 }
451 }
452 }
453 if (*pffb->achName &&
454 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
455 // Skip . and ..
456 (pffb->achName[0] != '.' || (pffb->achName[1]
457 && (pffb->achName[1] != '.'
458 || pffb->achName[2])))) {
459 isadir = TRUE;
460 break;
461 }
462 fb += pffb->oNextEntryOffset;
463 } // for
464
465 Interruptus:
466
467 if (isadir) {
468
469 PCNRITEM pci;
470
471 if (WinIsWindow((HAB)0, hwndCnr)) {
472 pci = WinSendMsg(hwndCnr,
473 CM_ALLOCRECORD,
474 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
475 if (!pci) {
476 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
477 GetPString(IDS_RECORDALLOCFAILEDTEXT));
478 }
479 else {
480 RECORDINSERT ri;
481 pci->pszFileName = NullStr;
482 pci->pszDisplayName = pci->pszFileName;
483 pci->rc.pszIcon = pci->pszDisplayName;
484 memset(&ri, 0, sizeof(RECORDINSERT));
485 ri.cb = sizeof(RECORDINSERT);
486 ri.pRecordOrder = (PRECORDCORE) CMA_END;
487 ri.pRecordParent = (PRECORDCORE) pciParent;
488 ri.zOrder = (ULONG) CMA_TOP;
489 ri.cRecordsInsert = 1;
490 ri.fInvalidateRecord = TRUE;
491 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD \"%s\" %.255s", hwndCnr, pci->pszFileName, pffb->achName); // 18 Dec 08 SHL fixme debug
492 if (!WinSendMsg(hwndCnr,
493 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
494 DosSleep(50); //05 Aug 07 GKY 100
495 WinSetFocus(HWND_DESKTOP, hwndCnr);
496 if (WinIsWindow((HAB)0, hwndCnr)) {
497 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD %s", hwndCnr, pci->pszFileName); // 18 Dec 08 SHL fixme debug
498 if (!WinSendMsg(hwndCnr,
499 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
500 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
501 GetPString(IDS_RECORDINSERTFAILEDTEXT));
502 FreeCnrItem(hwndCnr, pci);
503 }
504 else
505 ok = TRUE;
506 }
507 }
508 else
509 ok = TRUE;
510 }
511 }
512 }
513 else if (toupper(*str) > 'B' && str[1] == ':' && str[2] == '\\' &&
514 !str[3]) {
515
516 CHAR s[162];
517
518 sprintf(s,
519 GetPString(IDS_NOSUBDIRS2TEXT),
520 nm,
521 toupper(*pciParent->pszFileName),
522 (isremote) ? GetPString(IDS_NOSUBDIRS3TEXT) : NullStr);
523 Notify(s);
524 }
525 }
526 }
527 else if (toupper(*str) > 'B' && rc != ERROR_NO_MORE_FILES) {
528 CHAR s[CCHMAXPATH + 80];
529 sprintf(s, GetPString(IDS_SEARCHERRORTEXT), rc, str);
530 Notify(s);
531 }
532
533None:
534
535 DosError(FERR_DISABLEHARDERR);
536 return ok;
537}
538
539#pragma alloc_text(FLESH,Flesh,FleshEnv,UnFlesh,Stubby)
Note: See TracBrowser for help on using the repository browser.