source: trunk/dll/treecnr.c @ 739

Last change on this file since 739 was 739, checked in by Steven Levine, 13 years ago

More ticket #24 updates

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