source: trunk/dll/flesh.c@ 1353

Last change on this file since 1353 was 1353, checked in by Steven Levine, 17 years ago

Minor cleanup

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