source: trunk/dll/treecnr.c @ 761

Last change on this file since 761 was 761, checked in by Gregg Young, 13 years ago

Cleanup of FilesToGet? changes (ticket 138)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 77.8 KB
Line 
1/***********************************************************************
2
3  $Id: treecnr.c 761 2007-08-04 22:38:34Z gyoung $
4
5  Tree containers
6
7  Copyright (c) 1993-98 M. Kimes
8  Copyright (c) 2001, 2007 Steven H. Levine
9
10  16 Oct 02 SHL Handle large partitions
11  11 Jun 03 SHL Add JFS and FAT32 support
12  25 May 05 SHL Rename comnam to szCommonName and fix typo
13  25 May 05 SHL Use ULONGLONG and CommaFmtULL
14  26 May 05 SHL More large file formatting updates
15  05 Jun 05 SHL Use QWL_USER
16  06 Aug 05 SHL Renames
17  08 Dec 05 SHL TreeCnrWndProc: disable menu items if drive not ready
18  17 Jul 06 SHL Use Runtime_Error
19  15 Aug 06 SHL Rework SetMask args
20  31 Aug 06 JS  Add more partitioning menu items
21  22 OCT 06 GKY Add NDFS32 support
22  29 Dec 06 GKY Fixed menu gray out for remote drives (added variable "remote")
23  29 Dec 06 GKY Enabled edit of drive flags on "not ready" drives
24  18 Feb 07 GKY More drive type and icon support
25  08 Mar 07 SHL Ensure drive icon updates after drive flags change
26  09 Mar 07 GKY Use SelectDriveIcon
27  30 Mar 07 GKY Remove GetPString for window class names
28  06 Apr 07 GKY Work around PM DragInfo and DrgFreeDISH limits
29  06 Apr 07 GKY Add some error checking in drag/drop
30  19 Apr 07 SHL Sync with AcceptOneDrop GetOneDrop mods
31  19 Apr 07 SHL Add more drag/drop error checking
32  12 May 07 SHL Use dcd->ulItemsToUnHilite; sync with UnHilite arg mods
33  10 Jun 07 GKY Add CheckPmDrgLimit including IsFm2Window as part of work around PM drag limit
34  10 Jun 07 GKY Mouse button 3 white space click to fail silently
35  05 Jul 07 SHL Disable leftover debug code
36  02 Aug 07 SHL Sync with CNRITEM mods
37
38***********************************************************************/
39
40#define INCL_DOS
41#define INCL_WIN
42#define INCL_GPI
43#define INCL_DOSERRORS
44#define INCL_LONGLONG
45#include <os2.h>
46
47#include <stdarg.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include <ctype.h>
52#include <process.h>                    // _beginthread
53
54#include "fm3dll.h"
55#include "fm3dlg.h"
56#include "fm3str.h"
57#include "mle.h"
58
59#pragma data_seg(DATA1)
60
61static PSZ pszSrcFile = __FILE__;
62
63#pragma alloc_text(TREECNR,TreeCnrWndProc,TreeObjWndProc,TreeClientWndProc)
64#pragma alloc_text(TREECNR,TreeFrameWndProc,TreeTitleWndProc,ShowTreeRec)
65#pragma alloc_text(TREECNR,TreeStatProc,OpenButtonProc)
66#pragma alloc_text(STARTUP,StartTreeCnr)
67
68APIRET16 APIENTRY16 Dos16MemAvail(PULONG pulAvailMem);
69
70typedef struct APPNOTIFY
71{
72  HAPP happ;
73  CHAR device;
74  struct APPNOTIFY *next;
75  struct APPNOTIFY *prev;
76}
77APPNOTIFY;
78
79MRESULT EXPENTRY OpenButtonProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
80{
81  static BOOL emphasized = FALSE;
82
83  switch (msg) {
84  case WM_CREATE:
85    {
86      MRESULT rc;
87
88      rc = PFNWPButton(hwnd, msg, mp1, mp2);
89      WinSetPresParam(hwnd, PP_FONTNAMESIZE,
90                      strlen(GetPString(IDS_8TIMESNEWROMANTEXT)) + 1,
91                      (PVOID) GetPString(IDS_8TIMESNEWROMANTEXT));
92      return rc;
93    }
94
95  case WM_MOUSEMOVE:
96    BubbleHelp(hwnd, TRUE, FALSE, TRUE, GetPString(IDS_OPENBUTTONHELP));
97    break;
98
99  case WM_CONTEXTMENU:
100    PostMsg(WinQueryWindow(hwnd, QW_PARENT),
101            WM_COMMAND, MPFROM2SHORT(IDM_OPENWALK, 0), MPVOID);
102    return 0;
103
104  case DM_DRAGOVER:
105    if (!emphasized) {
106      emphasized = TRUE;
107      EmphasizeButton(hwnd, emphasized);
108    }
109    if (AcceptOneDrop(hwnd, mp1, mp2))
110      return MRFROM2SHORT(DOR_DROP, DO_MOVE);
111    return MRFROM2SHORT(DOR_NEVERDROP, 0);
112
113  case DM_DRAGLEAVE:
114    if (emphasized) {
115      emphasized = FALSE;
116      EmphasizeButton(hwnd, emphasized);
117    }
118    break;
119
120  case DM_DROPHELP:
121    DropHelp(mp1, mp2, hwnd, GetPString(IDS_OPENDROPHELP));
122    return 0;
123
124  case DM_DROP:
125    {
126      char szFrom[CCHMAXPATH + 2];
127
128      if (emphasized) {
129        emphasized = FALSE;
130        EmphasizeButton(hwnd, emphasized);
131      }
132      if (GetOneDrop(hwnd, mp1, mp2, szFrom, sizeof(szFrom))) {
133        MakeValidDir(szFrom);
134        WinSendMsg(WinQueryWindow(hwnd, QW_PARENT),
135                   UM_OPENWINDOWFORME, MPFROMP(szFrom), MPVOID);
136      }
137    }
138    return 0;
139
140  }
141  return PFNWPButton(hwnd, msg, mp1, mp2);
142}
143
144VOID ShowTreeRec(HWND hwndCnr, CHAR * dirname, BOOL collapsefirst,
145                 BOOL maketop)
146{
147  /* Find a record in tree view, move it so it shows in container and
148     make it the current record */
149
150  PCNRITEM pci, pciToSelect, pciP;
151  BOOL quickbail = FALSE;
152  CHAR szDir[CCHMAXPATH], *p;
153
154  /* is it already the current record? */
155  pci = WinSendMsg(hwndCnr,
156                   CM_QUERYRECORDEMPHASIS,
157                   MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_CURSORED));
158  if (pci && (INT) pci != -1 && !stricmp(pci->pszFileName, dirname)) {
159    quickbail = TRUE;
160    goto MakeTop;                       /* skip lookup bullsh*t */
161  }
162  WinEnableWindowUpdate(hwndCnr, FALSE);
163  pci = FindCnrRecord(hwndCnr, dirname, NULL, TRUE, FALSE, TRUE);
164  if (!pci || (INT) pci == -1) {
165    *szDir = *dirname;
166    szDir[1] = ':';
167    szDir[2] = '\\';
168    szDir[3] = 0;
169    p = szDir + 3;
170    for (;;) {
171      pciP = FindCnrRecord(hwndCnr, szDir, NULL, TRUE, FALSE, TRUE);
172      if (pciP && (INT) pciP != -1) {
173        if (!stricmp(dirname, pciP->pszFileName))
174          break;
175        if (!(pciP->rc.flRecordAttr & CRA_EXPANDED))
176          WinSendMsg(hwndCnr, CM_EXPANDTREE, MPFROMP(pciP), MPVOID);
177        strcpy(szDir, dirname);
178        if (p - szDir >= strlen(szDir))
179          break;
180        p = strchr(p, '\\');
181        if (p) {
182          *p = 0;
183          p++;
184        }
185        else
186          break;
187      }
188      else
189        break;
190      DosSleep(0L);
191    }
192    pci = FindCnrRecord(hwndCnr, dirname, NULL, TRUE, FALSE, TRUE);
193  }
194  if (pci && (INT) pci != -1) {
195    if (!(pci->rc.flRecordAttr & CRA_CURSORED)) {
196      if (collapsefirst) {
197        /* collapse top level of all branches */
198        pciP = WinSendMsg(hwndCnr,
199                          CM_QUERYRECORD,
200                          MPVOID, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
201        while (pciP && (INT) pciP != -1) {
202          if (toupper(*pciP->pszFileName) == toupper(*dirname))
203            /* collapse all levels if branch is our drive */
204            ExpandAll(hwndCnr, FALSE, pciP);
205          else if (pciP->rc.flRecordAttr & CRA_EXPANDED)
206            WinSendMsg(hwndCnr, CM_COLLAPSETREE, MPFROMP(pciP), MPVOID);
207          pciP = WinSendMsg(hwndCnr,
208                            CM_QUERYRECORD,
209                            MPFROMP(pciP),
210                            MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
211        }
212      }
213      /* expand all parent branches */
214      pciToSelect = pci;
215      for (;;) {
216        pciP = WinSendMsg(hwndCnr,
217                          CM_QUERYRECORD,
218                          MPFROMP(pciToSelect),
219                          MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
220        if (pciP && (INT) pciP != -1) {
221          if (!(pciP->rc.flRecordAttr & CRA_EXPANDED))
222            WinSendMsg(hwndCnr, CM_EXPANDTREE, MPFROMP(pciP), MPVOID);
223          pciToSelect = pciP;
224        }
225        else
226          break;
227        DosSleep(0L);
228      }
229    }
230    /* make record visible */
231  MakeTop:
232    pciToSelect = pci;
233    if (pciToSelect && (INT) pciToSelect != -1) {
234      if (fTopDir || maketop)
235        ShowCnrRecord(hwndCnr, (PMINIRECORDCORE) pciToSelect);
236      if (fSwitchTreeExpand && !(pciToSelect->rc.flRecordAttr & CRA_EXPANDED))
237        WinSendMsg(hwndCnr, CM_EXPANDTREE, MPFROMP(pciToSelect), MPVOID);
238      if (quickbail) {
239        WinEnableWindowUpdate(hwndCnr, TRUE);
240        return;
241      }
242      WinSendMsg(hwndCnr,
243                 CM_SETRECORDEMPHASIS,
244                 MPFROMP(pciToSelect),
245                 MPFROM2SHORT(TRUE, CRA_SELECTED | CRA_CURSORED));
246    }
247  }
248  WinEnableWindowUpdate(hwndCnr, TRUE);
249}
250
251MRESULT EXPENTRY TreeTitleWndProc(HWND hwnd, ULONG msg, MPARAM mp1,
252                                  MPARAM mp2)
253{
254  PFNWP oldproc = (PFNWP) WinQueryWindowPtr(hwnd, QWL_USER);
255
256  switch (msg) {
257  case WM_CONTEXTMENU:
258    return WinSendMsg(WinQueryWindow(hwnd, QW_PARENT),
259                      UM_CONTEXTMENU, mp1, mp2);
260  }
261  return oldproc(hwnd, msg, mp1, mp2);
262}
263
264MRESULT EXPENTRY TreeStatProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
265{
266  switch (msg) {
267  case WM_CREATE:
268    return CommonTextProc(hwnd, msg, mp1, mp2);
269
270  case WM_CONTEXTMENU:
271    PostMsg(WinQueryWindow(hwnd, QW_PARENT), msg, mp1, mp2);
272    return 0;
273
274  case WM_PAINT:
275    {
276      MRESULT mr = PFNWPStatic(hwnd, msg, mp1, mp2);
277
278      PaintRecessedWindow(hwnd, (HPS) 0, FALSE, FALSE);
279      return mr;
280    }
281
282  case WM_SETFOCUS:
283    if (mp2)
284      PostMsg(hwnd, UM_FOCUSME, MPVOID, MPVOID);
285    break;
286
287  case UM_FOCUSME:
288    WinSetFocus(HWND_DESKTOP, WinQueryWindow(hwnd, QW_PARENT));
289    return 0;
290  }
291  return PFNWPStatic(hwnd, msg, mp1, mp2);
292}
293
294MRESULT EXPENTRY TreeFrameWndProc(HWND hwnd, ULONG msg, MPARAM mp1,
295                                  MPARAM mp2)
296{
297  switch (msg) {
298  case UM_RESCAN:
299    PostMsg(WinQueryWindow(hwnd, QW_PARENT), msg, mp1, mp2);
300    return 0;
301
302  case WM_ADJUSTWINDOWPOS:
303    {
304      SWP *pswp;
305
306      pswp = (SWP *) mp1;
307      if (ParentIsDesktop(hwnd, (HWND) 0)) {
308        if (pswp->fl & (SWP_HIDE | SWP_MINIMIZE))
309          HideNote();
310      }
311    }
312    break;
313
314  case WM_TRACKFRAME:
315    if (!fFreeTree && !ParentIsDesktop(hwnd, (HWND) 0)) {
316      switch (SHORT1FROMMP(mp1) & TF_MOVE) {
317      case TF_MOVE:
318      case TF_LEFT:
319      case TF_TOP:
320      case (TF_LEFT | TF_BOTTOM):
321      case (TF_LEFT | TF_TOP):
322        {
323          SWP swp;
324
325          WinQueryWindowPos(hwnd, &swp);
326          if (!(swp.fl & SWP_ACTIVATE))
327            WinSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
328                            SWP_ZORDER | SWP_ACTIVATE);
329        }
330        return 0;
331      }
332    }
333    break;
334
335  case WM_CALCFRAMERECT:
336    if (*(ULONG *) realappname != FM3UL) {
337
338      MRESULT mr;
339      PRECTL prectl;
340
341      mr = CommonFrameWndProc(TREE_CNR, hwnd, msg, mp1, mp2);
342
343      /*
344       * Calculate the position of the client rectangle.
345       * Otherwise,  we'll see a lot of redraw when we move the
346       * client during WM_FORMATFRAME.
347       */
348
349      if (mr && mp2) {
350        prectl = (PRECTL) mp1;
351        prectl->yTop -= 22;
352      }
353      return mr;
354    }
355    break;
356
357  case WM_FORMATFRAME:
358    {
359      SHORT sCount;
360      PSWP pswp, pswpClient, pswpNew;
361
362      sCount = (SHORT) CommonFrameWndProc(TREE_CNR, hwnd, msg, mp1, mp2);
363
364      /*
365       * Reformat the frame to "squeeze" the client
366       */
367
368      pswp = (PSWP) mp1;
369      {
370        SHORT x;
371
372        for (x = 0; x < sCount; x++) {
373          if (WinQueryWindowUShort(pswp->hwnd, QWS_ID) == FID_CLIENT) {
374            pswpClient = pswp;
375            break;
376          }
377          pswp++;
378        }
379      }
380      pswpNew = (PSWP) mp1 + sCount;
381      *pswpNew = *pswpClient;
382      pswpNew->hwnd = WinWindowFromID(hwnd, MAIN_STATUS);
383      if (*(ULONG *) realappname == FM3UL) {
384
385        PSWP pswpTitlebar = (PSWP) 0, pswpMinbutton = (PSWP) 0;
386        SHORT x;
387
388        pswpNew->hwnd = WinWindowFromID(hwnd, IDM_OPENWINDOW);
389        pswp = (PSWP) mp1;
390        for (x = 0; x < sCount; x++) {
391          if (WinQueryWindowUShort(pswp->hwnd, QWS_ID) == FID_TITLEBAR)
392            pswpTitlebar = pswp;
393          else if (WinQueryWindowUShort(pswp->hwnd, QWS_ID) == FID_MINMAX)
394            pswpMinbutton = pswp;
395          if (pswpTitlebar && pswpMinbutton)
396            break;
397          pswp++;
398        }
399        pswpNew->cy = pswpMinbutton->cy + 3;
400        pswpNew->cx = min(pswpNew->cy, (pswpMinbutton->cx / 2) + 3);
401        pswpTitlebar->cx -= (pswpNew->cx + 1);
402        pswpNew->x = pswpTitlebar->x + pswpTitlebar->cx;
403        pswpNew->y = pswpMinbutton->y - 1;
404      }
405      else {
406        pswpNew->x = pswpClient->x + 3;
407        pswpNew->y = (pswpClient->y + pswpClient->cy) - 20;
408        pswpNew->cx = pswpClient->cx - 6;
409        pswpNew->cy = 18;
410        pswpClient->cy -= 22;
411      }
412      sCount++;
413      return MRFROMSHORT(sCount);
414    }
415
416  case WM_QUERYFRAMECTLCOUNT:
417    {
418      SHORT sCount;
419
420      sCount = (SHORT) CommonFrameWndProc(TREE_CNR, hwnd, msg, mp1, mp2);
421      sCount++;
422      return MRFROMSHORT(sCount);
423    }
424  }
425  return CommonFrameWndProc(TREE_CNR, hwnd, msg, mp1, mp2);
426}
427
428MRESULT EXPENTRY TreeClientWndProc(HWND hwnd, ULONG msg, MPARAM mp1,
429                                   MPARAM mp2)
430{
431
432  switch (msg) {
433  case UM_CONTAINERHWND:
434    return MRFROMLONG(WinWindowFromID(hwnd, TREE_CNR));
435
436  case UM_VIEWSMENU:
437    return MRFROMLONG(CheckMenu(&TreeCnrMenu, TREECNR_POPUP));
438
439  case UM_TIMER:
440  case UM_ACTION:
441  case UM_SHOWME:
442  case UM_OPENWINDOWFORME:
443  case UM_MINIMIZE:
444  case UM_MAXIMIZE:
445  case WM_INITMENU:
446  case UM_INITMENU:
447  case UM_FILTER:
448  case UM_FILESMENU:
449  case UM_UPDATERECORD:
450  case UM_UPDATERECORDLIST:
451  case MM_PORTHOLEINIT:
452  case UM_DRIVECMD:
453  case WM_CLOSE:
454  case WM_CONTROL:
455  case UM_COMMAND:
456  case WM_COMMAND:
457    return WinSendMsg(WinWindowFromID(hwnd, TREE_CNR), msg, mp1, mp2);
458
459  case WM_PSETFOCUS:
460  case WM_SETFOCUS:
461    if (mp2)
462      PostMsg(hwnd, UM_FOCUSME, MPVOID, MPVOID);
463    break;
464
465  case UM_FOCUSME:
466    WinSetFocus(HWND_DESKTOP, WinWindowFromID(hwnd, TREE_CNR));
467    break;
468
469  case WM_ERASEBACKGROUND:
470    WinFillRect((HPS) mp1, (PRECTL) mp2, 0x00d0d0d0);
471    return 0;
472
473  case WM_PAINT:
474    {
475      HPS hps;
476      RECTL rcl;
477
478      hps = WinBeginPaint(hwnd, (HPS) 0, NULL);
479      if (hps) {
480        WinQueryWindowRect(hwnd, &rcl);
481        WinFillRect(hps, &rcl, CLR_PALEGRAY);
482        PaintRecessedWindow(WinWindowFromID(WinQueryWindow(hwnd, QW_PARENT),
483                                            MAIN_STATUS), hps, FALSE, FALSE);
484        WinEndPaint(hps);
485      }
486    }
487    break;
488
489  case WM_SIZE:
490    WinSetWindowPos(WinWindowFromID(hwnd, TREE_CNR),
491                    HWND_TOP,
492                    0,
493                    0,
494                    SHORT1FROMMP(mp2),
495                    SHORT2FROMMP(mp2), SWP_SHOW | SWP_MOVE | SWP_SIZE);
496    if (hwndMain)
497      PostMsg(hwndMain, UM_SIZE, MPVOID, MPVOID);
498    break;
499
500  case WM_CONTEXTMENU:
501  case UM_CONTEXTMENU:
502    PostMsg(WinWindowFromID(hwnd, TREE_CNR),
503            WM_CONTROL, MPFROM2SHORT(TREE_CNR, CN_CONTEXTMENU), MPVOID);
504    return 0;
505  }
506  return WinDefWindowProc(hwnd, msg, mp1, mp2);
507}
508
509MRESULT EXPENTRY TreeObjWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
510{
511  DIRCNRDATA *dcd;
512
513  switch (msg) {
514  case WM_CREATE:
515    break;
516
517  case UM_SHOWME:
518    if (mp1) {
519      dcd = INSTDATA(hwnd);
520      if (dcd) {
521        BOOL tempsusp, tempfollow, temptop;
522
523        tempsusp = dcd->suspendview;
524        dcd->suspendview = TRUE;
525        tempfollow = fFollowTree;
526        fFollowTree = FALSE;
527        if (mp2) {
528          temptop = fTopDir;
529          fTopDir = TRUE;
530        }
531        ShowTreeRec(dcd->hwndCnr, (CHAR *) mp1, fCollapseFirst, TRUE);
532        dcd->suspendview = tempsusp;
533        fFollowTree = tempfollow;
534        if (mp2)
535          fTopDir = temptop;
536      }
537      free((CHAR *) mp1);
538    }
539    return 0;
540
541  case DM_PRINTOBJECT:
542    return MRFROMLONG(DRR_TARGET);
543
544  case DM_DISCARDOBJECT:
545    dcd = INSTDATA(hwnd);
546    if (fFM2Deletes && dcd) {
547
548      LISTINFO *li;
549      CNRDRAGINFO cni;
550
551      cni.pRecord = NULL;
552      cni.pDragInfo = (PDRAGINFO) mp1;
553      li = DoFileDrop(dcd->hwndCnr,
554                      dcd->directory, FALSE, MPVOID, MPFROMP(&cni));
555      CheckPmDrgLimit(cni.pDragInfo);
556      if (li) {
557        li->type = ((fDefaultDeletePerm) ? IDM_PERMDELETE : IDM_DELETE);
558        if (!PostMsg(hwnd, UM_MASSACTION, MPFROMP(li), MPVOID))
559          FreeListInfo(li);
560        else
561          return MRFROMLONG(DRR_SOURCE);
562      }
563    }
564    return MRFROMLONG(DRR_TARGET);
565
566  case UM_EXPAND:
567    dcd = WinQueryWindowPtr(hwnd, QWL_USER);
568    if (!dcd)
569      Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
570    else {
571      BOOL tempsusp = dcd->suspendview;
572
573      dcd->suspendview = TRUE;
574      ExpandAll(dcd->hwndCnr,
575                (SHORT1FROMMP(mp1) == IDM_EXPAND), (PCNRITEM) mp2);
576      dcd->suspendview = tempsusp;
577      PostMsg(dcd->hwndCnr, UM_FILTER, MPVOID, MPVOID);
578    }
579    return 0;
580
581  case UM_UPDATERECORDLIST:
582    dcd = WinQueryWindowPtr(hwnd, QWL_USER);
583    if (!dcd || !mp1)
584      Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
585    else {
586      INT numentries = 0;
587      CHAR **list = (CHAR **) mp1;
588
589      while (list[numentries])
590        numentries++;
591      if (numentries)
592        UpdateCnrList(dcd->hwndCnr, list, numentries, TRUE, dcd);
593    }
594    return 0;
595
596  case UM_SETUP:
597    dcd = WinQueryWindowPtr(hwnd, QWL_USER);
598    if (!dcd)
599      Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
600    else {
601      dcd->hwndObject = hwnd;
602      if (ParentIsDesktop(hwnd, dcd->hwndParent))
603        DosSleep(250L);
604    }
605    return 0;
606
607  case UM_RESCAN2:
608    dcd = WinQueryWindowPtr(hwnd, QWL_USER);
609    if (!dcd)
610      Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
611    // Bypass if not running integrated (i.e if vtree)
612    else if (hwndStatus &&
613             dcd->hwndFrame == WinQueryActiveWindow(dcd->hwndParent)) {
614      CHAR s[CCHMAXPATH * 2];
615      PCNRITEM pci = (PCNRITEM) mp1;
616      FSALLOCATE fsa;
617      struct
618      {
619        ULONG serial;
620        CHAR volumelength;
621        CHAR volumelabel[CCHMAXPATH];
622      }
623      volser;
624      CHAR tb[64];
625      CHAR szFree[64];
626      CNRINFO cnri;
627
628      strcpy(s, GetPString(IDS_TREETEXT));
629      memset(&cnri, 0, sizeof(CNRINFO));
630      cnri.cb = sizeof(CNRINFO);
631      WinSendMsg(dcd->hwndCnr,
632                 CM_QUERYCNRINFO,
633                 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
634      if (cnri.cRecords) {
635        sprintf(s, GetPString(IDS_NUMDRIVESTEXT), cnri.cRecords);
636        if (pci) {
637          if (!(driveflags[toupper(*pci->pszFileName) - 'A'] &
638                DRIVE_REMOVABLE) ||
639              driveserial[toupper(*pci->pszFileName) - 'A'] != -1) {
640            memset(&volser, 0, sizeof(volser));
641            DosError(FERR_DISABLEHARDERR);
642            if (!DosQueryFSInfo(toupper(*pci->pszFileName) - '@',
643                                FSIL_VOLSER,
644                                &volser,
645                                (ULONG) sizeof(volser)) &&
646                dcd->hwndFrame == WinQueryActiveWindow(dcd->hwndParent)) {
647              DosError(FERR_DISABLEHARDERR);
648              if (!DosQueryFSInfo(toupper(*pci->pszFileName) - '@',
649                                  FSIL_ALLOC, &fsa, sizeof(FSALLOCATE))) {
650                CommaFmtULL(tb, sizeof(tb),
651                            (ULONGLONG) fsa.cUnitAvail * (fsa.cSectorUnit *
652                                                          fsa.cbSector), 'M');
653                sprintf(szFree, "  %s %s", tb, GetPString(IDS_FREETEXT));
654              }
655              else
656                *szFree = 0;
657              driveserial[toupper(*pci->pszFileName) - 'A'] = volser.serial;
658              sprintf(&s[strlen(s)],
659                      GetPString(IDS_TREESTATUSSTARTTEXT),
660                      toupper(*pci->pszFileName),
661                      volser.volumelabel, volser.serial, szFree);
662              if (!fMoreButtons) {
663                if (*dcd->mask.szMask ||
664                    (dcd->mask.attrFile != ALLATTRS ||
665                     ((fFilesInTree ||
666                       (driveflags[toupper(*pci->pszFileName)] &
667                        DRIVE_INCLUDEFILES)) ?
668                      dcd->mask.antiattr :
669                      (dcd->mask.antiattr &&
670                       dcd->mask.antiattr != FILE_DIRECTORY)))) {
671                  sprintf(&s[strlen(s)],
672                          " (%s)",
673                          (*dcd->mask.szMask) ?
674                          dcd->mask.szMask : GetPString(IDS_ATTRTEXT));
675                }
676              }
677            }
678          }
679          else {
680            /* find root record and strip it */
681            pci = FindParentRecord(dcd->hwndCnr, pci);
682            driveserial[toupper(*pci->pszFileName) - 'A'] = -1;
683            UnFlesh(dcd->hwndCnr, pci);
684          }
685        }
686      }
687      if (dcd->hwndFrame == WinQueryActiveWindow(dcd->hwndParent))
688        WinSetWindowText(hwndStatus, s);
689    }
690    return 0;
691
692  case UM_RESCAN:
693    /*
694     * populate container
695     */
696    dcd = WinQueryWindowPtr(hwnd, QWL_USER);
697    if (!dcd)
698      Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
699    else {
700      RemoveCnrItems(dcd->hwndCnr, NULL, 0, CMA_FREE | CMA_INVALIDATE | CMA_ERASE);
701      WinSendMsg(dcd->hwndCnr,
702                 CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), MPFROMLONG(-1));
703      WinSendMsg(dcd->hwndCnr,
704                 CM_SCROLLWINDOW,
705                 MPFROMSHORT(CMA_HORIZONTAL), MPFROMLONG(-1));
706      FillTreeCnr(dcd->hwndCnr, dcd->hwndParent);
707      if (fOkayMinimize) {
708        PostMsg(dcd->hwndCnr, UM_MINIMIZE, MPVOID, MPVOID);
709        fOkayMinimize = FALSE;
710      }
711      WinSendMsg(dcd->hwndCnr,
712                 CM_INVALIDATERECORD,
713                 MPVOID, MPFROM2SHORT(0, CMA_ERASE | CMA_REPOSITION));
714      PostMsg(dcd->hwndCnr, UM_RESCAN, MPVOID, MPVOID);
715    }
716    return 0;
717
718  case UM_COMMAND:
719    if (mp1) {
720
721      LISTINFO *li = (LISTINFO *) mp1;
722
723      switch (li->type) {
724      case IDM_DOITYOURSELF:
725      case IDM_APPENDTOCLIP:
726      case IDM_SAVETOCLIP:
727      case IDM_ARCHIVE:
728      case IDM_VIEW:
729      case IDM_EDIT:
730      case IDM_OBJECT:
731      case IDM_SHADOW:
732      case IDM_SHADOW2:
733      case IDM_PRINT:
734      case IDM_ATTRS:
735      case IDM_DELETE:
736      case IDM_PERMDELETE:
737        if (PostMsg(hwnd, UM_MASSACTION, mp1, mp2))
738          return (MRESULT) TRUE;
739      default:
740        if (PostMsg(hwnd, UM_ACTION, mp1, mp2))
741          return (MRESULT) TRUE;
742      }
743    }
744    return 0;
745
746  case UM_MASSACTION:
747    if (mp1) {
748
749      dcd = WinQueryWindowPtr(hwnd, QWL_USER);
750      if (!dcd)
751        Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
752      else {
753        WORKER *wk;
754
755        wk = xmallocz(sizeof(WORKER), pszSrcFile, __LINE__);
756        if (!wk)
757          FreeListInfo((LISTINFO *) mp1);
758        else {
759          wk->size = sizeof(WORKER);
760          wk->hwndCnr = dcd->hwndCnr;
761          wk->hwndParent = dcd->hwndParent;
762          wk->hwndFrame = dcd->hwndFrame;
763          wk->hwndClient = dcd->hwndClient;
764          wk->li = (LISTINFO *) mp1;
765          strcpy(wk->directory, dcd->directory);
766          if (_beginthread(MassAction, NULL, 122880, (PVOID) wk) == -1) {
767            Runtime_Error(pszSrcFile, __LINE__,
768                          GetPString(IDS_COULDNTSTARTTHREADTEXT));
769            free(wk);
770            FreeListInfo((LISTINFO *) mp1);
771          }
772        }
773      }
774    }
775    return 0;
776
777  case UM_ACTION:
778    if (mp1) {
779
780      dcd = WinQueryWindowPtr(hwnd, QWL_USER);
781      if (!dcd)
782        Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
783      else {
784        WORKER *wk;
785
786        wk = xmallocz(sizeof(WORKER), pszSrcFile, __LINE__);
787        if (!wk)
788          FreeListInfo((LISTINFO *) mp1);
789        else {
790          wk->size = sizeof(WORKER);
791          wk->hwndCnr = dcd->hwndCnr;
792          wk->hwndParent = dcd->hwndParent;
793          wk->hwndFrame = dcd->hwndFrame;
794          wk->hwndClient = dcd->hwndClient;
795          wk->li = (LISTINFO *) mp1;
796          strcpy(wk->directory, dcd->directory);
797          if (_beginthread(Action, NULL, 122880, (PVOID) wk) == -1) {
798            Runtime_Error(pszSrcFile, __LINE__,
799                          GetPString(IDS_COULDNTSTARTTHREADTEXT));
800            free(wk);
801            FreeListInfo((LISTINFO *) mp1);
802          }
803        }
804      }
805    }
806    return 0;
807
808  case WM_CLOSE:
809    WinDestroyWindow(hwnd);
810    break;
811
812  case WM_DESTROY:
813    hwndTree = (HWND) 0;
814    dcd = WinQueryWindowPtr(hwnd, QWL_USER);
815    if (dcd) {
816      WinSendMsg(dcd->hwndCnr,
817                 UM_CLOSE, MPFROMLONG(dcd->dontclose != FALSE), MPVOID);
818      free(dcd);
819    }
820    DosPostEventSem(CompactSem);
821    if (!PostMsg((HWND) 0, WM_QUIT, MPVOID, MPVOID))
822      WinSendMsg((HWND) 0, WM_QUIT, MPVOID, MPVOID);
823    break;
824  }
825  return WinDefWindowProc(hwnd, msg, mp1, mp2);
826}
827
828MRESULT EXPENTRY TreeCnrWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
829{
830  static APPNOTIFY *apphead = NULL, *apptail = NULL;
831  DIRCNRDATA *dcd = INSTDATA(hwnd);
832
833  switch (msg) {
834  case DM_PRINTOBJECT:
835    return MRFROMLONG(DRR_TARGET);
836
837  case DM_DISCARDOBJECT:
838    if (dcd)
839      return WinSendMsg(dcd->hwndObject, msg, mp1, mp2);
840    else
841      return MRFROMLONG(DRR_TARGET);
842
843  case WM_CHAR:
844    shiftstate = (SHORT1FROMMP(mp1) & (KC_SHIFT | KC_ALT | KC_CTRL));
845    if (SHORT1FROMMP(mp1) & KC_KEYUP)
846      return (MRESULT) TRUE;
847    if (SHORT1FROMMP(mp1) & KC_VIRTUALKEY) {
848      switch (SHORT2FROMMP(mp2)) {
849      case VK_INSERT:
850        if ((shiftstate & KC_CTRL) == KC_CTRL)
851          PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(IDM_MKDIR, 0), MPVOID);
852        break;
853      case VK_DELETE:
854        if ((shiftstate & KC_CTRL) == KC_CTRL)
855          PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(IDM_PERMDELETE, 0), MPVOID);
856        else if ((shiftstate & KC_SHIFT) == KC_SHIFT)
857          PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(IDM_SAVETOCLIP, 0), MPVOID);
858        else
859          PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(IDM_DELETE, 0), MPVOID);
860        break;
861      }
862    }
863    if (shiftstate || fNoSearch)
864      break;
865    if (SHORT1FROMMP(mp1) & KC_CHAR) {
866
867      ULONG thistime, len;
868      SEARCHSTRING srch;
869      PCNRITEM pci;
870
871      if (!dcd)
872        break;
873      switch (SHORT1FROMMP(mp2)) {
874      case '\x1b':
875      case '\r':
876      case '\n':
877        dcd->lasttime = 0;
878        *dcd->szCommonName = 0;
879        break;
880      default:
881        thistime = WinQueryMsgTime(WinQueryAnchorBlock(hwnd));
882        if (thistime > dcd->lasttime + 1250)
883          *dcd->szCommonName = 0;
884        dcd->lasttime = thistime;
885        if (SHORT1FROMMP(mp2) == ' ' && !*dcd->szCommonName)
886          break;
887      KbdRetry:
888        len = strlen(dcd->szCommonName);
889        if (len >= CCHMAXPATH - 1) {
890          *dcd->szCommonName = 0;
891          len = 0;
892        }
893        dcd->szCommonName[len] = toupper(SHORT1FROMMP(mp2));
894        dcd->szCommonName[len + 1] = 0;
895        memset(&srch, 0, sizeof(SEARCHSTRING));
896        srch.cb = (ULONG) sizeof(SEARCHSTRING);
897        srch.pszSearch = (PSZ) dcd->szCommonName;
898        srch.fsPrefix = TRUE;
899        srch.fsCaseSensitive = FALSE;
900        srch.usView = CV_ICON;
901        pci = WinSendMsg(hwnd,
902                         CM_SEARCHSTRING,
903                         MPFROMP(&srch), MPFROMLONG(CMA_FIRST));
904        if (pci && (INT) pci != -1) {
905          /* make found item current item */
906          WinSendMsg(hwnd,
907                     CM_SETRECORDEMPHASIS,
908                     MPFROMP(pci), MPFROM2SHORT(TRUE, CRA_CURSORED));
909          /* make sure that record shows in viewport */
910          ShowCnrRecord(hwnd, (PMINIRECORDCORE) pci);
911          return (MRESULT) TRUE;
912        }
913        else {
914          if (SHORT1FROMMP(mp2) == ' ') {
915            dcd->szCommonName[len] = 0;
916            break;
917          }
918          *dcd->szCommonName = 0;
919          dcd->lasttime = 0;
920          if (len)                      // retry as first letter if no match
921            goto KbdRetry;
922        }
923        break;
924      }
925    }
926    break;
927
928  case WM_MOUSEMOVE:
929  case WM_BUTTON1UP:
930  case WM_BUTTON2UP:
931  case WM_BUTTON3UP:
932    shiftstate = (SHORT2FROMMP(mp2) & (KC_SHIFT | KC_ALT | KC_CTRL));
933    break;
934
935  case UM_TIMER:
936    if (dcd && dcd->hwndFrame == WinQueryActiveWindow(dcd->hwndParent) &&
937        hwndStatus2) {
938      FILEFINDBUF3 ffb;
939      ULONG nm = 1;
940      HDIR hdir = HDIR_CREATE;
941
942      if (*SwapperDat) {
943        if (!DosFindFirst(SwapperDat,
944                          &hdir,
945                          FILE_NORMAL | FILE_HIDDEN |
946                          FILE_SYSTEM | FILE_ARCHIVED | FILE_READONLY,
947                          &ffb, sizeof(ffb), &nm, FIL_STANDARD)) {
948          CHAR tb[39], tm[39], tpm[39], s[163];
949          ULONG amem;
950
951          priority_bumped();
952          DosFindClose(hdir);
953          if (!DosQuerySysInfo(QSV_TOTAVAILMEM,
954                               QSV_TOTAVAILMEM,
955                               (PVOID) & amem, sizeof(amem))) {
956            CommaFmtULL(tpm, sizeof(tpm), amem, 'M');
957          }
958          else
959            *tpm = 0;
960          if (!Dos16MemAvail(&amem))
961            CommaFmtULL(tm, sizeof(tm), amem, 'M');
962          else
963            *tm = 0;
964          CommaFmtULL(tb, sizeof(tb), ffb.cbFile, 'M');
965          sprintf(s, " %s %s%s%s%s%s",
966                  GetPString(IDS_SWAPFILETEXT),
967                  tb,
968                  *tm ? GetPString(IDS_TREEMEMTEXT) : NullStr,
969                  tm, *tpm ? "/" : NullStr, tpm);
970          WinSetWindowText(hwndStatus2, s);
971        }
972        else
973          WinSetWindowText(hwndStatus2, NullStr);
974      }
975      else
976        WinSetWindowText(hwndStatus2, NullStr);
977    }
978    if (msg == UM_TIMER)
979      return 0;
980    break;
981
982  case WM_PRESPARAMCHANGED:
983    PresParamChanged(hwnd, "TreeCnr", mp1, mp2);
984    break;
985
986  case UM_FILESMENU:
987    {
988      PCNRITEM pci;
989      HWND menuHwnd = (HWND) 0;
990
991      pci = (PCNRITEM) CurrentRecord(hwnd);
992      if (pci && (INT) pci != -1) {
993        if (IsRoot(pci->pszFileName))
994          menuHwnd = CheckMenu(&TreeMenu, TREE_POPUP);
995        else {
996          menuHwnd = CheckMenu(&DirMenu, DIR_POPUP);
997//            WinEnableMenuItem(DirMenu,
998//                              IDM_TREE,
999//                              FALSE);
1000        }
1001        if (!(pci->attrFile & FILE_DIRECTORY))
1002          menuHwnd = CheckMenu(&FileMenu, FILE_POPUP);
1003      }
1004      return MRFROMLONG(menuHwnd);
1005    }
1006
1007  case UM_COMPARE:
1008    if (dcd && mp1 && mp2) {
1009
1010      COMPARE *cmp;
1011      CHAR *leftdir = (CHAR *) mp1, *rightdir = (CHAR *) mp2;
1012
1013      if (!IsFile(leftdir) && !IsFile(rightdir)) {
1014        cmp = xmallocz(sizeof(COMPARE), pszSrcFile, __LINE__);
1015        if (cmp) {
1016          cmp->size = sizeof(COMPARE);
1017          strcpy(cmp->leftdir, leftdir);
1018          strcpy(cmp->rightdir, rightdir);
1019          cmp->hwndParent = dcd->hwndParent;
1020          cmp->dcd.hwndParent = dcd->hwndParent;
1021          WinDlgBox(HWND_DESKTOP,
1022                    HWND_DESKTOP,
1023                    CompareDlgProc, FM3ModHandle, COMP_FRAME, MPFROMP(cmp));
1024        }
1025      }
1026    }
1027    return 0;
1028
1029  case UM_UPDATERECORDLIST:
1030    if (dcd && mp1)
1031      WinSendMsg(dcd->hwndObject, msg, mp1, mp2);
1032    return 0;
1033
1034  case UM_UPDATERECORD:
1035    if (dcd && mp1) {
1036
1037      CHAR *filename;
1038
1039      filename = mp1;
1040      if (filename)
1041        UpdateCnrRecord(hwnd, filename, TRUE, dcd);
1042    }
1043    return 0;
1044
1045  case WM_SETFOCUS:
1046    if (dcd && hwndStatus && mp2) {
1047      WinSendMsg(hwnd, UM_RESCAN, MPVOID, MPVOID);
1048      if (hwndMain)
1049        PostMsg(hwndMain, UM_ADVISEFOCUS, MPFROMLONG(dcd->hwndFrame), MPVOID);
1050    }
1051    break;
1052
1053  case UM_RESCAN:
1054    if (dcd && dcd->hwndFrame == WinQueryActiveWindow(dcd->hwndParent)) {
1055      /*
1056       * put name of our window on status line
1057       */
1058
1059      PCNRITEM pci = NULL;
1060      CHAR str[CCHMAXPATH + 6];
1061
1062      if (fAutoView && hwndMain) {
1063        pci = WinSendMsg(hwnd,
1064                         CM_QUERYRECORDEMPHASIS,
1065                         MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_CURSORED));
1066        if (pci && (INT) pci != -1 && fComments &&
1067            !(driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_SLOW))
1068          WinSendMsg(hwndMain, UM_LOADFILE, MPFROMP(pci->pszFileName), MPVOID);
1069        else
1070          WinSendMsg(hwndMain, UM_LOADFILE, MPVOID, MPVOID);
1071      }
1072      if (!fAutoView || !hwndMain)
1073        pci = (PCNRITEM) WinSendMsg(hwnd,
1074                                    CM_QUERYRECORDEMPHASIS,
1075                                    MPFROMLONG(CMA_FIRST),
1076                                    MPFROMSHORT(CRA_CURSORED));
1077      if ((INT) pci == -1)
1078        pci = NULL;
1079      if (pci) {
1080        if (*(ULONG *) realappname == FM3UL) {
1081          sprintf(str, "%s %s", GetPString(IDS_DTTEXT), pci->pszFileName);
1082          WinSetWindowText(dcd->hwndFrame, str);
1083          WinSetWindowText(WinWindowFromID(dcd->hwndFrame, FID_TITLEBAR),
1084                           str);
1085        }
1086        else
1087          WinSetWindowText(WinWindowFromID(dcd->hwndFrame,
1088                                           MAIN_STATUS), pci->pszFileName);
1089        if (fMoreButtons && hwndName) {
1090          WinSetWindowText(hwndName, pci->pszFileName);
1091          sprintf(str,
1092                  "%04u/%02u/%02u %02u:%02u:%02u",
1093                  pci->date.year,
1094                  pci->date.month,
1095                  pci->date.day,
1096                  pci->time.hours, pci->time.minutes, pci->time.seconds);
1097          WinSetWindowText(hwndDate, str);
1098          WinSetWindowText(hwndAttr, pci->pszDispAttr);
1099        }
1100      }
1101      PostMsg(dcd->hwndObject, UM_RESCAN2, MPFROMP(pci), MPVOID);
1102      if (hwndStatus2)
1103        PostMsg(hwnd, UM_TIMER, MPVOID, MPVOID);
1104    }
1105    return 0;
1106
1107  case UM_SETUP2:
1108    {
1109      PCNRITEM pci = (PCNRITEM) mp1;
1110
1111      if (pci)
1112        NotifyError(pci->pszFileName, (ULONG) mp2);
1113    }
1114    return 0;
1115
1116  case UM_SETUP:
1117    if (!dcd) {
1118      Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
1119      PostMsg(hwnd, WM_CLOSE, MPVOID, MPVOID);
1120      return 0;
1121    }
1122    else {
1123      if (!dcd->hwndObject) {
1124        /*
1125         * first time through -- set things up
1126         */
1127
1128        CNRINFO cnri;
1129
1130        RestorePresParams(hwnd, "TreeCnr");
1131        memset(&cnri, 0, sizeof(CNRINFO));
1132        cnri.cb = sizeof(CNRINFO);
1133        WinSendMsg(hwnd,
1134                   CM_QUERYCNRINFO,
1135                   MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
1136        cnri.cyLineSpacing = 0;
1137        cnri.cxTreeIndent = 12L;
1138        cnri.pSortRecord = (PVOID) SortTreeCnr;
1139        cnri.flWindowAttr &= (~(CV_NAME | CV_DETAIL | CV_TEXT));
1140        cnri.flWindowAttr |= (CV_TREE | CA_TREELINE | CV_ICON | CV_MINI);
1141        {
1142          ULONG size = sizeof(ULONG);
1143
1144          PrfQueryProfileData(fmprof,
1145                              appname,
1146                              "TreeflWindowAttr",
1147                              (PVOID) & cnri.flWindowAttr, &size);
1148          size = sizeof(MASK);
1149          *dcd->mask.prompt = 0;
1150          if (!*dcd->mask.szMask && !dcd->mask.attrFile) {
1151            if (PrfQueryProfileSize(fmprof,
1152                                    appname, "TreeFilter", &size) && size) {
1153              PrfQueryProfileData(fmprof,
1154                                  appname, "TreeFilter", &dcd->mask, &size);
1155              SetMask(NULL, &dcd->mask);
1156            }
1157            else
1158              dcd->mask.attrFile = (FILE_READONLY | FILE_NORMAL |
1159                                    FILE_ARCHIVED | FILE_DIRECTORY |
1160                                    FILE_HIDDEN | FILE_SYSTEM);
1161          }
1162          dcd->mask.attrFile |= FILE_DIRECTORY;
1163        }
1164        cnri.flWindowAttr &= (~(CA_MIXEDTARGETEMPH | CA_ORDEREDTARGETEMPH));
1165        cnri.flWindowAttr |= CV_FLOW;
1166        dcd->flWindowAttr = cnri.flWindowAttr;
1167        WinSendMsg(hwnd,
1168                   CM_SETCNRINFO,
1169                   MPFROMP(&cnri),
1170                   MPFROMLONG(CMA_FLWINDOWATTR | CMA_LINESPACING |
1171                              CMA_CXTREEINDENT | CMA_PSORTRECORD));
1172        if (_beginthread(MakeObjWin, NULL, 327680, (PVOID) dcd) == -1) {
1173          Runtime_Error(pszSrcFile, __LINE__,
1174                        GetPString(IDS_COULDNTSTARTTHREADTEXT));
1175          PostMsg(hwnd, WM_CLOSE, MPVOID, MPVOID);
1176          return 0;
1177        }
1178        else
1179          DosSleep(1L);
1180      }
1181    }
1182    return 0;
1183
1184  case WM_BUTTON3CLICK:
1185  case WM_CHORD:
1186    {
1187      PCNRITEM pci = NULL;
1188      QUERYRECFROMRECT pqr;
1189      NOTIFYRECORDENTER nr;
1190      BOOL tbool = fDCOpens;
1191      RECTL rectl;
1192      POINTL ptl;
1193
1194      shiftstate = (SHORT2FROMMP(mp2) & (KC_SHIFT | KC_ALT | KC_CTRL));
1195      if (msg == WM_CHORD) {
1196        if (!WinQueryPointerPos(HWND_DESKTOP, &ptl))
1197          break;
1198        WinMapWindowPoints(HWND_DESKTOP, hwnd, &ptl, 1L);
1199      }
1200      else {
1201        ptl.x = SHORT1FROMMP(mp1);
1202        ptl.y = SHORT2FROMMP(mp1);
1203      }
1204      memset(&rectl, 0, sizeof(rectl));
1205      memset(&pqr, 0, sizeof(pqr));
1206      pqr.cb = sizeof(pqr);
1207      pqr.rect.xLeft = ptl.x - 1;
1208      pqr.rect.xRight = ptl.x + 1;
1209      pqr.rect.yTop = ptl.y + 1;
1210      pqr.rect.yBottom = ptl.y - 1;
1211      pqr.fsSearch = CMA_PARTIAL;
1212      pci = (PCNRITEM) WinSendMsg(hwnd,
1213                                  CM_QUERYRECORDFROMRECT,
1214                                  MPFROMLONG(CMA_FIRST), MPFROMP(&pqr));
1215      if (!pci || (INT) pci == -1)
1216        break; //Probable B3 click on white space Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
1217      else {
1218        memset(&nr, 0, sizeof(nr));
1219        nr.hwndCnr = hwnd;
1220        nr.pRecord = (PRECORDCORE) pci;
1221        fDCOpens = TRUE;
1222        WinSendMsg(hwnd,
1223                   WM_CONTROL,
1224                   MPFROM2SHORT(WinQueryWindowUShort(hwnd,
1225                                                     QWS_ID),
1226                                CN_ENTER), MPFROMP(&nr));
1227        PostMsg(hwnd, UM_RESTOREDC, MPFROMLONG(tbool), MPVOID);
1228      }
1229    }
1230    break;
1231
1232  case UM_RESTOREDC:
1233    fDCOpens = (BOOL) mp1;
1234    return 0;
1235
1236  case WM_CONTROL:
1237    DosError(FERR_DISABLEHARDERR);
1238    if (dcd) {
1239      switch (SHORT2FROMMP(mp1)) {
1240      case CN_BEGINEDIT:
1241      case CN_REALLOCPSZ:
1242      case CN_ENDEDIT:
1243        {
1244          MRESULT mre;
1245
1246          mre = CnrDirectEdit(hwnd, msg, mp1, mp2);
1247          if (mre != (MRESULT) - 1)
1248            return mre;
1249        }
1250        break;
1251
1252      case CN_DRAGLEAVE:
1253        if (mp2) {
1254
1255          PDRAGINFO pDInfo;
1256
1257          // fixme to know why - seems superfluous
1258          pDInfo = ((PCNRDRAGINFO) mp2)->pDragInfo;
1259          DrgAccessDraginfo(pDInfo);
1260          DrgFreeDraginfo(pDInfo);
1261        }
1262        return 0;
1263
1264      case CN_DRAGAFTER:
1265      case CN_DRAGOVER:
1266        if (mp2) {
1267
1268          PDRAGITEM pDItem;
1269          PDRAGINFO pDInfo;
1270          PCNRITEM pci;
1271          USHORT uso;
1272
1273          pDInfo = ((PCNRDRAGINFO) mp2)->pDragInfo;
1274          if (!DrgAccessDraginfo(pDInfo)) {
1275            Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
1276                      "DrgAccessDraginfo");
1277            return (MRFROM2SHORT(DOR_NODROP, 0));       /* Drop not valid */
1278          }
1279          pci = (PCNRITEM) ((PCNRDRAGINFO) mp2)->pRecord;
1280          if ((INT) pci == -1)
1281            pci = NULL;
1282          if (pci && (pci->flags & (RECFLAGS_ENV | RECFLAGS_NODROP))) {
1283            DrgFreeDraginfo(pDInfo);
1284            return MRFROM2SHORT(DOR_NODROP, 0);
1285          }
1286          if (!WinIsWindowEnabled(dcd->hwndFrame)) {
1287            DrgFreeDraginfo(pDInfo);
1288            return MRFROM2SHORT(DOR_NODROP, 0);
1289          }
1290          if (pci) {
1291            uso = pDInfo->usOperation;
1292            if (uso == DO_DEFAULT)
1293              uso = (fCopyDefault) ? DO_COPY : DO_MOVE;
1294            if (!(pci->attrFile & FILE_DIRECTORY)) {
1295              if (uso != DO_LINK && uso != DO_COPY && uso != DO_MOVE) {
1296                DrgFreeDraginfo(pDInfo);
1297                return (MRFROM2SHORT(DOR_NODROP, 0));
1298              }
1299              if (uso != DO_LINK &&
1300                  !(driveflags[toupper(*pci->pszFileName) - 'A'] &
1301                    DRIVE_NOTWRITEABLE)) {
1302
1303                ARC_TYPE *info;
1304
1305                if (!fQuickArcFind &&
1306                    !(driveflags[toupper(*pci->pszFileName) - 'A'] &
1307                      DRIVE_SLOW))
1308                  info = find_type(pci->pszFileName, NULL);
1309                else
1310                  info = quick_find_type(pci->pszFileName, NULL);
1311                if (!info || ((uso == DO_MOVE && !info->move) ||
1312                              (uso == DO_COPY && !info->create))) {
1313                  DrgFreeDraginfo(pDInfo);
1314                  return (MRFROM2SHORT(DOR_NODROP, 0));
1315                }
1316              }
1317            }
1318          }
1319          pDItem = DrgQueryDragitemPtr(pDInfo,  /* Access DRAGITEM */
1320                                       0);      /* Index to DRAGITEM */
1321          if (DrgVerifyRMF(pDItem,      /* Check valid rendering */
1322                           DRM_OS2FILE, /* mechanisms and data */
1323                           NULL) || DrgVerifyRMF(pDItem, DRM_FM2ARCMEMBER, DRF_FM2ARCHIVE)) {   /* formats */
1324            DrgFreeDraginfo(pDInfo);    /* Free DRAGINFO */
1325            if (!pci || (INT) pci == -1)
1326              return MRFROM2SHORT(DOR_DROP, DO_MOVE);
1327            if (driveflags[toupper(*pci->pszFileName) - 'A'] &
1328                DRIVE_NOTWRITEABLE)
1329              return MRFROM2SHORT(DOR_DROP, DO_LINK);
1330            if (toupper(*pci->pszFileName) < 'C')
1331              return MRFROM2SHORT(DOR_DROP, DO_COPY);
1332            return MRFROM2SHORT(DOR_DROP,       /* Return okay to drop */
1333                                ((fCopyDefault) ? DO_COPY : DO_MOVE));
1334          }
1335          DrgFreeDraginfo(pDInfo);      /* Free DRAGINFO */
1336        }
1337        return MRFROM2SHORT(DOR_NODROP, 0);     /* Drop not valid */
1338
1339      case CN_INITDRAG:
1340        {
1341          PCNRDRAGINIT pcd = (PCNRDRAGINIT) mp2;
1342          PCNRITEM pci;
1343
1344          if (!pcd) {
1345            Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
1346            break;
1347          }
1348          else {
1349            pci = (PCNRITEM) pcd->pRecord;
1350            if (!pci || (INT) pci == -1) {
1351              Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
1352              break;
1353            }
1354            if (pci->flags & (RECFLAGS_ENV | RECFLAGS_NODRAG)) {
1355              Runtime_Error(pszSrcFile, __LINE__, "drag not allowed");
1356              break;
1357            }
1358            if (hwndStatus2) {
1359              WinSetWindowText(hwndStatus2, (IsRoot(pci->pszFileName)) ?
1360                               GetPString(IDS_DRAGROOTTEXT) :
1361                               (pci->attrFile & FILE_DIRECTORY) ?
1362                               GetPString(IDS_DRAGDIRTEXT) :
1363                               GetPString(IDS_DRAGFILETEXT));
1364            }
1365            DoFileDrag(hwnd, dcd->hwndObject, mp2, NULL, NULL, TRUE);
1366            if (hwndStatus2) {
1367              PostMsg(hwnd, UM_RESCAN, MPVOID, MPVOID);
1368            }
1369          }
1370        }
1371        return 0;
1372
1373      case CN_DROP:
1374        {
1375          LISTINFO *li;
1376          ULONG action = UM_ACTION;
1377
1378          li = DoFileDrop(hwnd, NULL, TRUE, mp1, mp2);
1379          CheckPmDrgLimit(((PCNRDRAGINFO)mp2)->pDragInfo);
1380          if (li) {
1381            if (!*li->targetpath) {
1382              if (li->list[0])
1383                PMMkDir(dcd->hwndParent, li->list[0], FALSE);
1384              FreeListInfo(li);
1385              return 0;
1386            }
1387            if (li->list && li->list[0] && IsRoot(li->list[0]))
1388              li->type = DO_LINK;
1389            else if (fDragndropDlg && (!*li->arcname || !li->info)) {
1390
1391              CHECKLIST cl;
1392
1393              memset(&cl, 0, sizeof(cl));
1394              cl.size = sizeof(cl);
1395              cl.flags = li->type;
1396              cl.list = li->list;
1397              cl.cmd = li->type;
1398              cl.prompt = li->targetpath;
1399              li->type = WinDlgBox(HWND_DESKTOP,
1400                                   dcd->hwndParent,
1401                                   DropListProc,
1402                                   FM3ModHandle, DND_FRAME, MPFROMP(&cl));
1403              if (li->type == DID_ERROR)
1404                  Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,
1405                            "Drag & Drop Dialog");
1406              if (!li->type) {
1407                FreeListInfo(li);
1408                return 0;
1409              }
1410              li->list = cl.list;
1411              if (!li->list || !li->list[0]) {
1412                FreeListInfo(li);
1413                return 0;
1414              }
1415            }
1416            switch (li->type) {
1417            case DO_LINK:
1418              if (fLinkSetsIcon) {
1419                li->type = IDM_SETICON;
1420                action = UM_MASSACTION;
1421              }
1422              else
1423                li->type = IDM_COMPARE;
1424              break;
1425            case DND_EXTRACT:
1426              if (*li->targetpath && !IsFile(li->targetpath))
1427                li->type = IDM_EXTRACT;
1428              break;
1429            case DND_MOVE:
1430              li->type = IDM_MOVE;
1431              if (*li->targetpath && IsFile(li->targetpath) == 1) {
1432                action = UM_MASSACTION;
1433                li->type = IDM_ARCHIVEM;
1434              }
1435              break;
1436            case DND_WILDMOVE:
1437              li->type = IDM_WILDMOVE;
1438              if (*li->targetpath && IsFile(li->targetpath) == 1) {
1439                action = UM_MASSACTION;
1440                li->type = IDM_ARCHIVEM;
1441              }
1442              break;
1443            case DND_OBJECT:
1444              li->type = IDM_OBJECT;
1445              action = UM_MASSACTION;
1446              break;
1447            case DND_SHADOW:
1448              li->type = IDM_SHADOW;
1449              action = UM_MASSACTION;
1450              break;
1451            case DND_COMPARE:
1452              li->type = IDM_COMPARE;
1453              break;
1454            case DND_SETICON:
1455              action = UM_MASSACTION;
1456              li->type = IDM_SETICON;
1457              break;
1458            case DND_COPY:
1459              li->type = IDM_COPY;
1460              if (*li->targetpath && IsFile(li->targetpath) == 1) {
1461                action = UM_MASSACTION;
1462                li->type = IDM_ARCHIVE;
1463              }
1464              break;
1465            case DND_WILDCOPY:
1466              li->type = IDM_WILDCOPY;
1467              if (*li->targetpath && IsFile(li->targetpath) == 1) {
1468                action = UM_MASSACTION;
1469                li->type = IDM_ARCHIVE;
1470              }
1471              break;
1472            default:
1473              if (*li->arcname && li->info) {
1474                action = UM_MASSACTION;
1475                li->type = (li->type == DO_MOVE) ?
1476                  IDM_FAKEEXTRACTM : IDM_FAKEEXTRACT;
1477              }
1478              else if (*li->targetpath && IsFile(li->targetpath) == 1) {
1479                action = UM_MASSACTION;
1480                li->type = (li->type == DO_MOVE) ? IDM_ARCHIVEM : IDM_ARCHIVE;
1481              }
1482              else
1483                li->type = (li->type == DO_MOVE) ? IDM_MOVE : IDM_COPY;
1484              break;
1485            }
1486            if (!li->list || !li->list[0])
1487              FreeListInfo(li);
1488            else if (!PostMsg(dcd->hwndObject, action, MPFROMP(li), MPVOID))
1489              FreeListInfo(li);
1490            else {
1491
1492              USHORT usop = 0;
1493
1494              switch (li->type) {
1495              case IDM_COPY:
1496              case IDM_WILDCOPY:
1497                usop = DO_COPY;
1498                break;
1499              case IDM_MOVE:
1500              case IDM_WILDMOVE:
1501              case IDM_ARCHIVEM:
1502                usop = DO_MOVE;
1503                break;
1504              }
1505              if (usop)
1506                return MRFROM2SHORT(DOR_DROP, usop);
1507            }
1508          }
1509        }
1510        return 0;
1511
1512      case CN_EMPHASIS:
1513        if (!fDummy) {
1514
1515          PNOTIFYRECORDEMPHASIS pre = mp2;
1516
1517          if (pre->fEmphasisMask & CRA_SELECTED) {
1518            if (pre->pRecord->flRecordAttr & CRA_SELECTED) {
1519              if (((PCNRITEM) (pre->pRecord))->attrFile & FILE_DIRECTORY) {
1520                PostMsg(hwnd, UM_RESCAN, MPVOID, MPVOID);
1521                if (fFollowTree &&
1522                    !(driveflags
1523                      [toupper(*((PCNRITEM) pre->pRecord)->pszFileName) -
1524                       'A'] & DRIVE_INVALID)) {
1525                  if (!LastDir && !ParentIsDesktop(hwnd, dcd->hwndParent))
1526                    LastDir = FindDirCnr(dcd->hwndParent);
1527                  if (LastDir) {
1528
1529                    NOTIFYRECORDENTER pri;
1530                    BOOL tbool = fDCOpens;
1531
1532                    fDCOpens = FALSE;
1533                    memset(&pri, 0, sizeof(pri));
1534                    pri.hwndCnr = hwnd;
1535                    pri.fKey = FALSE;
1536                    pri.pRecord = pre->pRecord;
1537                    WinSendMsg(hwnd,
1538                               WM_CONTROL,
1539                               MPFROM2SHORT(SHORT1FROMMP(mp1),
1540                                            CN_ENTER), MPFROMP(&pri));
1541                    fDCOpens = tbool;
1542                  }
1543                }
1544                if (*(ULONG *) realappname != FM3UL)
1545                  WinSetWindowText(WinWindowFromID(dcd->hwndFrame,
1546                                                   MAIN_STATUS),
1547                                   ((PCNRITEM) (pre->pRecord))->pszFileName);
1548              }
1549            }
1550          }
1551        }
1552        break;
1553
1554      case CN_CONTEXTMENU:
1555        {
1556          PCNRITEM pci = (PCNRITEM) mp2;
1557          BOOL wasFollowing;
1558
1559          DosEnterCritSec();
1560          wasFollowing = fFollowTree;
1561          fFollowTree = FALSE;
1562          DosExitCritSec();
1563          if (pci && (INT) pci != -1 && !(pci->flags & RECFLAGS_ENV)) {
1564            WinSendMsg(hwnd,
1565                       CM_SETRECORDEMPHASIS,
1566                       MPFROMP(pci), MPFROM2SHORT(TRUE, CRA_CURSORED));
1567            MarkAll(hwnd, FALSE, FALSE, TRUE);
1568            if (!(pci->attrFile & FILE_DIRECTORY))
1569              dcd->hwndLastMenu = CheckMenu(&FileMenu, FILE_POPUP);
1570            else if (!IsRoot(pci->pszFileName))
1571              dcd->hwndLastMenu = CheckMenu(&DirMenu, DIR_POPUP);
1572            else
1573              dcd->hwndLastMenu = CheckMenu(&TreeMenu, TREE_POPUP);
1574          }
1575          else {
1576            dcd->hwndLastMenu = CheckMenu(&TreeCnrMenu, TREECNR_POPUP);
1577            if (dcd->hwndLastMenu && !dcd->cnremphasized) {
1578              WinSendMsg(hwnd, CM_SETRECORDEMPHASIS, MPVOID,
1579                         MPFROM2SHORT(TRUE, CRA_SOURCE));
1580              dcd->cnremphasized = TRUE;
1581            }
1582          }
1583          if (dcd->hwndLastMenu) {
1584            if (dcd->hwndLastMenu == DirMenu)
1585              WinEnableMenuItem(DirMenu, IDM_TREE, FALSE);
1586            if (dcd->hwndLastMenu == TreeCnrMenu) {
1587              if (dcd->flWindowAttr & CV_MINI)
1588                WinCheckMenuItem(dcd->hwndLastMenu, IDM_MINIICONS, TRUE);
1589            }
1590            if (!PopupMenu(hwnd, hwnd, dcd->hwndLastMenu)) {
1591              if (dcd->cnremphasized) {
1592                WinSendMsg(hwnd, CM_SETRECORDEMPHASIS, MPVOID,
1593                           MPFROM2SHORT(FALSE, CRA_SOURCE));
1594                dcd->cnremphasized = FALSE;
1595              }
1596              if (dcd->hwndLastMenu != TreeCnrMenu)
1597                MarkAll(hwnd, TRUE, FALSE, TRUE);
1598            }
1599          }
1600          DosEnterCritSec();
1601          fFollowTree = wasFollowing;
1602          DosExitCritSec();
1603        }
1604        break;
1605
1606      case CN_ENTER:
1607        if (mp2) {
1608          PCNRITEM pci = (PCNRITEM) ((PNOTIFYRECORDENTER) mp2)->pRecord;
1609
1610          PostMsg(hwnd, UM_ENTER, MPFROMP(pci), MPVOID);
1611        }
1612        break;
1613
1614      case CN_COLLAPSETREE:
1615      case CN_EXPANDTREE:
1616        {
1617          PCNRITEM pci = (PCNRITEM) mp2;
1618
1619          if (pci && (INT) pci != -1 && !(pci->flags & RECFLAGS_ENV)) {
1620            if (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE) {
1621
1622              struct
1623              {
1624                ULONG serial;
1625                CHAR volumelength;
1626                CHAR volumelabel[CCHMAXPATH];
1627              }
1628              volser;
1629
1630              memset(&volser, 0, sizeof(volser));
1631              DosError(FERR_DISABLEHARDERR);
1632              if (!DosQueryFSInfo(toupper(*pci->pszFileName) - '@',
1633                                  FSIL_VOLSER, &volser,
1634                                  (ULONG) sizeof(volser))) {
1635                if (SHORT2FROMMP(mp1) == CN_COLLAPSETREE &&
1636                    !volser.serial ||
1637                    driveserial[toupper(*pci->pszFileName) - 'A'] !=
1638                    volser.serial)
1639                  UnFlesh(hwnd, pci);
1640                if (SHORT2FROMMP(mp1) != CN_COLLAPSETREE ||
1641                    (!volser.serial ||
1642                     driveserial[toupper(*pci->pszFileName) - 'A'] !=
1643                     volser.serial)) {
1644                  if (Flesh(hwnd, pci) &&
1645                      SHORT2FROMMP(mp1) == CN_EXPANDTREE &&
1646                      !dcd->suspendview && fTopDir)
1647                    PostMsg(hwnd, UM_TOPDIR, MPFROMP(pci), MPVOID);
1648                }
1649                driveserial[toupper(*pci->pszFileName) - 'A'] = volser.serial;
1650              }
1651              else {
1652                driveserial[toupper(*pci->pszFileName) - 'A'] = -1;
1653                UnFlesh(hwnd, pci);
1654                PostMsg(hwnd, UM_RESCAN, MPVOID, MPVOID);
1655                DosBeep(250, 100);
1656              }
1657            }
1658            else if (SHORT2FROMMP(mp1) == CN_EXPANDTREE) {
1659              if (Flesh(hwnd, pci) && !dcd->suspendview && fTopDir)
1660                PostMsg(hwnd, UM_TOPDIR, MPFROMP(pci), MPVOID);
1661            }
1662            if (SHORT2FROMMP(mp1) == CN_EXPANDTREE && !dcd->suspendview)
1663              WinSendMsg(hwnd, UM_FILTER, MPVOID, MPVOID);
1664          }
1665        }
1666        break;
1667      }                                 // switch WM_CONTROL
1668    }
1669    return 0;
1670
1671  case UM_ACTION:
1672    if (mp1) {
1673
1674      LISTINFO *li = mp1;
1675      ULONG action = (ULONG) mp2;
1676
1677      if (!li->list || !li->list[0] ||
1678          !PostMsg(dcd->hwndObject, action, MPFROMP(li), MPVOID))
1679        FreeListInfo(li);
1680    }
1681    return 0;
1682
1683  case UM_SHOWME:
1684    if (mp1 && dcd) {
1685      CHAR *dir = xstrdup((CHAR *) mp1, pszSrcFile, __LINE__);
1686
1687      if (dir) {
1688        if (!PostMsg(dcd->hwndObject, UM_SHOWME, MPFROMP(dir), MPVOID))
1689          free(dir);
1690      }
1691    }
1692    return 0;
1693
1694  case UM_TOPDIR:
1695    if (mp1) {
1696
1697      PCNRITEM pci = (PCNRITEM) mp1;
1698
1699      ShowCnrRecord(hwnd, (PMINIRECORDCORE) pci);
1700    }
1701    return 0;
1702
1703  case UM_ENTER:
1704    {
1705      FILEFINDBUF3 ffb;
1706      HDIR hDir = HDIR_CREATE;
1707      ULONG nm = 1;
1708      APIRET status;
1709      BOOL IsOk = FALSE;
1710      ULONG ulDriveNum, ulDriveMap;
1711      PCNRITEM pciP, pciL, pci;
1712      ULONG fl = SWP_ACTIVATE;
1713
1714      if (fFollowTree)
1715        fl = 0;
1716      SetShiftState();
1717      pci = (PCNRITEM) mp1;
1718      if (pci &&
1719          (INT) pci != -1 &&
1720          !(pci->rc.flRecordAttr & CRA_INUSE) &&
1721          !(pci->flags & RECFLAGS_ENV) && IsFullName(pci->pszFileName)) {
1722        if (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_INVALID) {
1723          DosBeep(50, 100);
1724          if (hwndStatus)
1725            WinSetWindowText(hwndStatus, GetPString(IDS_RESCANSUGTEXT));
1726          return 0;
1727        }
1728        DosError(FERR_DISABLEHARDERR);
1729        if (!DosQCurDisk(&ulDriveNum, &ulDriveMap)) {
1730          if (!(ulDriveMap & 1L << (toupper(*pci->pszFileName) - 'A'))) {
1731            pciL = pciP = pci;
1732            for (;;) {
1733              pciP = WinSendMsg(hwnd,
1734                                CM_QUERYRECORD,
1735                                MPFROMP(pciL),
1736                                MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
1737              if (pciP && (INT) pciP != -1)
1738                pciL = pciP;
1739              else {
1740                pciP = pciL;
1741                break;
1742              }
1743            } // for
1744            RemoveCnrItems(hwnd, pciP, 1, CMA_FREE | CMA_INVALIDATE);
1745            return 0;
1746          }
1747        }
1748        if (driveflags[toupper(*pci->pszFileName) - 'A'] &
1749            (DRIVE_REMOVABLE | DRIVE_NOPRESCAN)) {
1750
1751          struct
1752          {
1753            ULONG serial;
1754            CHAR volumelength;
1755            CHAR volumelabel[CCHMAXPATH];
1756          }
1757          volser;
1758
1759          pciL = pciP = pci;
1760          for (;;) {
1761            pciP = WinSendMsg(hwnd,
1762                              CM_QUERYRECORD,
1763                              MPFROMP(pciL),
1764                              MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
1765            if (pciP && (INT) pciP != -1)
1766              pciL = pciP;
1767            else {
1768              pciP = pciL;
1769              break;
1770            }
1771          }
1772          if ((driveflags[toupper(*pci->pszFileName) - 'A'] &
1773               DRIVE_NOPRESCAN) ||
1774              (toupper(*pci->pszFileName) > 'B' &&
1775               !(driveflags[toupper(*pci->pszFileName) - 'A'] &
1776                 DRIVE_CDROM))) {
1777
1778            INT removable, x = (INT) (toupper(*pci->pszFileName) - 'A');
1779            ULONG drvtype;
1780            CHAR FileSystem[CCHMAXPATH];
1781
1782            DosError(FERR_DISABLEHARDERR);
1783            removable = CheckDrive(toupper(*pciP->pszFileName),
1784                                   FileSystem, &drvtype);
1785            if (removable != -1) {
1786              driveflags[x] &= (DRIVE_IGNORE | DRIVE_NOPRESCAN |
1787                                DRIVE_NOLOADICONS | DRIVE_NOLOADSUBJS |
1788                                DRIVE_NOLOADLONGS | DRIVE_INCLUDEFILES |
1789                                DRIVE_SLOW | DRIVE_NOSTATS);
1790
1791              if (removable == 1)
1792                driveflags[x] |= DRIVE_REMOVABLE;
1793              if (drvtype & DRIVE_REMOTE)
1794                driveflags[x] |= DRIVE_REMOTE;
1795              if (!strcmp(FileSystem, CBSIFS)) {
1796                driveflags[x] |= DRIVE_ZIPSTREAM;
1797                driveflags[x] &= (~DRIVE_REMOTE);
1798              }
1799              if(!strcmp(FileSystem,NDFS32)) {
1800                driveflags[x] |= DRIVE_VIRTUAL;
1801                driveflags[x] &= (~DRIVE_REMOTE);
1802              }
1803              if(!strcmp(FileSystem,RAMFS)) {
1804                driveflags[x] |= DRIVE_RAMDISK;
1805                driveflags[x] &= (~DRIVE_REMOTE);
1806              }
1807              if (!strcmp(FileSystem, CDFS) || !strcmp(FileSystem, ISOFS))
1808                driveflags[x] |= (DRIVE_REMOVABLE |
1809                                  DRIVE_NOTWRITEABLE | DRIVE_CDROM);
1810              if(!strcmp(FileSystem,NTFS))
1811                driveflags[x] |= DRIVE_NOTWRITEABLE;
1812              if (strcmp(FileSystem, HPFS) &&
1813                  strcmp(FileSystem, JFS) &&
1814                  strcmp(FileSystem, CDFS) &&
1815                  strcmp(FileSystem, ISOFS) &&
1816                  strcmp(FileSystem, RAMFS) &&
1817                  strcmp(FileSystem, FAT32) &&
1818                  strcmp(FileSystem, NDFS32) &&
1819                  strcmp(FileSystem, NTFS) &&
1820                  strcmp(FileSystem, HPFS386)) {
1821                driveflags[x] |= DRIVE_NOLONGNAMES;
1822              }
1823              SelectDriveIcon(pciP);
1824              WinSendMsg(hwnd,
1825                         CM_INVALIDATERECORD,
1826                         MPFROMP(&pciP),
1827                         MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
1828              if (hwndMain)
1829                PostMsg(hwndMain, UM_BUILDDRIVEBAR, MPVOID, MPVOID);
1830            }
1831          }
1832          memset(&volser, 0, sizeof(volser));
1833          DosError(FERR_DISABLEHARDERR);
1834          status = DosQueryFSInfo(toupper(*pci->pszFileName) - '@',
1835                                  FSIL_VOLSER, &volser,
1836                                  (ULONG) sizeof(volser));
1837          if (!status) {
1838            if (!volser.serial ||
1839                driveserial[toupper(*pci->pszFileName) - 'A'] !=
1840                volser.serial) {
1841              UnFlesh(hwnd, pciP);
1842              Flesh(hwnd, pciP);
1843              driveserial[toupper(*pci->pszFileName) - 'A'] = volser.serial;
1844            }
1845            pciL = WinSendMsg(hwnd,
1846                              CM_QUERYRECORD,
1847                              MPFROMP(pciP),
1848                              MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
1849            if (!pciL)
1850              Flesh(hwnd, pciP);
1851          }
1852          else {
1853            driveserial[toupper(*pci->pszFileName) - 'A'] = -1;
1854            UnFlesh(hwnd, pci);
1855            PostMsg(hwnd, UM_RESCAN, MPVOID, MPVOID);
1856            PostMsg(hwnd, UM_SETUP2, MPFROMP(pci), MPFROMLONG(status));
1857            return 0;
1858          }
1859        }
1860        status = 0;
1861        IsOk = (IsRoot(pci->pszFileName) &&
1862                IsValidDrive(toupper(*pci->pszFileName)));
1863        if (!IsOk) {
1864          DosError(FERR_DISABLEHARDERR);
1865          status = DosFindFirst(pci->pszFileName, &hDir,
1866                                FILE_NORMAL | FILE_DIRECTORY |
1867                                FILE_ARCHIVED | FILE_READONLY |
1868                                FILE_HIDDEN | FILE_SYSTEM,
1869                                &ffb, sizeof(ffb), &nm, FIL_STANDARD);
1870          priority_bumped();
1871        }
1872        if (!status) {
1873          if (!IsOk)
1874            DosFindClose(hDir);
1875          if (IsOk || (ffb.attrFile & FILE_DIRECTORY)) {
1876            if ((shiftstate & (KC_CTRL | KC_ALT)) == (KC_CTRL | KC_ALT)) {
1877              PostMsg(hwnd,
1878                      WM_COMMAND, MPFROM2SHORT(IDM_SHOWALLFILES, 0), MPVOID);
1879              return 0;
1880            }
1881            if ((shiftstate & (KC_CTRL | KC_SHIFT)) == (KC_CTRL | KC_SHIFT)) {
1882              OpenObject(pci->pszFileName, Settings, dcd->hwndFrame);
1883              return 0;
1884            }
1885            if (!(shiftstate & (KC_CTRL | KC_SHIFT))) {
1886              if (!ParentIsDesktop(hwnd, dcd->hwndParent)) {
1887                if (FindDirCnrByName(pci->pszFileName, TRUE))
1888                  return 0;
1889              }
1890            }
1891            if ((shiftstate & KC_CTRL) ||
1892                (!(shiftstate & KC_SHIFT) &&
1893                 ParentIsDesktop(hwnd, dcd->hwndParent) && fVTreeOpensWPS)) {
1894
1895              ULONG size = sizeof(ULONG), flWindowAttr = CV_ICON;
1896              CHAR s[33];
1897
1898              strcpy(s, "ICON");
1899              PrfQueryProfileData(fmprof,
1900                                  appname,
1901                                  "DirflWindowAttr",
1902                                  (PVOID) & flWindowAttr, &size);
1903              if (flWindowAttr & CV_DETAIL) {
1904                if (IsRoot(pci->pszFileName))
1905                  strcpy(s, "TREE");
1906                else
1907                  strcpy(s, "DETAILS");
1908              }
1909              OpenObject(pci->pszFileName, s, dcd->hwndFrame);
1910              return 0;
1911            }
1912            if (!ParentIsDesktop(hwnd, dcd->hwndParent) &&
1913                !fDCOpens && !LastDir && !(shiftstate & KC_SHIFT))
1914              LastDir = FindDirCnr(dcd->hwndParent);
1915            if (LastDir && !fDCOpens && !(shiftstate & KC_SHIFT)) {
1916              WinSendMsg(LastDir,
1917                         UM_SETDIR, MPFROMP(pci->pszFileName), MPVOID);
1918              WinSetWindowPos(WinQueryWindow(WinQueryWindow(LastDir,
1919                                                            QW_PARENT),
1920                                             QW_PARENT),
1921                              HWND_TOP, 0, 0, 0, 0, SWP_ZORDER | fl);
1922            }
1923            else
1924              OpenDirCnr(hwnd,
1925                         dcd->hwndParent,
1926                         dcd->hwndFrame, FALSE, pci->pszFileName);
1927          }
1928          else {
1929            if (!(driveflags[toupper(*pci->pszFileName) - 'A'] &
1930                  DRIVE_INCLUDEFILES))
1931              RemoveCnrItems(hwnd, pci, 1, CMA_FREE | CMA_INVALIDATE);
1932            else {
1933
1934              SWP swp;
1935
1936              WinQueryWindowPos(dcd->hwndFrame, &swp);
1937              DefaultViewKeys(hwnd,
1938                              dcd->hwndFrame,
1939                              dcd->hwndParent, &swp, pci->pszFileName);
1940            }
1941          }
1942        }
1943        else {
1944          if (!IsRoot(pci->pszFileName)) {
1945            NotifyError(pci->pszFileName, status);
1946            RemoveCnrItems(hwnd, pci, 1, CMA_FREE | CMA_INVALIDATE);
1947          }
1948        }
1949      }
1950      else if (!pci)
1951        PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(IDM_MKDIR, 0), MPVOID);
1952      if (fFollowTree)
1953        WinSetFocus(HWND_DESKTOP, hwnd);
1954    }
1955    return 0;
1956
1957  case WM_MENUEND:
1958    if (dcd) {
1959
1960      HWND hwndMenu = (HWND) mp2;
1961
1962      if (hwndMenu == TreeCnrMenu || hwndMenu == TreeMenu ||
1963          hwndMenu == DirMenu) {
1964        MarkAll(hwnd, TRUE, FALSE, TRUE);
1965        if (dcd->cnremphasized) {
1966          WinSendMsg(hwnd,
1967                     CM_SETRECORDEMPHASIS,
1968                     MPVOID, MPFROM2SHORT(FALSE, CRA_SOURCE));
1969          dcd->cnremphasized = FALSE;
1970        }
1971      }
1972    }
1973    break;
1974
1975  case UM_OPENWINDOWFORME:
1976    if (dcd) {
1977      if (mp1 && !IsFile((CHAR *) mp1))
1978        OpenDirCnr(hwnd, dcd->hwndParent, dcd->hwndFrame, FALSE, (char *)mp1);
1979    }
1980    return 0;
1981
1982  case MM_PORTHOLEINIT:
1983    if (dcd) {
1984      switch (SHORT1FROMMP(mp1)) {
1985      case 0:
1986      case 1:
1987        {
1988          ULONG wmsg;
1989
1990          wmsg = ((SHORT1FROMMP(mp1) == 0) ? UM_FILESMENU : UM_VIEWSMENU);
1991          PortholeInit((HWND) WinSendMsg(dcd->hwndClient,
1992                                         wmsg, MPVOID, MPVOID), mp1, mp2);
1993        }
1994        break;
1995      }
1996    }
1997    break;
1998
1999  case UM_INITMENU:
2000  case WM_INITMENU:
2001    if (dcd) {
2002      switch (SHORT1FROMMP(mp1)) {
2003      case IDM_FILESMENU:
2004        {
2005          PCNRITEM pci;
2006
2007          pci = (PCNRITEM) CurrentRecord(hwnd);
2008          if (pci && (INT) pci != -1) {
2009            BOOL rdy;
2010            BOOL writeable;
2011            BOOL removable;
2012            BOOL remote;
2013            BOOL underenv;
2014            CHAR chDrvU;
2015            CHAR szDrv[CCHMAXPATH];
2016
2017            strcpy(szDrv, pci->pszFileName);
2018            chDrvU = *pci->pszFileName;
2019            chDrvU = toupper(chDrvU);
2020            MakeValidDir(szDrv);
2021            rdy = *szDrv == chDrvU;     // Drive not ready if MakeValidDir changes drive letter
2022            removable = rdy
2023              && (driveflags[chDrvU - 'A'] & DRIVE_REMOVABLE) != 0;
2024            writeable = rdy
2025              && !(driveflags[chDrvU - 'A'] & DRIVE_NOTWRITEABLE);
2026            remote = rdy && (driveflags[chDrvU - 'A'] & (DRIVE_REMOTE || DRIVE_VIRTUAL)) != 0;
2027            underenv = (pci->flags & RECFLAGS_UNDERENV) != 0;
2028
2029            WinEnableMenuItem((HWND) mp2, IDM_INFO, rdy);
2030
2031            WinEnableMenuItem((HWND) mp2, IDM_ATTRS, writeable);
2032            WinEnableMenuItem((HWND) mp2, IDM_EAS, writeable);
2033            WinEnableMenuItem((HWND) mp2, IDM_SUBJECT, writeable);
2034            WinEnableMenuItem((HWND) mp2, IDM_DRVFLAGS, 1);     // fixme to allow if not ready
2035
2036            WinEnableMenuItem((HWND) mp2, IDM_ARCHIVE, rdy);
2037
2038            WinEnableMenuItem((HWND) mp2, IDM_UPDATE, !underenv);
2039            WinEnableMenuItem((HWND) mp2, IDM_EXPANDSUBMENU, !underenv);
2040            WinEnableMenuItem((HWND) mp2, IDM_EXPAND, !underenv);
2041            WinEnableMenuItem((HWND) mp2, IDM_COLLAPSE, !underenv);
2042
2043            WinEnableMenuItem((HWND) mp2, IDM_SIZES, rdy);
2044            WinEnableMenuItem((HWND) mp2, IDM_MKDIR, writeable);
2045            WinEnableMenuItem((HWND) mp2, IDM_SHOWALLFILES, rdy);
2046            WinEnableMenuItem((HWND) mp2, IDM_UNDELETE, writeable);
2047
2048            WinEnableMenuItem((HWND) mp2, IDM_CHKDSK, writeable && !remote);
2049            WinEnableMenuItem((HWND) mp2, IDM_FORMAT, writeable && !remote);
2050            WinEnableMenuItem((HWND) mp2, IDM_OPTIMIZE, writeable && !remote);
2051            WinEnableMenuItem((HWND) mp2, IDM_PARTITIONSMENU, !remote);
2052
2053            WinEnableMenuItem((HWND) mp2, IDM_DETACH, remote);
2054
2055            WinEnableMenuItem((HWND) mp2, IDM_EJECT, removable);
2056
2057            WinEnableMenuItem((HWND) mp2, IDM_LOCK, removable);
2058            WinEnableMenuItem((HWND) mp2, IDM_UNLOCK, removable);
2059
2060            WinEnableMenuItem((HWND) mp2, IDM_DELETE, !underenv && writeable);
2061            WinEnableMenuItem((HWND) mp2, IDM_PERMDELETE, !underenv
2062                              && writeable);
2063            WinEnableMenuItem((HWND) mp2, IDM_DELETESUBMENU, !underenv
2064                              && writeable);
2065            WinEnableMenuItem((HWND) mp2, IDM_MOVEMENU, !underenv
2066                              && writeable);
2067            WinEnableMenuItem((HWND) mp2, IDM_RENAME, !underenv && writeable);
2068
2069          }
2070        }
2071        break;
2072
2073      case IDM_VIEWSMENU:
2074        WinCheckMenuItem((HWND) mp2,
2075                         IDM_MINIICONS, ((dcd->flWindowAttr & CV_MINI) != 0));
2076        WinEnableMenuItem((HWND) mp2, IDM_RESELECT, FALSE);
2077        break;
2078
2079      case IDM_COMMANDSMENU:
2080        SetupCommandMenu((HWND) mp2, hwnd);
2081        break;
2082
2083      case IDM_SORTSUBMENU:
2084        SetSortChecks((HWND) mp2, TreesortFlags);
2085        break;
2086
2087      case IDM_WINDOWSMENU:
2088        SetupWinList((HWND) mp2,
2089                     (hwndMain) ? hwndMain : (HWND) 0, dcd->hwndFrame);
2090        break;
2091      }
2092      dcd->hwndLastMenu = (HWND) mp2;
2093    }
2094    if (msg == WM_INITMENU)
2095      break;
2096    return 0;
2097
2098  case UM_COMMAND:
2099    if (!mp1)
2100      Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
2101    else {
2102      if (!dcd) {
2103        Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
2104        FreeListInfo((LISTINFO *) mp1);
2105      }
2106      else {
2107        if (!PostMsg(dcd->hwndObject, UM_COMMAND, mp1, mp2)) {
2108          Runtime_Error(pszSrcFile, __LINE__, "PostMsg");
2109          FreeListInfo((LISTINFO *) mp1);
2110        }
2111        else
2112          return (MRESULT) TRUE;
2113      }
2114    }
2115    return 0;
2116
2117  case UM_LOADFILE:
2118    if (dcd && mp2) {
2119
2120      HWND ret;
2121
2122      ret = StartMLEEditor(dcd->hwndParent, (INT) mp1, (CHAR *) mp2,
2123                           dcd->hwndFrame);
2124      if (mp2)
2125        free((CHAR *) mp2);
2126      return MRFROMLONG(ret);
2127    }
2128    return 0;
2129
2130  case UM_FIXCNRMLE:
2131  case UM_FIXEDITNAME:
2132    return CommonCnrProc(hwnd, msg, mp1, mp2);
2133
2134  case UM_NOTIFY:
2135    if (mp2)
2136      Notify((CHAR *) mp2);
2137    return 0;
2138
2139  case UM_FILTER:
2140    if (dcd) {
2141
2142      BOOL tempsusp = dcd->suspendview;
2143
2144      if (mp1) {
2145        DosEnterCritSec();
2146        SetMask((CHAR *) mp1, &dcd->mask);
2147        DosExitCritSec();
2148      }
2149      dcd->suspendview = TRUE;
2150      dcd->mask.attrFile |= FILE_DIRECTORY;
2151      WinSendMsg(hwnd, CM_FILTER, MPFROMP(Filter), MPFROMP(&dcd->mask));
2152      dcd->suspendview = tempsusp;
2153      PostMsg(hwnd, UM_RESCAN, MPVOID, MPVOID);
2154    }
2155    return 0;
2156
2157  case UM_DRIVECMD:
2158    if (mp1)
2159      ShowTreeRec(hwnd, (CHAR *) mp1, FALSE, TRUE);
2160    return 0;
2161
2162  case WM_APPTERMINATENOTIFY:
2163    {
2164      APPNOTIFY *info;
2165      PCNRITEM pci;
2166      CHAR s[] = " :\\";
2167
2168      if (!mp2) {
2169        if (hwndMain)
2170          PostMsg(hwndMain, UM_BUILDDRIVEBAR, MPVOID, MPVOID);
2171      }
2172      info = apphead;
2173      while (info) {
2174        if (info->happ == (HAPP) mp1) {
2175          *s = info->device;
2176          pci = FindCnrRecord(hwnd, s, NULL, FALSE, FALSE, TRUE);
2177          if (pci && (INT) pci != -1) {
2178            driveserial[info->device - 'A'] = -1;
2179            DriveFlagsOne(info->device - 'A');
2180            if (driveflags[info->device - 'A'] &
2181                (DRIVE_INVALID | DRIVE_IGNORE))
2182              RemoveCnrItems(hwnd, pci, 1, CMA_FREE);
2183            else
2184              Flesh(hwnd, pci);
2185          }
2186          if (info->prev)
2187            info->prev->next = info->next;
2188          if (info->next)
2189            info->next->prev = info->prev;
2190          if (apphead == info)
2191            apphead = info->next;
2192          if (apptail == info)
2193            apptail = info->prev;
2194          free(info);
2195          break;
2196        }
2197        info = info->next;
2198      }
2199    }
2200    break;
2201
2202  case WM_COMMAND:
2203    DosError(FERR_DISABLEHARDERR);
2204    if (dcd) {
2205      if (SwitchCommand(dcd->hwndLastMenu, SHORT1FROMMP(mp1)))
2206        return 0;
2207      switch (SHORT1FROMMP(mp1)) {
2208      case IDM_SETTARGET:
2209        SetTargetDir(hwnd, FALSE);
2210        break;
2211
2212      case IDM_DETACH:
2213        {
2214          CHAR d[3] = " :";
2215          PCNRITEM pci;
2216          PROGDETAILS pgd;
2217          CHAR params[368], *p;
2218          HAPP happ;
2219
2220          pci = (PCNRITEM) CurrentRecord(hwnd);
2221          if (pci && (INT) pci != -1 && isalpha(*pci->pszFileName)) {
2222            *d = toupper(*pci->pszFileName);
2223            p = GetCmdSpec(FALSE);
2224            memset(&pgd, 0, sizeof(pgd));
2225            pgd.Length = sizeof(pgd);
2226            pgd.progt.progc = PROG_WINDOWABLEVIO;
2227            pgd.progt.fbVisible = SHE_VISIBLE;
2228            pgd.pszTitle = GetPString(IDS_DETACHREQUESTTEXT);
2229            pgd.pszExecutable = p;
2230            pgd.pszParameters = params;
2231            pgd.pszStartupDir = NULL;
2232            pgd.pszIcon = NULL;
2233            pgd.pszEnvironment = NULL;
2234            pgd.swpInitial.hwndInsertBehind = HWND_TOP;
2235            pgd.swpInitial.hwnd = hwnd;
2236            pgd.swpInitial.fl = SWP_SHOW | SWP_ACTIVATE;
2237            sprintf(params, "/C NET USE %s /D", d);
2238            happ = WinStartApp(hwnd, &pgd, pgd.pszParameters,
2239                               NULL, SAF_MAXIMIZED);
2240            if (!happ) {
2241              saymsg(MB_CANCEL | MB_ICONEXCLAMATION, hwnd,
2242                     GetPString(IDS_ERRORTEXT),
2243                     GetPString(IDS_CANTSTARTTEXT), p, params);
2244            }
2245            else {
2246              APPNOTIFY *info;
2247
2248              info = xmallocz(sizeof(APPNOTIFY), pszSrcFile, __LINE__);
2249              if (info) {
2250                info->happ = happ;
2251                info->device = *d;
2252                if (!apphead)
2253                  apphead = info;
2254                else {
2255                  apptail->next = info;
2256                  info->prev = apptail;
2257                }
2258                apptail = info;
2259              }
2260            }
2261          }
2262        }
2263        break;
2264
2265      case IDM_REMAP:
2266        WinDlgBox(HWND_DESKTOP, hwnd, RemapDlgProc,
2267                  FM3ModHandle, MAP_FRAME, NULL);
2268        break;
2269
2270      case IDM_CONTEXTMENU:
2271        {
2272          PCNRITEM pci;
2273
2274          pci = (PCNRITEM) CurrentRecord(hwnd);
2275          PostMsg(hwnd, WM_CONTROL, MPFROM2SHORT(DIR_CNR, CN_CONTEXTMENU),
2276                  MPFROMP(pci));
2277        }
2278        break;
2279
2280      case IDM_FINDINTREE:
2281        {
2282          CHAR dir[CCHMAXPATH];
2283          PCNRITEM pci;
2284
2285          pci = (PCNRITEM) CurrentRecord(hwnd);
2286          if (pci && (INT) pci != -1) {
2287            strcpy(dir, pci->pszFileName);
2288            MakeValidDir(dir);
2289          }
2290          else
2291            save_dir2(dir);
2292          if (WinDlgBox(HWND_DESKTOP, dcd->hwndParent,
2293                        WalkAllDlgProc,
2294                        FM3ModHandle, WALK_FRAME, MPFROMP(dir)) && *dir)
2295            WinSendMsg(hwnd, UM_SHOWME, MPFROMP(dir), MPFROMLONG(1L));
2296        }
2297        break;
2298
2299      case IDM_BEGINEDIT:
2300        OpenEdit(hwnd);
2301        break;
2302
2303      case IDM_ENDEDIT:
2304        WinSendMsg(hwnd, CM_CLOSEEDIT, MPVOID, MPVOID);
2305        break;
2306
2307      case IDM_FILTER:
2308        {
2309          BOOL empty = FALSE;
2310          PCNRITEM pci;
2311
2312          pci = (PCNRITEM) CurrentRecord(hwnd);
2313          if (!*dcd->mask.szMask)
2314            empty = TRUE;
2315          dcd->mask.fIsTree = TRUE;
2316          *dcd->mask.prompt = 0;
2317          if (pci && (INT) pci != -1)
2318            dcd->mask.fFilesIncluded =
2319              ((driveflags[toupper(*pci->pszFileName) - 'A'] &
2320                DRIVE_INCLUDEFILES) != 0);
2321          else
2322            dcd->mask.fFilesIncluded = FALSE;
2323          if (WinDlgBox(HWND_DESKTOP, hwnd, PickMaskDlgProc,
2324                        FM3ModHandle, MSK_FRAME, MPFROMP(&dcd->mask)))
2325            WinSendMsg(hwnd, UM_FILTER, MPVOID, MPVOID);
2326          else if (empty)
2327            *dcd->mask.szMask = 0;
2328          PrfWriteProfileData(fmprof, appname, "TreeFilter", &dcd->mask,
2329                              sizeof(MASK));
2330        }
2331        break;
2332
2333      case IDM_SHOWSORT:
2334        QuickPopup(hwnd, dcd, CheckMenu(&TreeCnrMenu, TREECNR_POPUP),
2335                   IDM_SORTSUBMENU);
2336        break;
2337
2338      case IDM_SHOWSELECT:
2339        QuickPopup(hwnd, dcd, CheckMenu(&TreeCnrMenu, TREECNR_POPUP),
2340                   IDM_SELECTSUBMENU);
2341        break;
2342
2343      case IDM_NOTEBOOK:
2344        if (!ParentIsDesktop(dcd->hwndParent, dcd->hwndParent))
2345          PostMsg(dcd->hwndParent, msg, mp1, mp2);
2346        else
2347          WinDlgBox(HWND_DESKTOP, hwnd, CfgDlgProc, FM3ModHandle,
2348                    CFG_FRAME, (PVOID) "Tree");
2349        break;
2350
2351      case IDM_WALKDIR:
2352      case IDM_OPENWALK:
2353        {
2354          CHAR newpath[CCHMAXPATH];
2355          PCNRITEM pci;
2356
2357          pci = (PCNRITEM) CurrentRecord(hwnd);
2358          if (pci && (INT) pci != -1) {
2359            strcpy(newpath, pci->pszFileName);
2360            MakeValidDir(newpath);
2361          }
2362          else
2363            save_dir2(newpath);
2364          if (!WinDlgBox(HWND_DESKTOP, dcd->hwndParent, WalkAllDlgProc,
2365                         FM3ModHandle, WALK_FRAME,
2366                         MPFROMP(newpath)) || !*newpath)
2367            break;
2368          WinSendMsg(hwnd, UM_OPENWINDOWFORME, MPFROMP(newpath), MPVOID);
2369        }
2370        break;
2371
2372      case IDM_HELP:
2373        if (hwndHelp) {
2374          if (!ParentIsDesktop(dcd->hwndFrame, dcd->hwndParent))
2375            PostMsg(dcd->hwndParent, UM_COMMAND, mp1, mp2);
2376          else
2377            WinSendMsg(hwndHelp, HM_HELP_CONTENTS, MPVOID, MPVOID);
2378        }
2379        break;
2380
2381      case IDM_PARTITION:
2382        runemf2(SEPARATE | WINDOWED, HWND_DESKTOP, NULL, NULL,
2383                "%s", "MINILVM.EXE");
2384        break;
2385
2386      case IDM_PARTITIONDF:
2387        runemf2(SEPARATE | WINDOWED, HWND_DESKTOP, NULL, NULL,
2388                "%s", "DFSOS2.EXE");
2389        break;
2390
2391      case IDM_PARTITIONLVMG:
2392        runemf2(SEPARATE | WINDOWED, HWND_DESKTOP, NULL, NULL,
2393                "%s", "LVMGUI.CMD");
2394        break;
2395
2396      case IDM_PARTITIONFD:
2397        runemf2(SEPARATE | WINDOWED, HWND_DESKTOP, NULL, NULL,
2398                "%s", "FDISKPM.EXE");
2399        break;
2400
2401      case IDM_SORTNAME:
2402      case IDM_SORTFILENAME:
2403      case IDM_SORTSIZE:
2404      case IDM_SORTEASIZE:
2405      case IDM_SORTFIRST:
2406      case IDM_SORTLAST:
2407      case IDM_SORTLWDATE:
2408      case IDM_SORTLADATE:
2409      case IDM_SORTCRDATE:
2410        TreesortFlags &= (SORT_REVERSE | SORT_DIRSFIRST | SORT_DIRSLAST);
2411      case IDM_SORTDIRSFIRST:
2412      case IDM_SORTDIRSLAST:
2413      case IDM_SORTREVERSE:
2414        switch (SHORT1FROMMP(mp1)) {
2415        case IDM_SORTFILENAME:
2416          TreesortFlags |= SORT_FILENAME;
2417          break;
2418        case IDM_SORTSIZE:
2419          TreesortFlags |= SORT_SIZE;
2420          break;
2421        case IDM_SORTEASIZE:
2422          TreesortFlags |= SORT_EASIZE;
2423          break;
2424        case IDM_SORTFIRST:
2425          TreesortFlags |= SORT_FIRSTEXTENSION;
2426          break;
2427        case IDM_SORTLAST:
2428          TreesortFlags |= SORT_LASTEXTENSION;
2429          break;
2430        case IDM_SORTLWDATE:
2431          TreesortFlags |= SORT_LWDATE;
2432          break;
2433        case IDM_SORTLADATE:
2434          TreesortFlags |= SORT_LADATE;
2435          break;
2436        case IDM_SORTCRDATE:
2437          TreesortFlags |= SORT_CRDATE;
2438          break;
2439        case IDM_SORTDIRSFIRST:
2440          if (TreesortFlags & SORT_DIRSFIRST)
2441            TreesortFlags &= (~SORT_DIRSFIRST);
2442          else {
2443            TreesortFlags |= SORT_DIRSFIRST;
2444            TreesortFlags &= (~SORT_DIRSLAST);
2445          }
2446          break;
2447        case IDM_SORTDIRSLAST:
2448          if (TreesortFlags & SORT_DIRSLAST)
2449            TreesortFlags &= (~SORT_DIRSLAST);
2450          else {
2451            TreesortFlags |= SORT_DIRSLAST;
2452            TreesortFlags &= (~SORT_DIRSFIRST);
2453          }
2454          break;
2455        case IDM_SORTREVERSE:
2456          if (TreesortFlags & SORT_REVERSE)
2457            TreesortFlags &= (~SORT_REVERSE);
2458          else
2459            TreesortFlags |= SORT_REVERSE;
2460          break;
2461        }
2462        PrfWriteProfileData(fmprof, appname, "TreeSort", &TreesortFlags,
2463                            sizeof(INT));
2464        WinSendMsg(hwnd, CM_SORTRECORD, MPFROMP(SortTreeCnr), MPVOID);
2465        break;
2466
2467      case IDM_COLLECT:
2468        if (!Collector) {
2469
2470          HWND hwndC;
2471          SWP swp;
2472
2473          if (!ParentIsDesktop(hwnd, dcd->hwndParent) &&
2474              !fAutoTile &&
2475              (!fExternalCollector && *(ULONG *) realappname == FM3UL))
2476            GetNextWindowPos(dcd->hwndParent, &swp, NULL, NULL);
2477          hwndC = StartCollector((fExternalCollector ||
2478                                  *(ULONG *) realappname != FM3UL) ?
2479                                 HWND_DESKTOP : dcd->hwndParent, 4);
2480          if (hwndC) {
2481            if (!ParentIsDesktop(hwnd,
2482                                 dcd->hwndParent) &&
2483                !fAutoTile &&
2484                (!fExternalCollector && *(ULONG *) realappname == FM3UL))
2485              WinSetWindowPos(hwndC,
2486                              HWND_TOP,
2487                              swp.x,
2488                              swp.y,
2489                              swp.cx,
2490                              swp.cy,
2491                              SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ZORDER);
2492            else if (!ParentIsDesktop(hwnd,
2493                                      dcd->hwndParent) &&
2494                     fAutoTile && *(ULONG *) realappname == FM3UL)
2495              TileChildren(dcd->hwndParent, TRUE);
2496          }
2497          WinSetWindowPos(hwndC, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
2498          DosSleep(250L);
2499        }
2500        else
2501          StartCollector(dcd->hwndParent, 4);
2502        PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(IDM_COLLECTOR, 0), MPVOID);
2503        break;
2504
2505      case IDM_COLLECTOR:
2506        DosSleep(64L);
2507        {
2508          CHAR **list;
2509
2510          list = BuildList(hwnd);
2511          if (list) {
2512            if (Collector) {
2513              if (!PostMsg(Collector, WM_COMMAND,
2514                           MPFROM2SHORT(IDM_COLLECTOR, 0), MPFROMP(list)))
2515                FreeList(list);
2516            }
2517            else
2518              FreeList(list);
2519          }
2520        }
2521        break;
2522
2523      case IDM_COLLAPSEALL:
2524        WinSendMsg(hwnd, CM_COLLAPSETREE, MPVOID, MPVOID);
2525        break;
2526
2527      case IDM_COLLAPSE:
2528      case IDM_EXPAND:
2529        {
2530          PCNRITEM pci = NULL;
2531
2532          pci = (PCNRITEM) CurrentRecord(hwnd);
2533          if (pci && (INT) pci != -1) {
2534            if (pci->flags & RECFLAGS_UNDERENV)
2535              break;
2536            PostMsg(dcd->hwndObject, UM_EXPAND, mp1, MPFROMP(pci));
2537          }
2538        }
2539        break;
2540
2541      case IDM_UPDATE:
2542        {
2543          PCNRITEM pci = (PCNRITEM)CurrentRecord(hwnd);
2544          if (pci && (INT)pci != -1) {
2545            UINT driveflag = driveflags[toupper(*pci->pszFileName) - 'A'];
2546            if (pci->attrFile & FILE_DIRECTORY) {
2547              if (pci->flags & RECFLAGS_UNDERENV)
2548                break;
2549              UnFlesh(hwnd, pci);
2550              // Check if drive type might need update
2551              if ((driveflag & (DRIVE_INVALID | DRIVE_NOPRESCAN)) ||
2552                  (~driveflag & DRIVE_NOPRESCAN && pci->rc.hptrIcon == hptrDunno))
2553              {
2554                driveflags[toupper(*pci->pszFileName) - 'A'] &=
2555                  (DRIVE_IGNORE | DRIVE_NOPRESCAN | DRIVE_NOLOADICONS |
2556                   DRIVE_NOLOADSUBJS | DRIVE_NOLOADLONGS | DRIVE_NOSTATS);
2557                DriveFlagsOne(toupper(*pci->pszFileName) - 'A');
2558                driveflag = driveflags[toupper(*pci->pszFileName) - 'A'];
2559                if (driveflag & DRIVE_INVALID)
2560                  pci->rc.hptrIcon = hptrDunno;
2561                else {
2562                  SelectDriveIcon(pci);
2563                }
2564                WinSendMsg(hwnd,
2565                           CM_INVALIDATERECORD,
2566                           MPFROMP(&pci),
2567                           MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
2568                if (hwndMain)
2569                  PostMsg(hwndMain, UM_BUILDDRIVEBAR, MPVOID, MPVOID);
2570              }
2571              if (~driveflag & DRIVE_INVALID)
2572                Flesh(hwnd, pci);
2573            }
2574          }
2575        }
2576        break;
2577
2578      case IDM_RESCAN:
2579        PostMsg(dcd->hwndObject, UM_RESCAN, MPVOID, MPVOID);
2580        break;
2581
2582      case IDM_RESORT:
2583        WinSendMsg(hwnd, CM_SORTRECORD, MPFROMP(SortTreeCnr), MPVOID);
2584        break;
2585
2586      case IDM_TEXT:
2587      case IDM_MINIICONS:
2588        {
2589          CNRINFO cnri;
2590
2591          memset(&cnri, 0, sizeof(CNRINFO));
2592          cnri.cb = sizeof(CNRINFO);
2593          WinSendMsg(hwnd,
2594                     CM_QUERYCNRINFO,
2595                     MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
2596          if (SHORT1FROMMP(mp1) == IDM_MINIICONS) {
2597            if (cnri.flWindowAttr & CV_MINI)
2598              cnri.flWindowAttr &= (~CV_MINI);
2599            else
2600              cnri.flWindowAttr |= CV_MINI;
2601          }
2602          else {
2603            if (cnri.flWindowAttr & CV_TEXT) {
2604              cnri.flWindowAttr &= (~CV_TEXT);
2605              cnri.flWindowAttr |= CV_ICON;
2606            }
2607            else {
2608              cnri.flWindowAttr &= (~CV_ICON);
2609              cnri.flWindowAttr |= CV_TEXT;
2610            }
2611          }
2612          dcd->flWindowAttr = cnri.flWindowAttr;
2613          PrfWriteProfileData(fmprof,
2614                              appname,
2615                              "TreeflWindowAttr",
2616                              &cnri.flWindowAttr, sizeof(ULONG));
2617          WinSendMsg(hwnd,
2618                     CM_SETCNRINFO,
2619                     MPFROMP(&cnri),
2620                     MPFROMLONG(CMA_FLWINDOWATTR | CMA_TREEICON |
2621                                CMA_SLTREEBITMAPORICON));
2622        }
2623        break;
2624
2625      case IDM_SIZES:
2626      case IDM_DRVFLAGS:
2627      case IDM_SHOWALLFILES:
2628      case IDM_UNDELETE:
2629      case IDM_OPTIMIZE:
2630      case IDM_CHKDSK:
2631      case IDM_FORMAT:
2632      case IDM_MKDIR:
2633      case IDM_LOCK:
2634      case IDM_UNLOCK:
2635      case IDM_EJECT:
2636      case IDM_CLOSETRAY:
2637        {
2638          PCNRITEM pci;
2639
2640          pci = (PCNRITEM) CurrentRecord(hwnd);
2641          if (pci && (INT) pci != -1)
2642            CommonDriveCmd(hwnd, pci->pszFileName, SHORT1FROMMP(mp1));
2643        }
2644        break;
2645
2646      case IDM_SAVETOLIST:
2647        WinDlgBox(HWND_DESKTOP,
2648                  hwnd,
2649                  SaveListDlgProc, FM3ModHandle, SAV_FRAME, MPFROMP(&hwnd));
2650        break;
2651
2652      case IDM_DELETE:
2653      case IDM_PERMDELETE:
2654      case IDM_MOVE:
2655      case IDM_WPSMOVE:
2656      case IDM_WILDMOVE:
2657      case IDM_RENAME:
2658        {
2659          PCNRITEM pci;
2660
2661          pci = (PCNRITEM) CurrentRecord(hwnd);
2662          if (pci && (INT) pci != -1) {
2663            if (pci->flags & RECFLAGS_UNDERENV)
2664              break;
2665          }
2666        }
2667        /* else intentional fallthru */
2668      case IDM_ATTRS:
2669      case IDM_INFO:
2670      case IDM_COPY:
2671      case IDM_WPSCOPY:
2672      case IDM_WILDCOPY:
2673      case IDM_DOITYOURSELF:
2674      case IDM_OPENWINDOW:
2675      case IDM_OPENSETTINGS:
2676      case IDM_OPENDEFAULT:
2677      case IDM_OPENICON:
2678      case IDM_OPENDETAILS:
2679      case IDM_OPENTREE:
2680      case IDM_SHADOW:
2681      case IDM_SHADOW2:
2682      case IDM_COMPARE:
2683      case IDM_VIEW:
2684      case IDM_VIEWTEXT:
2685      case IDM_VIEWBINARY:
2686      case IDM_EDIT:
2687      case IDM_EDITTEXT:
2688      case IDM_EDITBINARY:
2689      case IDM_EAS:
2690      case IDM_SUBJECT:
2691      case IDM_APPENDTOCLIP:
2692      case IDM_SAVETOCLIP:
2693      case IDM_ARCHIVE:
2694      case IDM_MCIPLAY:
2695      case IDM_UUDECODE:
2696        {
2697          LISTINFO *li;
2698          ULONG action = UM_ACTION;
2699
2700          li = xmallocz(sizeof(LISTINFO), pszSrcFile, __LINE__);
2701          if (li) {
2702            li->type = SHORT1FROMMP(mp1);
2703            li->hwnd = hwnd;
2704            li->list = BuildList(hwnd);
2705            if (!li->list || !li->list[0]) {
2706              free(li);
2707              break;
2708            }
2709            if (IsRoot(li->list[0])) {
2710              switch (SHORT1FROMMP(mp1)) {
2711              case IDM_MOVE:
2712              case IDM_COPY:
2713              case IDM_WILDCOPY:
2714              case IDM_WILDMOVE:
2715              case IDM_WPSMOVE:
2716              case IDM_WPSCOPY:
2717              case IDM_RENAME:
2718              case IDM_DELETE:
2719              case IDM_PERMDELETE:
2720                mp1 = MPFROM2SHORT(IDM_INFO, SHORT2FROMMP(mp1));
2721                li->type = IDM_INFO;
2722                break;
2723              }
2724            }
2725            switch (SHORT1FROMMP(mp1)) {
2726            case IDM_APPENDTOCLIP:
2727            case IDM_SAVETOCLIP:
2728            case IDM_ARCHIVE:
2729            case IDM_DELETE:
2730            case IDM_PERMDELETE:
2731            case IDM_ATTRS:
2732            case IDM_SHADOW:
2733            case IDM_SHADOW2:
2734            case IDM_DOITYOURSELF:
2735            case IDM_EAS:
2736            case IDM_VIEW:
2737            case IDM_VIEWTEXT:
2738            case IDM_VIEWBINARY:
2739            case IDM_EDIT:
2740            case IDM_EDITTEXT:
2741            case IDM_EDITBINARY:
2742            case IDM_MCIPLAY:
2743              action = UM_MASSACTION;
2744              break;
2745            }
2746            if (SHORT1FROMMP(mp1) == IDM_SHADOW ||
2747                SHORT1FROMMP(mp1) == IDM_SHADOW2)
2748              *li->targetpath = 0;
2749            if (!PostMsg(dcd->hwndObject, action, MPFROMP(li), MPVOID)) {
2750              Runtime_Error(pszSrcFile, __LINE__, "PostMsg");
2751              FreeListInfo(li);
2752            }
2753          }
2754        }
2755        break;
2756
2757      default:
2758        if (SHORT1FROMMP(mp1) >= IDM_COMMANDSTART &&
2759            SHORT1FROMMP(mp1) < IDM_QUICKTOOLSTART) {
2760
2761          INT x;
2762
2763          if (!cmdloaded)
2764            load_commands();
2765          x = SHORT1FROMMP(mp1) - IDM_COMMANDSTART;
2766          if (x >= 0) {
2767            x++;
2768            RunCommand(hwnd, x);
2769            if (fUnHilite)
2770              UnHilite(hwnd, TRUE, &dcd->lastselection, 0);
2771          }
2772        }
2773        break;
2774      }
2775    }
2776    return 0;
2777
2778  case WM_SAVEAPPLICATION:
2779    if (dcd && !ParentIsDesktop(hwnd, dcd->hwndParent)) {
2780
2781      SWP swp, swpP;
2782      INT ratio;
2783
2784      WinQueryWindowPos(dcd->hwndFrame, &swp);
2785      if (!(swp.fl & (SWP_MINIMIZE | SWP_MAXIMIZE | SWP_HIDE))) {
2786        WinQueryWindowPos(dcd->hwndParent, &swpP);
2787        ratio = (swpP.cx * 100) / swp.cx;
2788        if (ratio > 0)
2789          PrfWriteProfileData(fmprof, appname, "TreeWindowRatio",
2790                              &ratio, sizeof(INT));
2791      }
2792    }
2793    else if (dcd && ParentIsDesktop(hwnd, dcd->hwndParent)) {
2794
2795      SWP swp;
2796
2797      WinQueryWindowPos(dcd->hwndFrame, &swp);
2798      if (!(swp.fl & (SWP_HIDE | SWP_MINIMIZE | SWP_MAXIMIZE)))
2799        WinStoreWindowPos(FM2Str, "VTreeWindowPos", dcd->hwndFrame);
2800    }
2801    break;
2802
2803  case UM_MINIMIZE:
2804    if (dcd && hwndMain) {
2805      fOkayMinimize = TRUE;
2806      if (dcd->hwndObject && !fDummy) {
2807        DosSleep(100L);
2808        if (!fDummy) {
2809          fOkayMinimize = FALSE;
2810          WinSetWindowPos(((hwndMain) ? WinQueryWindow(hwndMain, QW_PARENT) :
2811                           dcd->hwndFrame), HWND_TOP, 0, 0, 0, 0,
2812                          SWP_MINIMIZE | SWP_DEACTIVATE);
2813        }
2814      }
2815    }
2816    return 0;
2817
2818  case UM_MAXIMIZE:
2819    if (dcd || hwndMain)
2820      WinSetWindowPos(((hwndMain) ? WinQueryWindow(hwndMain, QW_PARENT) :
2821                       dcd->hwndFrame), HWND_TOP, 0, 0, 0, 0, SWP_MAXIMIZE |
2822                      SWP_SHOW);
2823    return 0;
2824
2825  case UM_CLOSE:
2826    {
2827      HWND hwndParent = WinQueryWindow(WinQueryWindow(WinQueryWindow(hwnd,
2828                                                                     QW_PARENT),
2829                                                      QW_PARENT), QW_PARENT);
2830
2831      if (!mp1) {
2832        if (!PostMsg((HWND) 0, WM_QUIT, MPVOID, MPVOID))
2833          WinSendMsg((HWND) 0, WM_QUIT, MPVOID, MPVOID);
2834        if (hwndParent && !ParentIsDesktop(hwnd, hwndParent))
2835          WinDestroyWindow(hwndParent);
2836      }
2837      else
2838        WinDestroyWindow(WinQueryWindow(WinQueryWindow(hwnd, QW_PARENT),
2839                                        QW_PARENT));
2840    }
2841    return 0;
2842
2843  case WM_CLOSE:
2844    WinSendMsg(hwnd, WM_SAVEAPPLICATION, MPVOID, MPVOID);
2845    if (dcd)
2846      dcd->stopflag++;
2847    if (dcd && dcd->hwndObject) {
2848      /* kill object window */
2849      if (!PostMsg(dcd->hwndObject, WM_CLOSE, MPVOID, MPVOID))
2850        WinSendMsg(dcd->hwndObject, WM_CLOSE, MPVOID, MPVOID);
2851    }
2852    else
2853      WinSendMsg(hwnd, UM_CLOSE, MPFROMLONG(1L), MPVOID);
2854    return 0;
2855
2856  case WM_DESTROY:
2857    if (TreeCnrMenu)
2858      WinDestroyWindow(TreeCnrMenu);
2859    if (DirMenu)
2860      WinDestroyWindow(DirMenu);
2861    if (FileMenu)
2862      WinDestroyWindow(FileMenu);
2863    TreeCnrMenu = FileMenu = DirMenu = (HWND) 0;
2864    EmptyCnr(hwnd);
2865    if (apphead) {
2866
2867      APPNOTIFY *info, *next;
2868
2869      info = apphead;
2870      while (info) {
2871        next = info->next;
2872        free(info);
2873        info = next;
2874      }
2875      apphead = apptail = NULL;
2876    }
2877    break;
2878  }
2879  if (dcd && dcd->oldproc){
2880      return dcd->oldproc(hwnd, msg, mp1, mp2);
2881  }
2882  else
2883      return PFNWPCnr(hwnd, msg, mp1, mp2);
2884}
2885
2886HWND StartTreeCnr(HWND hwndParent, ULONG flags)
2887{
2888  /* bitmapped flags:
2889   * 0x00000001 = don't close app when window closes
2890   * 0x00000002 = no frame controls
2891   */
2892
2893  HWND hwndFrame = (HWND) 0, hwndClient;
2894  ULONG FrameFlags = FCF_TITLEBAR | FCF_SYSMENU |
2895    FCF_SIZEBORDER | FCF_MINMAX | FCF_ICON | FCF_NOBYTEALIGN | FCF_ACCELTABLE;
2896  DIRCNRDATA *dcd;
2897
2898  if (!hwndParent)
2899    hwndParent = HWND_DESKTOP;
2900  if (ParentIsDesktop(hwndParent, hwndParent))
2901    FrameFlags |= (FCF_TASKLIST | FCF_MENU);
2902  if (flags & 2)
2903    FrameFlags &= (~(FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER |
2904                     FCF_MINMAX | FCF_ICON));
2905  hwndFrame = WinCreateStdWindow(hwndParent,
2906                                 WS_VISIBLE,
2907                                 &FrameFlags,
2908                                 WC_TREECONTAINER,
2909                                 NULL,
2910                                 WS_VISIBLE | fwsAnimate,
2911                                 FM3ModHandle, TREE_FRAME, &hwndClient);
2912  if (hwndFrame && hwndClient) {
2913    dcd = xmalloc(sizeof(DIRCNRDATA), pszSrcFile, __LINE__);
2914    if (!dcd) {
2915      Runtime_Error(pszSrcFile, __LINE__, GetPString(IDS_OUTOFMEMORY));
2916      PostMsg(hwndClient, WM_CLOSE, MPVOID, MPVOID);
2917      hwndFrame = (HWND) 0;
2918    }
2919    else {
2920      SWP swp;
2921
2922      WinQueryWindowPos(hwndFrame, &swp);
2923      if (*(ULONG *) realappname == FM3UL) {
2924        if (!WinCreateWindow(hwndFrame,
2925                             WC_TREEOPENBUTTON,
2926                             "O",
2927                             WS_VISIBLE | BS_PUSHBUTTON | BS_NOPOINTERFOCUS,
2928                             ((swp.cx -
2929                               WinQuerySysValue(HWND_DESKTOP,
2930                                                SV_CXMINMAXBUTTON)) -
2931                              WinQuerySysValue(HWND_DESKTOP,
2932                                               SV_CXMINMAXBUTTON) / 2) -
2933                              WinQuerySysValue(HWND_DESKTOP, SV_CXSIZEBORDER),
2934                             (swp.cy -
2935                              WinQuerySysValue(HWND_DESKTOP,
2936                                               SV_CYMINMAXBUTTON)) -
2937                              WinQuerySysValue(HWND_DESKTOP, SV_CYSIZEBORDER),
2938                             WinQuerySysValue(HWND_DESKTOP,
2939                                              SV_CXMINMAXBUTTON) / 2,
2940                             WinQuerySysValue(HWND_DESKTOP,
2941                                              SV_CYMINMAXBUTTON), hwndFrame,
2942                                              HWND_TOP, IDM_OPENWINDOW, NULL, NULL)) {
2943          Win_Error2(hwndFrame, hwndParent, pszSrcFile, __LINE__,
2944                     IDS_WINCREATEWINDOW);
2945        }
2946      }
2947      else {
2948        if (!WinCreateWindow(hwndFrame,
2949                             WC_TREESTATUS,
2950                             GetPString(IDS_YOUAREHERETEXT),
2951                             WS_VISIBLE | SS_TEXT | DT_LEFT | DT_VCENTER,
2952                             swp.x + 4 + WinQuerySysValue(HWND_DESKTOP,
2953                                                          SV_CXSIZEBORDER),
2954                             swp.cy - (22 + WinQuerySysValue(HWND_DESKTOP,
2955                                                             SV_CYSIZEBORDER)),
2956                             (swp.cx - 8) - (WinQuerySysValue(HWND_DESKTOP,
2957                                                              SV_CXSIZEBORDER)
2958                                             * 2), 22, hwndFrame, HWND_TOP,
2959                             MAIN_STATUS, NULL, NULL)) {
2960          Win_Error2(hwndFrame, hwndParent, pszSrcFile, __LINE__,
2961                     IDS_WINCREATEWINDOW);
2962        }
2963      }
2964      memset(dcd, 0, sizeof(DIRCNRDATA));
2965      dcd->size = sizeof(DIRCNRDATA);
2966      dcd->type = TREE_FRAME;
2967      dcd->dontclose = ((flags & 1) != 0);
2968      dcd->hwndParent = (hwndParent) ? hwndParent : HWND_DESKTOP;
2969      dcd->hwndClient = hwndClient;
2970      dcd->hwndFrame = hwndFrame;
2971      {
2972        PFNWP oldproc;
2973
2974        oldproc = WinSubclassWindow(hwndFrame, TreeFrameWndProc);
2975        WinSetWindowPtr(hwndFrame, QWL_USER, (PVOID) oldproc);
2976        oldproc = WinSubclassWindow(WinWindowFromID(hwndFrame, FID_TITLEBAR),
2977                                    (PFNWP) TreeTitleWndProc);
2978        WinSetWindowPtr(WinWindowFromID(hwndFrame, FID_TITLEBAR),
2979                        QWL_USER, (PVOID) oldproc);
2980      }
2981      dcd->hwndCnr = WinCreateWindow(hwndClient,
2982                                     WC_CONTAINER,
2983                                     NULL,
2984                                     CCS_AUTOPOSITION | CCS_MINIICONS |
2985                                     CCS_MINIRECORDCORE | WS_VISIBLE,
2986                                     0,
2987                                     0,
2988                                     0,
2989                                     0,
2990                                     hwndClient,
2991                                     HWND_TOP, (ULONG) TREE_CNR, NULL, NULL);
2992      if (!dcd->hwndCnr) {
2993        Win_Error2(hwndClient, hwndClient, pszSrcFile, __LINE__,
2994                   IDS_WINCREATEWINDOW);
2995        PostMsg(hwndClient, WM_CLOSE, MPVOID, MPVOID);
2996        free(dcd);
2997        hwndFrame = (HWND) 0;
2998      }
2999      else {
3000        WinSetWindowPtr(dcd->hwndCnr, QWL_USER, (PVOID) dcd);
3001        if (ParentIsDesktop(hwndFrame, hwndParent)) {
3002          WinSetWindowText(WinWindowFromID(hwndFrame, FID_TITLEBAR), "VTree");
3003          FixSwitchList(hwndFrame, "VTree");
3004        }
3005        else {
3006          WinSetWindowText(hwndFrame, GetPString(IDS_TREETEXT));
3007          WinSetWindowText(WinWindowFromID(hwndFrame, FID_TITLEBAR),
3008                           GetPString(IDS_TREETEXT));
3009        }
3010        dcd->oldproc = WinSubclassWindow(dcd->hwndCnr, TreeCnrWndProc);
3011        // DbgMsg(pszSrcFile, __LINE__, "oldproc subclass %X", dcd->oldproc);   // 05 Jul 07 SHL
3012        // fixme to document 01 test?
3013        if (dcd->oldproc == 0l)
3014            Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
3015                     "WinSubclassWindow");
3016        if (!PostMsg(dcd->hwndCnr, UM_SETUP, MPVOID, MPVOID))
3017          WinSendMsg(dcd->hwndCnr, UM_SETUP, MPVOID, MPVOID);
3018      }
3019    }
3020  }
3021  return hwndFrame;
3022}
Note: See TracBrowser for help on using the repository browser.