source: trunk/dll/treecnr.c @ 618

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

Add more drag/drop error checking
Use FreeDragInfoData?
Sync with NumItemsToUnhilite? AcceptOneDrop? GetOneDrop? mods

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