source: trunk/dll/treecnr.c @ 672

Last change on this file since 672 was 672, checked in by Steven Levine, 14 years ago

Use dcd->ulItemsToUnHilite
Sync UnHilite? calls with arg mods

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