Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2350 lines
52 KiB

  1. /*++
  2. Copyright (c) 1993-1995 Microsoft Corporation
  3. Module Name:
  4. FileSel.c
  5. Abstract:
  6. Handles processing for the file selection listbox. This is a
  7. hierarchical file/directory tree with checkboxes besides the files
  8. and directories.
  9. If the checkbox is checked then that file or directory will be
  10. copied, otherwise it won't. There are some directories that are
  11. excluded by default. These are directories on the NW server that
  12. are known to contain binaries that are not needed on the NT side
  13. (such as the NetWare administration tools).
  14. Author:
  15. Arthur Hanson (arth) 10-Feb-1994
  16. Revision History:
  17. --*/
  18. #include "globals.h"
  19. #include "hierfile.h"
  20. #include "nwconv.h"
  21. #include "convapi.h"
  22. #include "ntnetapi.h"
  23. #include "nwnetapi.h"
  24. #include "columnlb.h"
  25. #include "statbox.h"
  26. #include "userdlg.h"
  27. #include <math.h> // For pow function
  28. #define X_BORDER 10
  29. #define Y_BORDER 10
  30. #define SPLITTER_WIDTH 3
  31. #define BUTTON_Y_BORDER 6
  32. #define BUTTON_X_BORDER 10
  33. static int List1Width;
  34. static int Splitter_Left;
  35. static int Splitter_Bottom;
  36. static HCURSOR CursorSplitter;
  37. static HWND hwndList2 = 0;
  38. static HWND hwndList1 = 0;
  39. static SHARE_BUFFER *CurrentShare;
  40. static SOURCE_SERVER_BUFFER *SServ;
  41. static BOOL HiddenFiles = FALSE;
  42. static BOOL SystemFiles = FALSE;
  43. static DIR_BUFFER *oDir = NULL;
  44. static ULONG TotalFileSize = 0;
  45. static LPARAM mouseHit = 0;
  46. static WORD LastFocus = 0;
  47. static HWND ListFocus = NULL;
  48. static ULONG TCount;
  49. static WNDPROC _wpOrigWndProc;
  50. static WNDPROC _wpOrigWndProc2;
  51. HEIRDRAWSTRUCT HierDrawStruct;
  52. BOOL SysDir = FALSE;
  53. #define ROWS 2
  54. #define COLS 2
  55. // define a scratch buffer for quickly building up dir/file lists
  56. #define DEF_NUM_RECS 50
  57. #define DEF_REC_DELTA 25
  58. static UINT BufferSize = 0;
  59. static WIN32_FIND_DATA *ffd = NULL;
  60. /*+-------------------------------------------------------------------------+
  61. | Routines for Directory/File Trees |
  62. +-------------------------------------------------------------------------+*/
  63. /////////////////////////////////////////////////////////////////////////
  64. FILE_PATH_BUFFER *
  65. FilePathInit()
  66. /*++
  67. Routine Description:
  68. Arguments:
  69. Return Value:
  70. --*/
  71. {
  72. FILE_PATH_BUFFER *fpBuf = NULL;
  73. fpBuf = AllocMemory(sizeof(FILE_PATH_BUFFER));
  74. if (fpBuf == NULL)
  75. return NULL;
  76. memset(fpBuf, 0, sizeof(FILE_PATH_BUFFER));
  77. return fpBuf;
  78. } // FilePathInit
  79. /////////////////////////////////////////////////////////////////////////
  80. VOID
  81. FilePathServerSet(
  82. FILE_PATH_BUFFER *fpBuf,
  83. LPTSTR Server
  84. )
  85. /*++
  86. Routine Description:
  87. Arguments:
  88. Return Value:
  89. --*/
  90. {
  91. fpBuf->Server = Server;
  92. if (fpBuf->Server == NULL)
  93. return;
  94. wsprintf(fpBuf->FullPath, TEXT("\\\\%s\\"), Server);
  95. } // FilePathServerSet
  96. /////////////////////////////////////////////////////////////////////////
  97. VOID
  98. FilePathShareSet(
  99. FILE_PATH_BUFFER *fpBuf,
  100. LPTSTR Share
  101. )
  102. /*++
  103. Routine Description:
  104. Arguments:
  105. Return Value:
  106. --*/
  107. {
  108. fpBuf->Share = Share;
  109. if ((fpBuf->Server == NULL) || (fpBuf->Share == NULL))
  110. return;
  111. wsprintf(fpBuf->FullPath, TEXT("\\\\%s\\%s"), fpBuf->Server, Share);
  112. fpBuf->Path = &fpBuf->FullPath[lstrlen(fpBuf->FullPath)];
  113. } // FilePathShareSet
  114. /////////////////////////////////////////////////////////////////////////
  115. VOID
  116. FilePathPathSet(
  117. FILE_PATH_BUFFER *fpBuf,
  118. LPTSTR Path
  119. )
  120. /*++
  121. Routine Description:
  122. Arguments:
  123. Return Value:
  124. --*/
  125. {
  126. if ((fpBuf->Server == NULL) || (fpBuf->Share == NULL))
  127. return;
  128. *fpBuf->Path = TEXT('\0');
  129. if (Path == NULL)
  130. return;
  131. lstrcat(fpBuf->FullPath, Path);
  132. } // FilePathPathSet
  133. /////////////////////////////////////////////////////////////////////////
  134. VOID
  135. TreeDelete(
  136. DIR_BUFFER *Dir
  137. )
  138. /*++
  139. Routine Description:
  140. Walks an in-memory directory tree and free's up all the memory associated
  141. with it and all child nodes.
  142. Arguments:
  143. Return Value:
  144. --*/
  145. {
  146. DIR_BUFFER *DList;
  147. ULONG i;
  148. if (Dir == NULL)
  149. return;
  150. if (Dir->DirList) {
  151. DList = Dir->DirList->DirBuffer;
  152. for (i = 0; i < Dir->DirList->Count; i++)
  153. TreeDelete(&DList[i]);
  154. FreeMemory(Dir->DirList);
  155. }
  156. if (Dir->FileList)
  157. FreeMemory(Dir->FileList);
  158. } // TreeDelete
  159. /////////////////////////////////////////////////////////////////////////
  160. VOID
  161. TreePrune(
  162. DIR_BUFFER *Dir
  163. )
  164. /*++
  165. Routine Description:
  166. Prunes a tree down by removing un-needed nodes. If a node is marked
  167. as CONVERT_ALL or CONVERT_NONE then we don't need any of the child
  168. leaves as we know these will be the same. Only CONVERT_PARTIAL
  169. needs to be saved.
  170. This is used so we only copy/save the minimum needed.
  171. Arguments:
  172. Return Value:
  173. --*/
  174. {
  175. BYTE Convert;
  176. DIR_BUFFER *DList;
  177. ULONG i;
  178. if (Dir == NULL)
  179. return;
  180. // First visit all of the children sub-dirs and prune them. Next:
  181. // if partial convert then we can't delete this node, else we can
  182. // clean up all the children - we leave it to the parent node to
  183. // delete the current node.
  184. Convert = Dir->Convert;
  185. if (Dir->DirList) {
  186. DList = Dir->DirList->DirBuffer;
  187. for (i = 0; i < Dir->DirList->Count; i++)
  188. TreePrune(&DList[i]);
  189. if (Convert == CONVERT_PARTIAL)
  190. return;
  191. if (Dir->Special && (Convert == CONVERT_ALL))
  192. return;
  193. for (i = 0; i < Dir->DirList->Count; i++)
  194. TreeDelete(&DList[i]);
  195. Dir->DirList = NULL;
  196. }
  197. if (Convert == CONVERT_PARTIAL)
  198. return;
  199. if (Dir->FileList)
  200. FreeMemory(Dir->FileList);
  201. Dir->FileList = NULL;
  202. } // TreePrune
  203. /////////////////////////////////////////////////////////////////////////
  204. VOID
  205. _TreeCountR(
  206. DIR_BUFFER *Dir
  207. )
  208. /*++
  209. Routine Description:
  210. Count all the files under a sub-dir. This recuses down all the child
  211. nodes.
  212. Arguments:
  213. Return Value:
  214. --*/
  215. {
  216. BYTE Convert;
  217. DIR_BUFFER *DList;
  218. ULONG i;
  219. if ((Dir == NULL) || (!Dir->Convert))
  220. return;
  221. Convert = Dir->Convert;
  222. if (Dir->DirList) {
  223. DList = Dir->DirList->DirBuffer;
  224. for (i = 0; i < Dir->DirList->Count; i++)
  225. _TreeCountR(&DList[i]);
  226. }
  227. if (Dir->FileList)
  228. for (i = 0; i < Dir->FileList->Count; i++)
  229. if (Dir->FileList->FileBuffer[i].Convert)
  230. TCount++;
  231. } // _TreeCountR
  232. ULONG TreeCount(DIR_BUFFER *Dir) {
  233. TCount = 0;
  234. if (Dir == NULL)
  235. return TCount;
  236. _TreeCountR(Dir);
  237. return TCount;
  238. } // TreeCount
  239. /////////////////////////////////////////////////////////////////////////
  240. VOID
  241. _TreeCopyR(
  242. DIR_BUFFER *Dir
  243. )
  244. /*++
  245. Routine Description:
  246. Duplicates a directory/File tree structure in memory.
  247. Arguments:
  248. Return Value:
  249. --*/
  250. {
  251. DIR_LIST *DList;
  252. DIR_BUFFER *DBuff;
  253. FILE_LIST *FList;
  254. FILE_BUFFER *FBuff;
  255. ULONG Size;
  256. ULONG i;
  257. if (Dir == NULL)
  258. return;
  259. if (Dir->FileList) {
  260. // Create clone of file list
  261. Size = sizeof(FILE_LIST) + (sizeof(FILE_BUFFER) * Dir->FileList->Count);
  262. FList = AllocMemory(Size);
  263. if (FList != NULL)
  264. memcpy(FList, Dir->FileList, Size);
  265. // Copied it, now fixup the internal pointers.
  266. FList->parent = Dir;
  267. FBuff = FList->FileBuffer;
  268. for (i = 0; i < FList->Count; i++)
  269. FBuff[i].parent = FList;
  270. // Now replace pointer with cloned tree
  271. Dir->FileList = FList;
  272. }
  273. if (Dir->DirList) {
  274. // Create clone of Dir List
  275. Size = sizeof(DIR_LIST) + (sizeof(DIR_BUFFER) * Dir->DirList->Count);
  276. DList = AllocMemory(Size);
  277. if (DList != NULL)
  278. memcpy(DList, Dir->DirList, Size);
  279. // Copied it, now fixup the internal pointers.
  280. DList->parent = Dir;
  281. DBuff = DList->DirBuffer;
  282. for (i = 0; i < DList->Count; i++)
  283. DBuff[i].parent = DList;
  284. // Now replace pointer with cloned tree
  285. Dir->DirList = DList;
  286. // Now recurse into children and fix them up
  287. for (i = 0; i < DList->Count; i++)
  288. _TreeCopyR(&DBuff[i]);
  289. }
  290. } // _TreeCopyR
  291. /////////////////////////////////////////////////////////////////////////
  292. DIR_BUFFER *
  293. TreeCopy(
  294. DIR_BUFFER *Dir
  295. )
  296. /*++
  297. Routine Description:
  298. Arguments:
  299. Return Value:
  300. --*/
  301. {
  302. DIR_BUFFER *nDir = NULL;
  303. if (Dir == NULL)
  304. return NULL;
  305. nDir = AllocMemory(sizeof(DIR_BUFFER));
  306. if (nDir != NULL) {
  307. memcpy(nDir, Dir, sizeof(DIR_BUFFER));
  308. _TreeCopyR(nDir);
  309. }
  310. return nDir;
  311. } // TreeCopy
  312. /////////////////////////////////////////////////////////////////////////
  313. int __cdecl
  314. FileBufferCompare(
  315. const VOID *arg1,
  316. const VOID *arg2
  317. )
  318. /*++
  319. Routine Description:
  320. Arguments:
  321. Return Value:
  322. --*/
  323. {
  324. WIN32_FIND_DATA *Farg1, *Farg2;
  325. Farg1 = (WIN32_FIND_DATA *) arg1;
  326. Farg2 = (WIN32_FIND_DATA *) arg2;
  327. // This works as the first item of the structure is the string
  328. return lstrcmpi( Farg1->cFileName, Farg2->cFileName);
  329. } // FileBufferCompare
  330. /////////////////////////////////////////////////////////////////////////
  331. VOID
  332. DirAdjustConvert(
  333. DIR_BUFFER *Dir
  334. )
  335. /*++
  336. Routine Description:
  337. Need to adjust convert flag (none, full, partial) down the tree to the
  338. root.
  339. Arguments:
  340. Return Value:
  341. --*/
  342. {
  343. BOOL Partial = FALSE;
  344. ULONG ChildCount = 0;
  345. ULONG ChildSelected = 0;
  346. DIR_LIST *DirList = NULL;
  347. FILE_LIST *FileList = NULL;
  348. ULONG i;
  349. if (Dir == NULL)
  350. return;
  351. // if no files or dirs don't try to re-adjust current setting.
  352. if ((Dir->DirList == NULL) && (Dir->FileList == NULL))
  353. goto DirAdjRecurse;
  354. // Scan the children directories to see what is to be converted.
  355. DirList = Dir->DirList;
  356. if (DirList != NULL) {
  357. ChildCount += DirList->Count;
  358. for (i = 0; i < DirList->Count; i++)
  359. if (DirList->DirBuffer[i].Convert == CONVERT_PARTIAL)
  360. Partial = TRUE;
  361. else
  362. ChildSelected += DirList->DirBuffer[i].Convert;
  363. }
  364. // if any of the children were partial convert then it is easy, as
  365. // we are partial convert as well.
  366. if (Partial) {
  367. Dir->Convert = CONVERT_PARTIAL;
  368. goto DirAdjRecurse;
  369. }
  370. // Scan the children files to see what is to be converted.
  371. FileList = Dir->FileList;
  372. if (FileList != NULL) {
  373. ChildCount += FileList->Count;
  374. for (i = 0; i < FileList->Count; i++)
  375. ChildSelected += FileList->FileBuffer[i].Convert;
  376. }
  377. if (ChildSelected == ChildCount)
  378. Dir->Convert = CONVERT_ALL;
  379. else
  380. if (ChildSelected == 0)
  381. Dir->Convert = CONVERT_NONE;
  382. else
  383. Dir->Convert = CONVERT_PARTIAL;
  384. DirAdjRecurse:
  385. DirList = Dir->parent;
  386. if (DirList != NULL)
  387. DirAdjustConvert(DirList->parent);
  388. } // DirAdjustConvert
  389. /////////////////////////////////////////////////////////////////////////
  390. VOID
  391. DirAdjustConvertChildren(
  392. DIR_BUFFER *Dir,
  393. BYTE Convert
  394. )
  395. /*++
  396. Routine Description:
  397. Arguments:
  398. Return Value:
  399. --*/
  400. {
  401. DIR_LIST *DirList = NULL;
  402. FILE_LIST *FileList = NULL;
  403. ULONG i;
  404. if (Dir == NULL)
  405. return;
  406. Dir->Convert = Convert;
  407. // Scan the children files
  408. FileList = Dir->FileList;
  409. if (FileList != NULL)
  410. for (i = 0; i < FileList->Count; i++)
  411. FileList->FileBuffer[i].Convert = Convert;
  412. // Scan the children directories
  413. DirList = Dir->DirList;
  414. if (DirList != NULL)
  415. for (i = 0; i < DirList->Count; i++)
  416. DirAdjustConvertChildren(&DirList->DirBuffer[i], Convert);
  417. } // DirAdjustConvertChildren
  418. /////////////////////////////////////////////////////////////////////////
  419. BOOL
  420. SubdirRestrict(
  421. LPTSTR Path,
  422. LPTSTR Subdir
  423. )
  424. /*++
  425. Routine Description:
  426. Arguments:
  427. Return Value:
  428. --*/
  429. {
  430. ULONG i = 0;
  431. LPTSTR RestrictPath[5];
  432. CONVERT_OPTIONS * ConvertOptions;
  433. // if the user has specified the 'transfer netware specific info'
  434. // option the we should transfer the mail directory by default...
  435. ConvertOptions = (CONVERT_OPTIONS *)CurrentConvertList->ConvertOptions;
  436. if (ConvertOptions->NetWareInfo)
  437. RestrictPath[i++] = Lids(IDS_S_3);
  438. RestrictPath[i++] = Lids(IDS_S_2);
  439. RestrictPath[i++] = Lids(IDS_S_4);
  440. RestrictPath[i++] = Lids(IDS_S_5);
  441. RestrictPath[i++] = NULL;
  442. i = 0;
  443. while(RestrictPath[i] != NULL) {
  444. if (!lstrcmpi(RestrictPath[i], Subdir))
  445. return TRUE;
  446. i++;
  447. }
  448. return FALSE;
  449. } // SubdirRestrict
  450. /////////////////////////////////////////////////////////////////////////
  451. VOID
  452. FillDirInit()
  453. /*++
  454. Routine Description:
  455. Arguments:
  456. Return Value:
  457. --*/
  458. {
  459. if (ffd == NULL) {
  460. ffd = AllocMemory(sizeof(WIN32_FIND_DATA) * DEF_NUM_RECS);
  461. BufferSize = DEF_NUM_RECS;
  462. }
  463. } // FillDirInit
  464. /////////////////////////////////////////////////////////////////////////
  465. VOID
  466. FillDir(
  467. UINT Level,
  468. LPTSTR Path,
  469. DIR_BUFFER *Dir,
  470. BOOL DoDirs
  471. )
  472. /*++
  473. Routine Description:
  474. Given a DIR_BUFFER, enumerate the files and sub-dirs under it and
  475. attach them (one level-deep only).
  476. Arguments:
  477. Return Value:
  478. --*/
  479. {
  480. static TCHAR NewPath[MAX_UNC_PATH + 1];
  481. DIR_LIST *DirList = NULL;
  482. DIR_LIST *OldDirList = NULL;
  483. DIR_BUFFER *DBuff;
  484. FILE_LIST *FileList = NULL;
  485. FILE_LIST *OldFileList = NULL;
  486. FILE_BUFFER *FBuff;
  487. HANDLE fHandle = NULL;
  488. ULONG DirCount = 0;
  489. ULONG FileCount = 0;
  490. ULONG Count = 0;
  491. BOOL ret = TRUE;
  492. ULONG i;
  493. BYTE Convert;
  494. BOOL ConvFlag;
  495. FixPathSlash(NewPath, Path);
  496. lstrcat(NewPath, TEXT("*.*"));
  497. #ifdef DEBUG
  498. dprintf(TEXT("Working on dir: %u %s\r\n"), Level, Path);
  499. #endif
  500. Panel_Line(7, TEXT("%s"), Path);
  501. fHandle = FindFirstFile(NewPath, &ffd[Count]);
  502. ret = (fHandle != INVALID_HANDLE_VALUE);
  503. // loop filling in the temp buffer - figure out how many dirs and files
  504. // we have to remember - and build up a temporary buffer of them
  505. while (ret) {
  506. if (ffd[Count].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  507. ConvFlag = TRUE;
  508. if (!((lstrcmp(ffd[Count].cFileName, TEXT("."))) && (lstrcmp(ffd[Count].cFileName, TEXT("..")))))
  509. ConvFlag = FALSE;
  510. if (!HiddenFiles && (ffd[Count].dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
  511. ConvFlag = FALSE;
  512. if (!SystemFiles && (ffd[Count].dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
  513. ConvFlag = FALSE;
  514. // Use the cAlternateFileName as a flag whether to convert
  515. if (ConvFlag) {
  516. ffd[Count].cAlternateFileName[0] = 1;
  517. DirCount++;
  518. } else
  519. ffd[Count].cAlternateFileName[0] = 0;
  520. } else {
  521. ConvFlag = TRUE;
  522. if (!HiddenFiles && (ffd[Count].dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
  523. ConvFlag = FALSE;
  524. if (!SystemFiles && (ffd[Count].dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
  525. ConvFlag = FALSE;
  526. if (ConvFlag) {
  527. ffd[Count].cAlternateFileName[0] = 1;
  528. FileCount++;
  529. } else
  530. ffd[Count].cAlternateFileName[0] = 0;
  531. }
  532. Count++;
  533. // check if we are going to run out of space in our buffer - if so
  534. // allocate more space
  535. if (Count >= BufferSize) {
  536. BufferSize += DEF_REC_DELTA;
  537. ffd = ReallocMemory(ffd, sizeof(WIN32_FIND_DATA) * BufferSize);
  538. }
  539. if (ffd == NULL) {
  540. FindClose(fHandle);
  541. return;
  542. } else
  543. ret = FindNextFile(fHandle, &ffd[Count]);
  544. }
  545. FindClose(fHandle);
  546. #ifdef DEBUG
  547. dprintf(TEXT(" Num Dirs / Files: %li %li\r\n"), DirCount, FileCount);
  548. #endif
  549. // Temp buffer is all filled in at this point. Sort it first
  550. if (Count != 0)
  551. qsort((void *) ffd, (size_t) Count, sizeof(WIN32_FIND_DATA), FileBufferCompare);
  552. // Now create the actual list structures
  553. if (DoDirs && DirCount)
  554. DirList = AllocMemory(sizeof(DIR_LIST) + (sizeof(DIR_BUFFER) * DirCount));
  555. if (FileCount)
  556. FileList = AllocMemory(sizeof(FILE_LIST) + (sizeof(FILE_BUFFER) * FileCount));
  557. // if there is no dirlist and there is an old one, clean up the old-one.
  558. if (DoDirs && (DirList == NULL) && (Dir->DirList != NULL)) {
  559. // save off file list so it isn't nuked
  560. OldFileList = (FILE_LIST *) Dir->FileList;
  561. Dir->FileList = NULL;
  562. TreeDelete(Dir);
  563. Dir->DirList = NULL;
  564. // Now restore file list
  565. Dir->FileList = OldFileList;
  566. }
  567. // same for file list.
  568. if ((FileList == NULL) && (Dir->FileList != NULL)) {
  569. FreeMemory(Dir->FileList);
  570. Dir->FileList = NULL;
  571. }
  572. // If nothing to copy, or couldn't alloc memory then no reason to continue
  573. // further...
  574. if ((DirList == NULL) && (FileList == NULL))
  575. return;
  576. if (Dir->Convert == CONVERT_PARTIAL)
  577. Convert = CONVERT_ALL;
  578. else
  579. Convert = Dir->Convert;
  580. if (DoDirs && (DirList != NULL)) {
  581. DirList->Count = DirCount;
  582. DirList->Level = Level;
  583. DirList->parent = Dir;
  584. DirList->DirBuffer[DirCount - 1].Last = TRUE;
  585. }
  586. if (FileList != NULL) {
  587. FileList->Count = FileCount;
  588. FileList->parent = Dir;
  589. }
  590. // transfer the temp buffers to our list structures
  591. DirCount = FileCount = 0;
  592. for (i = 0; i < Count; i++) {
  593. if (ffd[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  594. // Directories
  595. if (DoDirs) {
  596. // Check our Flag
  597. if (ffd[i].cAlternateFileName[0] == 1) {
  598. DBuff = &DirList->DirBuffer[DirCount];
  599. DBuff->Attributes = ffd[i].dwFileAttributes;
  600. lstrcpy(DBuff->Name, ffd[i].cFileName);
  601. DBuff->parent = DirList;
  602. // Check against the subdirs we don't want to convert by default
  603. // if the user has already toggled that these should be converted,
  604. // then the copy of the old info below will fix it back up.
  605. if (SysDir && (Level == 1) && SubdirRestrict(Path, DBuff->Name)) {
  606. DBuff->Convert = CONVERT_NONE;
  607. DBuff->Special = TRUE;
  608. } else
  609. DBuff->Convert = Convert;
  610. DirCount++;
  611. }
  612. }
  613. } else {
  614. // Files
  615. Panel_Line(8, TEXT("%s"), ffd[i].cFileName);
  616. // Check our Flag
  617. if (ffd[i].cAlternateFileName[0] == 1) {
  618. FBuff = &FileList->FileBuffer[FileCount];
  619. FBuff->Attributes = ffd[i].dwFileAttributes;
  620. lstrcpy(FBuff->Name, ffd[i].cFileName);
  621. FBuff->parent = FileList;
  622. FBuff->Convert = Convert;
  623. FBuff->Size = ffd[i].nFileSizeLow;
  624. TotalFileSize += ffd[i].nFileSizeLow;
  625. Panel_Line(9, TEXT("%s"), lToStr(TotalFileSize));
  626. FileCount++;
  627. }
  628. }
  629. }
  630. // Now have the new lists filled in. If there was an old list then we must
  631. // now merge ... can we say pain in the #$$
  632. if (DoDirs) {
  633. OldDirList = (DIR_LIST *) Dir->DirList;
  634. Dir->DirList = DirList;
  635. }
  636. OldFileList = (FILE_LIST *) Dir->FileList;
  637. Dir->FileList = FileList;
  638. // Check the directories
  639. if (DoDirs && (OldDirList != NULL) && (DirList != NULL)) {
  640. int cmp;
  641. DirCount = 0;
  642. i = 0;
  643. while (i < OldDirList->Count) {
  644. do {
  645. cmp = lstrcmpi(OldDirList->DirBuffer[i].Name, DirList->DirBuffer[DirCount].Name);
  646. // a match so copy old data into new...
  647. if (!cmp) {
  648. DBuff = &DirList->DirBuffer[DirCount];
  649. DBuff->Convert = OldDirList->DirBuffer[i].Convert;
  650. DBuff->DirList = OldDirList->DirBuffer[i].DirList;
  651. DBuff->FileList = OldDirList->DirBuffer[i].FileList;
  652. // Now point these back to the new structures
  653. if (DBuff->DirList)
  654. DBuff->DirList->parent = DBuff;
  655. if (DBuff->FileList)
  656. DBuff->FileList->parent = DBuff;
  657. }
  658. // keep incrementing new dir list until we go past old server
  659. // list, then must skip out and increment old server list
  660. DirCount++;
  661. } while ((DirCount < DirList->Count) && (cmp > 0));
  662. if (DirCount >= DirList->Count)
  663. break;
  664. i++;
  665. }
  666. }
  667. // Same stuff for the files
  668. if ((OldFileList != NULL) && (FileList != NULL)) {
  669. int cmp;
  670. FileCount = 0;
  671. i = 0;
  672. while (i < OldFileList->Count) {
  673. do {
  674. cmp = lstrcmpi(OldFileList->FileBuffer[i].Name, FileList->FileBuffer[FileCount].Name);
  675. // a match so copy old data into new...
  676. if (!cmp)
  677. FileList->FileBuffer[FileCount].Convert = OldFileList->FileBuffer[i].Convert;
  678. FileCount++;
  679. } while ((FileCount < FileList->Count) && (cmp > 0));
  680. if (FileCount >= FileList->Count)
  681. break;
  682. i++;
  683. }
  684. }
  685. // Clean up any old lists
  686. if (OldDirList != NULL)
  687. FreeMemory(OldDirList);
  688. if (OldFileList != NULL)
  689. FreeMemory(OldFileList);
  690. DirAdjustConvert(Dir);
  691. } // FillDir
  692. /////////////////////////////////////////////////////////////////////////
  693. VOID
  694. _TreeFillRecurse(
  695. UINT Level,
  696. LPTSTR Path,
  697. DIR_BUFFER *Dir
  698. )
  699. /*++
  700. Routine Description:
  701. Arguments:
  702. Return Value:
  703. --*/
  704. {
  705. TCHAR NewPath[MAX_UNC_PATH + 1];
  706. DIR_LIST *DirList = NULL;
  707. ULONG i;
  708. FillDir(Level, Path, Dir, TRUE);
  709. DirList = Dir->DirList;
  710. if (DirList != NULL)
  711. for (i = 0; i < DirList->Count; i++) {
  712. if (Panel_Cancel())
  713. return;
  714. if (DirList->DirBuffer[i].Convert) {
  715. wsprintf(NewPath, TEXT("%s\\%s"), Path, DirList->DirBuffer[i].Name);
  716. _TreeFillRecurse(Level + 1, NewPath, &DirList->DirBuffer[i]);
  717. }
  718. }
  719. } // _TreeFillRecurse
  720. /////////////////////////////////////////////////////////////////////////
  721. VOID
  722. TreeFillRecurse(
  723. UINT Level,
  724. LPTSTR Path,
  725. DIR_BUFFER *Dir
  726. )
  727. {
  728. TotalFileSize = 0;
  729. FillDirInit();
  730. _TreeFillRecurse(Level, Path, Dir);
  731. } // TreeFillRecurse
  732. /////////////////////////////////////////////////////////////////////////
  733. ULONG
  734. TotalFileSizeGet()
  735. /*++
  736. Routine Description:
  737. Arguments:
  738. Return Value:
  739. --*/
  740. {
  741. return TotalFileSize;
  742. } // TotalFileSizeGet
  743. /////////////////////////////////////////////////////////////////////////
  744. VOID
  745. TreeRecurseCurrentShareSet(
  746. SHARE_BUFFER *CShare
  747. )
  748. /*++
  749. Routine Description:
  750. Arguments:
  751. Return Value:
  752. --*/
  753. {
  754. CurrentShare = CShare;
  755. SysDir = FALSE;
  756. if (!CShare)
  757. return;
  758. if (!lstrcmpi(CShare->Name, Lids(IDS_S_6)))
  759. SysDir = TRUE;
  760. return;
  761. } // TreeRecurseCurrentShareSet
  762. /////////////////////////////////////////////////////////////////////////
  763. VOID
  764. TreeRootInit(
  765. SHARE_BUFFER *CShare,
  766. LPTSTR NewPath
  767. )
  768. /*++
  769. Routine Description:
  770. Arguments:
  771. Return Value:
  772. --*/
  773. {
  774. TreeRecurseCurrentShareSet(CShare);
  775. if (CShare->Root)
  776. return;
  777. CShare->Root = AllocMemory(sizeof(DIR_BUFFER));
  778. lstrcpy(CShare->Root->Name, NewPath);
  779. CShare->Root->Last = TRUE;
  780. CShare->Root->Attributes = FILE_ATTRIBUTE_DIRECTORY;
  781. CShare->Root->DirList = NULL;
  782. CShare->Root->FileList = NULL;
  783. CShare->Root->parent = NULL;
  784. // have to set this to preserve user selection of special excluded dirs...
  785. if (SysDir)
  786. CShare->Root->Special = TRUE;
  787. CShare->Root->Convert = CONVERT_ALL;
  788. FillDir(1, CShare->Root->Name, CShare->Root, TRUE);
  789. DirAdjustConvert(CShare->Root);
  790. } // TreeRootInit
  791. /////////////////////////////////////////////////////////////////////////
  792. VOID
  793. ControlsResize(
  794. HWND hDlg,
  795. int Height,
  796. int Width
  797. )
  798. /*++
  799. Routine Description:
  800. Arguments:
  801. Return Value:
  802. --*/
  803. {
  804. HWND hCtrl;
  805. int nHeight, nWidth, BtnWidth, BtnHeight;
  806. RECT rc;
  807. hCtrl = GetDlgItem(hDlg, IDOK);
  808. GetWindowRect(hCtrl, &rc);
  809. BtnWidth = (rc.right - rc.left);
  810. BtnHeight = (rc.bottom - rc.top);
  811. // Get size of first listbox and figure height as it is same for both
  812. hCtrl = GetDlgItem(hDlg, IDC_LIST1);
  813. GetWindowRect(hCtrl, &rc);
  814. List1Width = (rc.right - rc.left);
  815. nHeight = Height - Y_BORDER - BtnHeight - (2 * BUTTON_Y_BORDER); // subtract out borders
  816. Splitter_Bottom = nHeight + Y_BORDER;
  817. Splitter_Left = List1Width + X_BORDER;
  818. // First Listbox never changes width on Window resize
  819. MoveWindow(hCtrl, X_BORDER, Y_BORDER, List1Width, nHeight, TRUE);
  820. GetWindowRect(hCtrl, &rc);
  821. nHeight = (rc.bottom - rc.top);
  822. // Second Listbox has width based on first and new size of Window.
  823. if (Width > (2 * X_BORDER) + SPLITTER_WIDTH)
  824. nWidth = Width - ( 2 * X_BORDER) - SPLITTER_WIDTH;
  825. else
  826. nWidth = 1;
  827. // Now must take off from first listbox
  828. if (nWidth > List1Width)
  829. nWidth -= List1Width;
  830. else
  831. nWidth = 1;
  832. hCtrl = GetDlgItem(hDlg, IDC_LIST2);
  833. MoveWindow(hCtrl, X_BORDER + List1Width + SPLITTER_WIDTH, Y_BORDER, nWidth, nHeight, TRUE);
  834. // Figure out where to put the buttons
  835. nWidth = (Width / 2) - (((3 * BtnWidth) + (2 * BUTTON_X_BORDER)) / 2);
  836. nHeight = Height - BtnHeight - BUTTON_Y_BORDER;
  837. hCtrl = GetDlgItem(hDlg, IDOK);
  838. MoveWindow(hCtrl, nWidth, nHeight, BtnWidth, BtnHeight, TRUE);
  839. nWidth += BtnWidth + BUTTON_X_BORDER;
  840. hCtrl = GetDlgItem(hDlg, IDCANCEL);
  841. MoveWindow(hCtrl, nWidth, nHeight, BtnWidth, BtnHeight, TRUE);
  842. nWidth += BtnWidth + BUTTON_X_BORDER;
  843. hCtrl = GetDlgItem(hDlg, IDHELP);
  844. MoveWindow(hCtrl, nWidth, nHeight, BtnWidth, BtnHeight, TRUE);
  845. } // ControlsResize
  846. /////////////////////////////////////////////////////////////////////////
  847. VOID
  848. FileSelect_OnDrawItem(
  849. HWND hwnd,
  850. DRAWITEMSTRUCT FAR* lpDrawItem
  851. )
  852. /*++
  853. Routine Description:
  854. Arguments:
  855. Return Value:
  856. --*/
  857. {
  858. TCHAR szText[MAX_PATH + 1];
  859. DWORD_PTR dwData;
  860. int nLevel = 0;
  861. int nTempLevel;
  862. int nRow = 0;
  863. int nColumn = 0;
  864. int chkColumn = 0;
  865. DWORD dwConnectLevel = 0;
  866. DWORD dwMask;
  867. DIR_BUFFER *Dir, *Dir2;
  868. FILE_BUFFER *File;
  869. DIR_LIST *DirList, *DirList2;
  870. BOOL FileBox = FALSE;
  871. dwData = lpDrawItem->itemData;
  872. if (dwData == 0)
  873. return;
  874. if ((lpDrawItem->CtlID != IDC_LIST1) && (lpDrawItem->CtlID != IDC_LIST2))
  875. return;
  876. if (lpDrawItem->CtlID == IDC_LIST2)
  877. FileBox = TRUE;
  878. // Select the correct icon, open folder, closed folder, or document.
  879. if (FileBox) {
  880. File = (FILE_BUFFER *) dwData;
  881. lstrcpy(szText, File->Name);
  882. nRow = 1;
  883. chkColumn = File->Convert;
  884. } else {
  885. Dir2 = Dir = (DIR_BUFFER *) dwData;
  886. lstrcpy(szText, Dir->Name);
  887. chkColumn = Dir->Convert;
  888. DirList2 = DirList = (DIR_LIST *) Dir->parent;
  889. if (DirList != NULL)
  890. nLevel = DirList->Level;
  891. // Is it open ?
  892. if ( HierFile_IsOpened(&HierDrawStruct, dwData) )
  893. nColumn = 1;
  894. else
  895. nColumn = 0;
  896. // Connect level figures out what connecting lines should be drawn
  897. // - stored as a bitmask.
  898. if (nLevel == 0)
  899. dwConnectLevel = 0;
  900. else {
  901. nTempLevel = nLevel - 1;
  902. // First bit to set
  903. dwMask = (DWORD) pow(2, nLevel - 1);
  904. // Now go through and figure out what else to set...
  905. while (nTempLevel >= 0) {
  906. // Check if last child at this level...
  907. if (!Dir2->Last)
  908. dwConnectLevel |= dwMask;
  909. // figure out next parent...
  910. Dir2 = DirList2->parent;
  911. DirList2 = Dir2->parent;
  912. // move mask bit over, and up a level.
  913. dwMask /= 2;
  914. // move up one level.
  915. nTempLevel--;
  916. }
  917. }
  918. }
  919. // All set to call drawing function.
  920. HierFile_OnDrawItem(hwnd, lpDrawItem, nLevel, dwConnectLevel, szText,
  921. nRow, nColumn, chkColumn, &HierDrawStruct);
  922. return;
  923. } // FileSelect_OnDrawItem
  924. /////////////////////////////////////////////////////////////////////////
  925. VOID
  926. RecursePath(
  927. LPTSTR Path,
  928. DIR_BUFFER *Dir
  929. )
  930. /*++
  931. Routine Description:
  932. Arguments:
  933. Return Value:
  934. --*/
  935. {
  936. DIR_LIST *DirList;
  937. ULONG i;
  938. DirList = (DIR_LIST *) Dir->parent;
  939. if (DirList != NULL)
  940. RecursePath(Path, (DIR_BUFFER *) DirList->parent);
  941. i = lstrlen(Path);
  942. if (i)
  943. if (Path[i-1] != TEXT('\\'))
  944. lstrcat(Path, TEXT("\\"));
  945. lstrcat(Path, Dir->Name);
  946. } // RecursePath
  947. /////////////////////////////////////////////////////////////////////////
  948. VOID
  949. CloseList(
  950. HWND hWndList,
  951. DIR_BUFFER *Dir,
  952. WORD wItemNum
  953. )
  954. /*++
  955. Routine Description:
  956. Arguments:
  957. Return Value:
  958. --*/
  959. {
  960. DWORD_PTR dwIncr;
  961. DWORD Count;
  962. DIR_LIST *DirList;
  963. HierFile_CloseItem(&HierDrawStruct, (DWORD_PTR) Dir);
  964. DirList = (DIR_LIST *) Dir->DirList;
  965. if (DirList != NULL) {
  966. Count = DirList->Count;
  967. // Remove the child items. Close any children that are open on the way.
  968. // wItem can stay constant - we are moveing stuff up in the listbox as we are deleting.
  969. wItemNum++;
  970. dwIncr = SendMessage(hWndList, LB_GETITEMDATA, wItemNum, 0L);
  971. while (Count) {
  972. // Is this child open ?
  973. if ( HierFile_IsOpened(&HierDrawStruct, dwIncr) ) {
  974. CloseList(hWndList, (DIR_BUFFER *) dwIncr, wItemNum);
  975. }
  976. SendMessage(hWndList, LB_DELETESTRING, wItemNum, 0L);
  977. dwIncr = SendMessage(hWndList, LB_GETITEMDATA, wItemNum, 0L);
  978. Count--;
  979. }
  980. }
  981. } // CloseList
  982. /////////////////////////////////////////////////////////////////////////
  983. VOID
  984. FileSelect_ActionItem(
  985. HWND hWndList,
  986. DWORD_PTR dwData,
  987. WORD wItemNum
  988. )
  989. /*++
  990. Routine Description:
  991. Arguments:
  992. Return Value:
  993. --*/
  994. {
  995. static TCHAR NewPath[MAX_PATH + 1];
  996. DWORD Count = 0;
  997. DIR_BUFFER *Dir;
  998. DIR_LIST *DirList;
  999. FILE_LIST *FileList;
  1000. ULONG i;
  1001. if (!dwData)
  1002. return;
  1003. // Is it open ?
  1004. if ( HierFile_IsOpened(&HierDrawStruct, dwData) ) {
  1005. // It's open ... Close it
  1006. Dir = (DIR_BUFFER *) dwData;
  1007. DirList = (DIR_LIST *) Dir->DirList;
  1008. CloseList(hWndList, Dir, wItemNum);
  1009. } else {
  1010. // It's closed ... Open it
  1011. HierFile_OpenItem(&HierDrawStruct, dwData);
  1012. SendMessage(hWndList, WM_SETREDRAW, FALSE, 0L); // Disable redrawing.
  1013. CursorHourGlass();
  1014. Dir = (DIR_BUFFER *) dwData;
  1015. #ifdef DEBUG
  1016. dprintf(TEXT("Opening dir: %s\r\n"), Dir->Name);
  1017. #endif
  1018. DirList = (DIR_LIST *) Dir->parent;
  1019. if (DirList == NULL)
  1020. FillDir(1, Dir->Name, Dir, TRUE);
  1021. else {
  1022. // recurse backwards to create full path
  1023. lstrcpy(NewPath, TEXT(""));
  1024. RecursePath(NewPath, Dir);
  1025. FillDir(DirList->Level + 1, NewPath, Dir, TRUE);
  1026. }
  1027. DirList = NULL;
  1028. // Check if we have visited this node, if not allocate and fill it in.
  1029. if (Dir->DirList != NULL) {
  1030. DirList = (DIR_LIST *) Dir->DirList;
  1031. Count = DirList->Count;
  1032. for (i = 0; i < DirList->Count; i++) {
  1033. SendMessage(hWndList, LB_INSERTSTRING, (WPARAM) wItemNum + i + 1, (LPARAM) &DirList->DirBuffer[i]);
  1034. }
  1035. }
  1036. #ifdef DEBUG
  1037. if (Dir->FileList == NULL)
  1038. dprintf(TEXT("FileList NULL\r\n"));
  1039. #endif
  1040. if (Dir->FileList != NULL) {
  1041. FileList = (FILE_LIST *) Dir->FileList;
  1042. #ifdef DEBUG
  1043. dprintf(TEXT("FileList Count: %li\r\n"), FileList->Count);
  1044. #endif
  1045. SendMessage(hwndList2, LB_RESETCONTENT, (WPARAM) 0, (LPARAM) 0L);
  1046. for (i = 0; i < FileList->Count; i++) {
  1047. SendMessage(hwndList2, LB_ADDSTRING, (WPARAM) 0, (LPARAM) &FileList->FileBuffer[i]);
  1048. }
  1049. }
  1050. // Make sure as many child items as possible are showing
  1051. HierFile_ShowKids(&HierDrawStruct, hWndList, (WORD) wItemNum, (WORD) Count );
  1052. CursorNormal();
  1053. }
  1054. SendMessage(hWndList, WM_SETREDRAW, TRUE, 0L); // Enable redrawing.
  1055. InvalidateRect(hWndList, NULL, TRUE); // Force redraw
  1056. } // FileSelect_ActionItem
  1057. /////////////////////////////////////////////////////////////////////////
  1058. VOID
  1059. TreeOpenRecurse(
  1060. DIR_BUFFER *Dir,
  1061. WORD *wItemNum
  1062. )
  1063. /*++
  1064. Routine Description:
  1065. Arguments:
  1066. Return Value:
  1067. --*/
  1068. {
  1069. DIR_LIST *DirList = NULL;
  1070. ULONG i;
  1071. // if it's closed, open it
  1072. if ( !HierFile_IsOpened(&HierDrawStruct, (DWORD_PTR) Dir) )
  1073. FileSelect_ActionItem(hwndList1, (DWORD_PTR) Dir, *wItemNum);
  1074. DirList = Dir->DirList;
  1075. if (DirList != NULL) {
  1076. for (i = 0; i < DirList->Count; i++) {
  1077. (*wItemNum)++;
  1078. // Now recurse down the children
  1079. TreeOpenRecurse(&DirList->DirBuffer[i], wItemNum);
  1080. }
  1081. }
  1082. } // TreeOpenRecurse
  1083. /////////////////////////////////////////////////////////////////////////
  1084. VOID
  1085. FileSelect_UpdateFiles(
  1086. HWND hDlg
  1087. )
  1088. /*++
  1089. Routine Description:
  1090. Arguments:
  1091. Return Value:
  1092. --*/
  1093. {
  1094. static TCHAR NewPath[MAX_PATH + 1];
  1095. WORD wItemNum;
  1096. DWORD dwData;
  1097. HWND hCtrl;
  1098. ULONG i;
  1099. FILE_LIST *FileList;
  1100. DIR_BUFFER *Dir;
  1101. DIR_LIST *DirList;
  1102. hCtrl = GetDlgItem(hDlg, IDC_LIST1);
  1103. wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
  1104. if (wItemNum == (WORD) LB_ERR)
  1105. wItemNum = LastFocus;
  1106. // Check first listbox and resynch the directory information so that we
  1107. // pick up the current file list.
  1108. LastFocus = wItemNum;
  1109. dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
  1110. if ((dwData == (DWORD) LB_ERR) || (dwData == 0))
  1111. return;
  1112. Dir = (DIR_BUFFER *) dwData;
  1113. #ifdef DEBUG
  1114. dprintf(TEXT("Opening dir: %lX %s\r\n"), Dir->parent, Dir->Name);
  1115. #endif
  1116. DirList = (DIR_LIST *) Dir->parent;
  1117. if (DirList == NULL)
  1118. FillDir(1, Dir->Name, Dir, FALSE);
  1119. else {
  1120. // recurse backwards to create full path
  1121. lstrcpy(NewPath, TEXT(""));
  1122. RecursePath(NewPath, Dir);
  1123. FillDir(DirList->Level + 1, NewPath, Dir, FALSE);
  1124. }
  1125. // Since Dir pointer was changed need to update listbox pointer
  1126. SendMessage(hCtrl, LB_SETITEMDATA, wItemNum, (LPARAM) Dir);
  1127. // We have not re-synched the directory so we have the correct file info
  1128. // now reset the file listbox and fill it with the new file-list.
  1129. SendMessage(hwndList2, LB_RESETCONTENT, (WPARAM) 0, (LPARAM) 0L);
  1130. if (Dir->FileList != NULL) {
  1131. FileList = (FILE_LIST *) Dir->FileList;
  1132. #ifdef DEBUG
  1133. dprintf(TEXT("FileList Count: %li\r\n"), FileList->Count);
  1134. #endif
  1135. for (i = 0; i < FileList->Count; i++)
  1136. SendMessage(hwndList2, LB_ADDSTRING, (WPARAM) 0, (LPARAM) &FileList->FileBuffer[i]);
  1137. }
  1138. } // FileSelect_UpdateFiles
  1139. /////////////////////////////////////////////////////////////////////////
  1140. VOID
  1141. FileSelect_OnCommand(
  1142. HWND hDlg,
  1143. WPARAM wParam,
  1144. LPARAM lParam
  1145. )
  1146. /*++
  1147. Routine Description:
  1148. Arguments:
  1149. Return Value:
  1150. --*/
  1151. {
  1152. static TCHAR NewPath[MAX_PATH + 1];
  1153. int wmId, wmEvent;
  1154. WORD wItemNum;
  1155. DWORD dwData;
  1156. HWND hCtrl;
  1157. DIR_LIST *DirList;
  1158. FILE_LIST *FileList;
  1159. DIR_BUFFER *Dir;
  1160. int nLevel = 0;
  1161. wmId = LOWORD(wParam);
  1162. wmEvent = HIWORD(wParam);
  1163. switch (wmId) {
  1164. case IDOK:
  1165. // If we are on either of the listboxes, then use the Enter key to
  1166. // activate the selected item
  1167. if (ListFocus == hwndList1) {
  1168. hCtrl = GetDlgItem(hDlg, IDC_LIST1);
  1169. wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
  1170. dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
  1171. if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
  1172. break;
  1173. FileSelect_ActionItem(hCtrl, dwData, wItemNum);
  1174. } else {
  1175. CurrentShare->HiddenFiles = HiddenFiles;
  1176. CurrentShare->SystemFiles = SystemFiles;
  1177. // Delete our copy of the tree and prune the tree down to minimum
  1178. // storage space
  1179. TreeDelete(oDir);
  1180. TreePrune(CurrentShare->Root);
  1181. EndDialog(hDlg, 0);
  1182. }
  1183. break;
  1184. case IDCANCEL:
  1185. // Disable listboxes since we are deleting their item data
  1186. SendDlgItemMessage(hDlg, IDC_LIST1, WM_SETREDRAW, FALSE, 0L);
  1187. SendDlgItemMessage(hDlg, IDC_LIST2, WM_SETREDRAW, FALSE, 0L);
  1188. // Get back our old tree
  1189. if (CurrentShare->Root != NULL)
  1190. TreeDelete(CurrentShare->Root);
  1191. CurrentShare->Root = oDir;
  1192. EndDialog(hDlg, 0);
  1193. break;
  1194. case IDHELP:
  1195. WinHelp(hDlg, HELP_FILE, HELP_CONTEXT, (DWORD) IDC_HELP_FTRANS);
  1196. break;
  1197. case IDM_EXP_ONE:
  1198. // expand the current node
  1199. hCtrl = GetDlgItem(hDlg, IDC_LIST1);
  1200. wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
  1201. dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
  1202. if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
  1203. break;
  1204. if ( !HierFile_IsOpened(&HierDrawStruct, dwData) )
  1205. FileSelect_ActionItem(hCtrl, dwData, wItemNum);
  1206. break;
  1207. case IDM_EXP_ALL:
  1208. // Open all children from the root
  1209. wItemNum = 0;
  1210. hCtrl = GetDlgItem(hDlg, IDC_LIST1);
  1211. goto ExpandTree;
  1212. case IDM_EXP_BRANCH:
  1213. // Traverse down the branch, opening up all children
  1214. hCtrl = GetDlgItem(hDlg, IDC_LIST1);
  1215. wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
  1216. ExpandTree:
  1217. dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
  1218. if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
  1219. break;
  1220. Dir = (DIR_BUFFER *) dwData;
  1221. CursorHourGlass();
  1222. TreeOpenRecurse(Dir, &wItemNum);
  1223. CursorNormal();
  1224. // Force redraw
  1225. InvalidateRect(hwndList1, NULL, TRUE);
  1226. break;
  1227. case IDM_COLLAPSE:
  1228. // Close the current branch
  1229. hCtrl = GetDlgItem(hDlg, IDC_LIST1);
  1230. wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
  1231. dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
  1232. if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
  1233. break;
  1234. if ( HierFile_IsOpened(&HierDrawStruct, dwData) )
  1235. FileSelect_ActionItem(hCtrl, dwData, wItemNum);
  1236. break;
  1237. // Not used currently
  1238. case IDM_VIEW_BOTH:
  1239. case IDM_VIEW_TREE:
  1240. case IDM_VIEW_DIR:
  1241. break;
  1242. case IDM_HIDDEN:
  1243. HiddenFiles = !HiddenFiles;
  1244. CheckMenuItem((HMENU) wParam, IDM_HIDDEN, HiddenFiles ? MF_CHECKED : MF_UNCHECKED);
  1245. PostMessage(hDlg, WM_COMMAND, ID_REDRAWLIST, 0L);
  1246. break;
  1247. case IDM_SYSTEM:
  1248. SystemFiles = !SystemFiles;
  1249. CheckMenuItem((HMENU) wParam, IDM_SYSTEM, SystemFiles ? MF_CHECKED : MF_UNCHECKED);
  1250. PostMessage(hDlg, WM_COMMAND, ID_REDRAWLIST, 0L);
  1251. break;
  1252. case ID_REDRAWLIST:
  1253. FileSelect_UpdateFiles(hDlg);
  1254. break;
  1255. case IDC_LIST1:
  1256. switch (wmEvent) {
  1257. case LBN_SETFOCUS:
  1258. ListFocus = hwndList1;
  1259. break;
  1260. case LBN_KILLFOCUS:
  1261. ListFocus = NULL;
  1262. break;
  1263. case LBN_DBLCLK:
  1264. // Disregard the DBLCLK message if it is inside a checkbox.
  1265. hCtrl = GetDlgItem(hDlg, IDC_LIST1);
  1266. // First figure out where checkbox is located in listbox
  1267. wItemNum = (WORD) SendMessage(hCtrl, LB_GETCURSEL, 0, 0L);
  1268. dwData = (DWORD) SendMessage(hCtrl, LB_GETITEMDATA, wItemNum, 0L);
  1269. if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
  1270. break;
  1271. Dir = (DIR_BUFFER *) dwData;
  1272. DirList = (DIR_LIST *) Dir->parent;
  1273. if (DirList != NULL)
  1274. nLevel = DirList->Level;
  1275. if (!HierFile_InCheck(nLevel, LOWORD(mouseHit), &HierDrawStruct)) {
  1276. CursorHourGlass();
  1277. FileSelect_ActionItem(hCtrl, dwData, wItemNum);
  1278. CursorNormal();
  1279. }
  1280. break;
  1281. case LBN_SELCHANGE:
  1282. FileSelect_UpdateFiles(hDlg);
  1283. break;
  1284. }
  1285. break;
  1286. case ID_UPDATELIST:
  1287. hCtrl = GetDlgItem(hDlg, IDC_LIST1);
  1288. if (CurrentShare->Root == NULL) {
  1289. wsprintf(NewPath, TEXT("\\\\%s\\%s\\"), SServ->Name, CurrentShare->Name);
  1290. #ifdef DEBUG
  1291. // lstrcpy(NewPath, TEXT("c:\\"));
  1292. dprintf(TEXT("Root Path: %s\n"), NewPath);
  1293. #endif
  1294. TreeRootInit(CurrentShare, NewPath);
  1295. }
  1296. PostMessage(hCtrl, LB_SETCURSEL, (WPARAM) 0, 0L);
  1297. LastFocus = 0;
  1298. DirList = (DIR_LIST *) CurrentShare->Root->DirList;
  1299. FileList = (FILE_LIST *) CurrentShare->Root->FileList;
  1300. wItemNum = (WORD) SendMessage(hCtrl, LB_ADDSTRING, (WPARAM) 0, (LPARAM) CurrentShare->Root);
  1301. PostMessage(hDlg, WM_COMMAND, ID_REDRAWLIST, 0L);
  1302. break;
  1303. }
  1304. } // FileSelect_OnCommand
  1305. /////////////////////////////////////////////////////////////////////////
  1306. LRESULT CALLBACK
  1307. FileSelectSubClassProc(
  1308. HWND hWnd,
  1309. UINT message,
  1310. WPARAM wParam,
  1311. LPARAM lParam
  1312. )
  1313. /*++
  1314. Routine Description:
  1315. Handles key processing for the hierarchical listbox. Specifically
  1316. the up/down arrow keys and the letter keys.
  1317. Arguments:
  1318. Return Value:
  1319. --*/
  1320. {
  1321. LRESULT lResult = 0;
  1322. BOOL fCallOrigProc = TRUE;
  1323. WORD wItemNum, wNewNum;
  1324. DWORD dwData;
  1325. DIR_BUFFER *Dir;
  1326. DIR_LIST *DirList;
  1327. FILE_BUFFER *File;
  1328. int nLevel = 0;
  1329. DWORD_PTR lHeight;
  1330. DWORD PageCount, ListHeight;
  1331. RECT rc;
  1332. switch (message) {
  1333. case WM_LBUTTONDOWN:
  1334. // Send message to check if button-down is within our checkbox
  1335. wItemNum = (WORD) SendMessage(hWnd, LB_GETCURSEL, 0, 0L);
  1336. // Save the location off so we can check it during a DBLCLK message
  1337. // to see if we are inside a checkbox.
  1338. mouseHit = lParam;
  1339. // Post the message so the current selection is correct
  1340. PostMessage(hWnd, WM_COMMAND, ID_CHECKCHECK, lParam);
  1341. break;
  1342. case WM_COMMAND:
  1343. // Code for handling checkbox clicking
  1344. if (wParam == ID_CHECKCHECK) {
  1345. // First figure out where checkbox is located in listbox
  1346. wItemNum = (WORD) SendMessage(hWnd, LB_GETCURSEL, 0, 0L);
  1347. dwData = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, wItemNum, 0L);
  1348. if (wItemNum == (WORD) LB_ERR)
  1349. break;
  1350. if (hWnd == hwndList2) {
  1351. File = (FILE_BUFFER *) dwData;
  1352. if (HierFile_InCheck(nLevel, LOWORD(lParam), &HierDrawStruct)) {
  1353. if (File->Convert == CONVERT_NONE)
  1354. File->Convert = CONVERT_ALL;
  1355. else
  1356. File->Convert = CONVERT_NONE;
  1357. DirAdjustConvert(File->parent->parent);
  1358. }
  1359. } else {
  1360. Dir = (DIR_BUFFER *) dwData;
  1361. DirList = (DIR_LIST *) Dir->parent;
  1362. if (DirList != NULL)
  1363. nLevel = DirList->Level;
  1364. if (HierFile_InCheck(nLevel, LOWORD(lParam), &HierDrawStruct)) {
  1365. if (Dir->Convert == CONVERT_NONE)
  1366. DirAdjustConvertChildren(Dir, CONVERT_ALL);
  1367. else
  1368. DirAdjustConvertChildren(Dir, CONVERT_NONE);
  1369. DirAdjustConvert(Dir);
  1370. }
  1371. }
  1372. // Now check if button click was within checkbox boundaries...
  1373. if (HierFile_InCheck(nLevel, LOWORD(lParam), &HierDrawStruct)) {
  1374. // We have set the checkbox state correctly on the current item,
  1375. // and propageted this up and down the tree as necessary, now
  1376. // update the screen to reflect these changes.
  1377. InvalidateRect(hWnd, NULL, TRUE); // Force redraw
  1378. // if this is the directory listbox then also need to redraw
  1379. // the file listbox
  1380. if (hWnd == hwndList1)
  1381. InvalidateRect(hwndList2, NULL, TRUE);
  1382. }
  1383. }
  1384. break;
  1385. case WM_KEYDOWN:
  1386. wItemNum = (WORD) SendMessage(hWnd, LB_GETCURSEL, 0, 0L);
  1387. if (wItemNum != (WORD) LB_ERR)
  1388. dwData = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, wItemNum, 0L);
  1389. else {
  1390. wItemNum = 0;
  1391. dwData = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, wItemNum, 0L);
  1392. }
  1393. if ((wItemNum == (WORD) LB_ERR) || (dwData == LB_ERR) || (dwData == 0))
  1394. break;
  1395. fCallOrigProc = FALSE;
  1396. switch (LOWORD(wParam)) {
  1397. case VK_PRIOR:
  1398. // Need to figure out the number of items to page. This
  1399. // would be the listbox height divided by the height of
  1400. // a listbox item
  1401. lHeight = SendMessage(hWnd, LB_GETITEMHEIGHT, 0, 0L);
  1402. GetWindowRect(hWnd, &rc);
  1403. ListHeight = (rc.bottom - rc.top);
  1404. if (ListHeight)
  1405. PageCount = ListHeight / (LONG) lHeight;
  1406. else
  1407. PageCount = 0;
  1408. // See if we page past the top - if so adjust it.
  1409. if (wItemNum > PageCount)
  1410. wNewNum = (USHORT) (wItemNum - PageCount);
  1411. else
  1412. wNewNum = 0;
  1413. PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wNewNum, 0L);
  1414. if (hWnd == hwndList1)
  1415. PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
  1416. break;
  1417. case VK_NEXT:
  1418. // Need to figure out the number of items to page. This
  1419. // would be the listbox height divided by the height of
  1420. // a listbox item
  1421. lHeight = SendMessage(hWnd, LB_GETITEMHEIGHT, 0, 0L);
  1422. GetWindowRect(hWnd, &rc);
  1423. ListHeight = (rc.bottom - rc.top);
  1424. if (ListHeight)
  1425. PageCount = ListHeight / (ULONG) lHeight;
  1426. else
  1427. PageCount = 0;
  1428. // Figure out if we page past the end - if so adjust it
  1429. wItemNum = (USHORT) (wItemNum + PageCount);
  1430. wNewNum = (WORD) SendMessage(hWnd, LB_GETCOUNT, (WPARAM) 0, 0L);
  1431. if (wItemNum < wNewNum)
  1432. PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wItemNum, 0L);
  1433. else
  1434. PostMessage(hWnd, LB_SETCURSEL, (WPARAM) (wNewNum - 1), 0L);
  1435. if (hWnd == hwndList1)
  1436. PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
  1437. break;
  1438. case VK_END:
  1439. wItemNum = (WORD) SendMessage(hWnd, LB_GETCOUNT, (WPARAM) 0, 0L);
  1440. if (wItemNum != (WORD) LB_ERR)
  1441. PostMessage(hWnd, LB_SETCURSEL, (WPARAM) (wItemNum - 1), 0L);
  1442. if (hWnd == hwndList1)
  1443. PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
  1444. break;
  1445. case VK_HOME:
  1446. PostMessage(hWnd, LB_SETCURSEL, (WPARAM) 0, 0L);
  1447. if (hWnd == hwndList1)
  1448. PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
  1449. break;
  1450. case VK_UP:
  1451. if (wItemNum > 0) {
  1452. wItemNum--;
  1453. PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wItemNum, 0L);
  1454. if (hWnd == hwndList1)
  1455. PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
  1456. }
  1457. break;
  1458. case VK_DOWN:
  1459. wItemNum++;
  1460. PostMessage(hWnd, LB_SETCURSEL, (WPARAM) wItemNum, 0L);
  1461. if (hWnd == hwndList1)
  1462. PostMessage(GetParent(hWnd), WM_COMMAND, ID_REDRAWLIST, 0L);
  1463. break;
  1464. case VK_F1:
  1465. fCallOrigProc = TRUE;
  1466. break;
  1467. case VK_SPACE:
  1468. // First figure out where checkbox is located in listbox
  1469. wItemNum = (WORD) SendMessage(hWnd, LB_GETCURSEL, 0, 0L);
  1470. dwData = (DWORD) SendMessage(hWnd, LB_GETITEMDATA, wItemNum, 0L);
  1471. if (wItemNum == (WORD) LB_ERR)
  1472. break;
  1473. if (hWnd == hwndList2) {
  1474. File = (FILE_BUFFER *) dwData;
  1475. if (File->Convert == CONVERT_NONE)
  1476. File->Convert = CONVERT_ALL;
  1477. else
  1478. File->Convert = CONVERT_NONE;
  1479. DirAdjustConvert(File->parent->parent);
  1480. } else {
  1481. Dir = (DIR_BUFFER *) dwData;
  1482. DirList = (DIR_LIST *) Dir->parent;
  1483. if (DirList != NULL)
  1484. nLevel = DirList->Level;
  1485. if (Dir->Convert == CONVERT_NONE)
  1486. DirAdjustConvertChildren(Dir, CONVERT_ALL);
  1487. else
  1488. DirAdjustConvertChildren(Dir, CONVERT_NONE);
  1489. DirAdjustConvert(Dir);
  1490. }
  1491. // We have set the checkbox state correctly on the current item,
  1492. // and propageted this up and down the tree as necessary, now
  1493. // update the screen to reflect these changes.
  1494. InvalidateRect(hWnd, NULL, TRUE); // Force redraw
  1495. // if this is the directory listbox then also need to redraw
  1496. // the file listbox
  1497. if (hWnd == hwndList1)
  1498. InvalidateRect(hwndList2, NULL, TRUE);
  1499. break;
  1500. default:
  1501. break;
  1502. }
  1503. break;
  1504. }
  1505. if (fCallOrigProc)
  1506. if (hWnd == hwndList2)
  1507. lResult = CallWindowProc(_wpOrigWndProc2, hWnd, message, wParam, lParam);
  1508. else
  1509. lResult = CallWindowProc(_wpOrigWndProc, hWnd, message, wParam, lParam);
  1510. return (lResult);
  1511. } // FileSelectSubClassProc
  1512. /////////////////////////////////////////////////////////////////////////
  1513. LRESULT CALLBACK
  1514. DlgFileSelect(
  1515. HWND hDlg,
  1516. UINT message,
  1517. WPARAM wParam,
  1518. LPARAM lParam
  1519. )
  1520. /*++
  1521. Routine Description:
  1522. Arguments:
  1523. Return Value:
  1524. --*/
  1525. {
  1526. int xPos;
  1527. int yPos;
  1528. BOOL InRange;
  1529. RECT rc;
  1530. HWND hCtrl;
  1531. switch (message) {
  1532. case WM_INITDIALOG:
  1533. // Copy the tree
  1534. oDir = CurrentShare->Root;
  1535. CurrentShare->Root = TreeCopy(oDir);
  1536. // Center the dialog over the application window
  1537. CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
  1538. GetClientRect(hDlg, &rc);
  1539. ControlsResize(hDlg, (rc.bottom - rc.top), (rc.right - rc.left));
  1540. // subclass listbox handler
  1541. hCtrl = GetDlgItem(hDlg, IDC_LIST1);
  1542. _wpOrigWndProc = SubclassWindow(hCtrl, FileSelectSubClassProc);
  1543. hCtrl = GetDlgItem(hDlg, IDC_LIST2);
  1544. _wpOrigWndProc2 = SubclassWindow(hCtrl, FileSelectSubClassProc);
  1545. FillDirInit();
  1546. hwndList2 = hCtrl = GetDlgItem(hDlg, IDC_LIST2);
  1547. hwndList1 = GetDlgItem(hDlg, IDC_LIST1);
  1548. // Fill listbox and set selection (is assumed there is always a selection)...
  1549. PostMessage(hDlg, WM_COMMAND, ID_UPDATELIST, 0L);
  1550. return (TRUE);
  1551. case WM_INITMENU:
  1552. if (GetMenu(hDlg) != (HMENU) wParam)
  1553. break;
  1554. CheckMenuItem((HMENU) wParam, IDM_HIDDEN, HiddenFiles ? MF_CHECKED : MF_UNCHECKED);
  1555. CheckMenuItem((HMENU) wParam, IDM_SYSTEM, SystemFiles ? MF_CHECKED : MF_UNCHECKED);
  1556. break;
  1557. case WM_SIZE:
  1558. ControlsResize(hDlg, HIWORD(lParam), LOWORD(lParam));
  1559. break;
  1560. case WM_SETFONT:
  1561. // Set the text height
  1562. HierFile_DrawSetTextHeight(GetDlgItem(hDlg, IDC_LIST1), (HFONT)wParam, &HierDrawStruct);
  1563. break;
  1564. case WM_DRAWITEM:
  1565. FileSelect_OnDrawItem(hDlg, (DRAWITEMSTRUCT FAR*)(lParam));
  1566. return TRUE;
  1567. case WM_MEASUREITEM:
  1568. HierFile_OnMeasureItem(hDlg, (MEASUREITEMSTRUCT FAR*)(lParam), &HierDrawStruct);
  1569. return TRUE;
  1570. case WM_MOUSEMOVE: {
  1571. xPos = LOWORD(lParam);
  1572. yPos = HIWORD(lParam);
  1573. InRange = TRUE;
  1574. // Check if it is correct Y-coordinate
  1575. if ((yPos <= Y_BORDER) || (yPos >= Splitter_Bottom))
  1576. InRange = FALSE;
  1577. // Now Check X-coordinate
  1578. if ((xPos < Splitter_Left) || (xPos > (Splitter_Left + X_BORDER)))
  1579. InRange = FALSE;
  1580. // Is within range of splitter, so handle it...
  1581. }
  1582. break;
  1583. case WM_COMMAND:
  1584. FileSelect_OnCommand(hDlg, wParam, lParam);
  1585. break;
  1586. }
  1587. return (FALSE); // Didn't process the message
  1588. lParam;
  1589. } // DlgFileSelect
  1590. /////////////////////////////////////////////////////////////////////////
  1591. VOID
  1592. FileSelect_Do(
  1593. HWND hDlg,
  1594. SOURCE_SERVER_BUFFER *SourceServ,
  1595. SHARE_BUFFER *CShare
  1596. )
  1597. /*++
  1598. Routine Description:
  1599. Arguments:
  1600. Return Value:
  1601. --*/
  1602. {
  1603. DLGPROC lpfnDlg;
  1604. TreeRecurseCurrentShareSet(CShare);
  1605. SServ = SourceServ;
  1606. HiddenFiles = CurrentShare->HiddenFiles;
  1607. SystemFiles = CurrentShare->SystemFiles;
  1608. // Init the Hier Draw stuff - Need to do this here so we have a value
  1609. // for WM_MEASUREITEM which is sent before the WM_INITDIALOG message
  1610. HierFile_DrawInit(hInst, IDR_FILEICONS, IDR_CHECKICONS, ROWS, COLS, TRUE, &HierDrawStruct, TRUE );
  1611. lpfnDlg = MakeProcInstance((DLGPROC)DlgFileSelect, hInst);
  1612. DialogBox(hInst, TEXT("FileSelect"), hDlg, lpfnDlg) ;
  1613. FreeProcInstance(lpfnDlg);
  1614. HierFile_DrawTerm(&HierDrawStruct);
  1615. } // FileSelect_Do