source: trunk/dll/draglist.c @ 628

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

Avoid odd first time drag failure

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.2 KB
Line 
1
2/***********************************************************************
3
4  $Id: draglist.c 628 2007-04-22 04:56:32Z stevenhl $
5
6  Drag drop support
7
8  Copyright (c) 1993-98 M. Kimes
9  Copyright (c) 2001, 2002 Steven H.Levine
10
11  16 Oct 02 SHL DoFileDrag: don't free stack
12  26 Jul 06 SHL Check more run time errors
13  06 Apr 07 GKY Work around PM DragInfo and DrgFreeDISH limits
14  06 Apr 07 GKY Add DeleteDragitemStrHandles
15  06 Apr 07 GKY Add some error checking in drag/drop
16  19 Apr 07 SHL Rework DeleteDragitemStrHandles to be FreeDragInfoData
17  19 Apr 07 SHL Add more drag/drop error checking
18  19 Apr 07 SHL Optimize DRAGITEM DRAGIMAGE array access
19  21 Apr 07 SHL Avoid odd first time drag failure
20
21***********************************************************************/
22
23#define INCL_DOS
24#define INCL_WIN
25#define INCL_SHLERRORS
26#include <os2.h>
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <ctype.h>
32
33#include "fm3dll.h"
34
35static PSZ pszSrcFile = __FILE__;
36
37#pragma alloc_text(DRAGLIST,DragOne,DoFileDrag,DragList,PickUp,FreeDragInfoData)
38
39/**
40 * Delete drag item string handles.
41 * Work around for DrgDeleteDraginfoStrHandles
42 * which seems to fail with a large number of strings
43 * Assume called after successful DrgAccessDraginfo
44 */
45
46
47// #define USE_FAST_FREE                // Define to let PM do free
48
49VOID FreeDragInfoData (HWND hwnd, PDRAGINFO pDInfo)
50{
51  PDRAGITEM pDItem;
52  ULONG cDitem;
53  ULONG curitem;
54  APIRET ok;
55
56# ifdef USE_FAST_FREE
57  if (!DrgDeleteDraginfoStrHandles(pDInfo)) {
58    Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
59              "DrgDeleteDraginfoStrHandles");
60  }
61# else // The slow way
62  cDitem = DrgQueryDragitemCount(pDInfo);
63  for (curitem = 0; curitem < cDitem; curitem++) {
64    pDItem = DrgQueryDragitemPtr(pDInfo, curitem);
65    if (!pDItem) {
66      Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
67                "DrgQueryDragitemPtr(%u)", curitem);
68    }
69    else {
70      ok = DrgDeleteStrHandle(pDItem->hstrType);
71      if (!ok) {
72        Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
73                      "DrgDeleteStrHandle(0x%x) hstrType",pDItem->hstrType);
74      }
75      ok = DrgDeleteStrHandle(pDItem->hstrRMF);
76      if (!ok) {
77        Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
78                      "DrgDeleteStrHandle(0x%x) hstrRMF",pDItem->hstrRMF);
79      }
80      ok = DrgDeleteStrHandle(pDItem->hstrContainerName);
81      if (!ok) {
82        Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
83                      "DrgDeleteStrHandle(0x%x) hstrContainerName",pDItem->hstrContainerName);
84      }
85      ok = DrgDeleteStrHandle(pDItem->hstrSourceName);
86      if (!ok) {
87        Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
88                      "DrgDeleteStrHandle(0x%x) hstrSourceName",pDItem->hstrSourceName);
89      }
90      ok = DrgDeleteStrHandle(pDItem->hstrTargetName);
91      if (!ok) {
92        Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
93                      "DrgDeleteStrHandle(0x%x) hstrTargetName",pDItem->hstrTargetName);
94      }
95    }
96  } // for
97# endif
98  if (!DrgFreeDraginfo(pDInfo)) {
99    // fixme to find callers responsible for PMERR_SOURCE_SAME_AS_TARGET
100    if ((WinGetLastError(WinQueryAnchorBlock(hwnd)) & 0xffff) != PMERR_SOURCE_SAME_AS_TARGET) {
101      Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
102               "DrgFreeDraginfo");
103    }
104    else
105      DbgMsg(pszSrcFile, __LINE__, "DrgFreeDraginfo PMERR_SOURCE_SAME_AS_TARGET");
106  }
107}
108
109HWND DragOne(HWND hwndCnr, HWND hwndObj, CHAR * filename, BOOL moveok)
110{
111
112  DRAGITEM DItem;
113  HWND hDrop = 0;
114  DRAGIMAGE fakeicon;
115  PDRAGINFO pDInfo;
116  FILESTATUS3 fs3;
117  CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
118
119  if (filename && *filename) {
120    if ((IsRoot(filename) && IsValidDrive(*filename)) ||
121        !DosQueryPathInfo(filename, FIL_STANDARD, &fs3, sizeof(fs3))) {
122      strcpy(szDir, filename);
123      p = szDir;
124      while (*p) {
125        if (*p == '/')
126          *p = '\\';
127        p++;
128      }
129      p = strrchr(szDir, '\\');
130      if (p) {
131        *p = 0;
132        p++;
133        strcpy(szFile, p);
134        strcat(szDir, "\\");
135      }
136      else {
137        strcpy(szFile, filename);
138        *szDir = 0;
139      }
140      memset(&fakeicon, 0, sizeof(DRAGIMAGE));
141      fakeicon.hImage = (IsRoot(filename) ||
142                         (fs3.attrFile & FILE_DIRECTORY) != 0) ?
143        hptrDir : hptrFile;
144      memset(&DItem, 0, sizeof(DRAGITEM));
145      DItem.hwndItem = (hwndObj) ? hwndObj : hwndCnr;   // Initialize DRAGITEM
146      // DItem.hwndItem = hwndCnr;
147      DItem.ulItemID = 1;
148      DItem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
149      DItem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
150      DItem.hstrContainerName = DrgAddStrHandle(szDir);
151      DItem.hstrSourceName = DrgAddStrHandle(szFile);
152      if (!DItem.hstrSourceName)
153         Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
154         "DrgQueryStrName");
155      DItem.hstrTargetName = DrgAddStrHandle(szFile);
156      DItem.fsControl = 0;
157      if (IsRoot(filename) || (fs3.attrFile & FILE_DIRECTORY) != 0)
158        DItem.fsControl |= DC_CONTAINER;
159      if (IsFullName(filename) &&
160          (driveflags[toupper(*filename) - 'A'] & DRIVE_REMOVABLE))
161        DItem.fsControl |= DC_REMOVEABLEMEDIA;
162      DItem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
163      if (moveok && IsFullName(filename) &&
164          !(driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
165        DItem.fsSupportedOps |= DO_MOVEABLE;
166      if (IsRoot(filename))
167        DItem.fsSupportedOps = DO_LINKABLE;
168      fakeicon.cb = sizeof(DRAGIMAGE);
169      fakeicon.cptl = 0;
170      fakeicon.fl = DRG_ICON;
171      fakeicon.sizlStretch.cx = 32;
172      fakeicon.sizlStretch.cy = 32;
173      fakeicon.cxOffset = -16;
174      fakeicon.cyOffset = 0;
175      pDInfo = DrgAllocDraginfo(1);
176      if (pDInfo) {
177        if (IsFullName(filename) &&
178            (driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
179          pDInfo->usOperation = DO_COPY;
180        else
181          pDInfo->usOperation = DO_DEFAULT;
182        if (IsRoot(filename))
183          pDInfo->usOperation = DO_LINK;
184        pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
185        // pDInfo->hwndSource = hwndCnr;
186        DrgSetDragitem(pDInfo, &DItem, sizeof(DRAGITEM), 0);
187        WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
188        hDrop = DrgDrag(hwndCnr,
189                        pDInfo,
190                        &fakeicon,
191                        1,              // DragImage count
192                        VK_ENDDRAG,     // Drag end button
193                        NULL);
194        if (hDrop == NULLHANDLE)
195          FreeDragInfoData(hwndCnr, pDInfo);
196        WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
197      }
198    }
199  }
200  return hDrop;
201}
202
203HWND DoFileDrag(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd, CHAR * arcfile,
204                CHAR * directory, BOOL moveok)
205{
206  // Drag files from a container
207
208  BOOL isdir, rooting = FALSE;
209  PCNRITEM pci;
210  CHAR *p;
211  INT attribute = CRA_CURSORED;
212  PDRAGINFO pDInfo = NULL;
213  DRAGITEM **ppDItem = NULL, **ppDITest;
214  DRAGITEM *pDItem;
215  PCNRITEM pciRec = (PCNRITEM) pcd->pRecord;
216  HWND hDrop = NULLHANDLE;
217  ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
218  CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
219  DRAGIMAGE *paDImgIcons = NULL, *pDImg, dimgFakeIcon;
220  BOOL ok;
221  UINT c;
222
223  static BOOL first_drag = TRUE;
224
225  // fixme to be multi-drag safe - count needs to be in DCD etc. and passed to UnHilite
226  NumItemsToUnhilite = 0;
227  if (!pciRec && directory && *directory)
228    return DragOne(hwndCnr, hwndObj, directory, moveok);
229
230  if (!pciRec) {
231    pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
232                                MPFROMLONG(CMA_FIRST),
233                                MPFROMSHORT(attribute));
234    if (pci && (INT) pci > -1) {
235      if (pci->rc.flRecordAttr & CRA_SELECTED) {
236        attribute = CRA_SELECTED;
237        pci =
238          WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
239                     MPFROMSHORT(attribute));
240      }
241    }
242  }
243  else {
244    pci = pciRec;
245    attribute = (pci->rc.flRecordAttr & CRA_SELECTED) ? CRA_SELECTED : 0;
246    if (attribute) {
247      pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
248                       MPFROMSHORT(attribute));
249    }
250  }
251
252  ulSelect = 0;
253  while (pci && (INT) pci > -1) {
254    if (!(pci->rc.flRecordAttr & CRA_FILTERED)) {
255      if (IsRoot(pci->szFileName) && !IsValidDrive(*pci->szFileName))
256        goto Continuing;
257      if (!arcfile) {
258        strcpy(szBuffer, pci->szFileName);
259        p = strrchr(szBuffer, '\\');
260        if (p) {
261          p++;
262          strcpy(szFile, p);
263          *p = 0;
264        }
265        else
266          goto Continuing;
267      }
268      else
269        strcpy(szFile, pci->szFileName);
270    }
271    if (!arcfile) {
272      // Filesystem object
273      isdir = pci->attrFile & FILE_DIRECTORY;
274      // fixme to expand smarter - expand fast at first - do same for similar code
275      if (ulNumfiles + 2 > ulNumDIAlloc) {
276        // Expand
277        if (!paDImgIcons) {
278          pDImg =
279            xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
280                     pszSrcFile, __LINE__);
281          if (!pDImg)
282            break;
283          paDImgIcons = pDImg;
284        }
285        else if (!ulNumIcon) {
286          pDImg = &paDImgIcons[ulNumfiles];
287          pDImg->cb = sizeof(DRAGIMAGE);
288          pDImg->cptl = 0;
289          pDImg->hImage = hptrLast;
290          pDImg->fl = DRG_ICON;
291          pDImg->sizlStretch.cx = 32;
292          pDImg->sizlStretch.cy = 32;
293          pDImg->cxOffset = -16 + (ulNumfiles * 4);
294          pDImg->cyOffset = 0 + (ulNumfiles * 7);
295          ulNumIcon = ulNumfiles + 1;
296        }
297        ppDITest =
298          xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
299                   pszSrcFile, __LINE__);
300        if (!ppDITest)
301          break;
302        ppDItem = ppDITest;
303        ulNumDIAlloc += 4L;
304      }
305      pDItem = xmalloc(sizeof(DRAGITEM), pszSrcFile, __LINE__);
306      if (!pDItem)
307        break;                          // Already complained
308      ppDItem[ulNumfiles] = pDItem;
309      if (!ulNumIcon) {
310        pDImg = &paDImgIcons[ulNumfiles];
311        pDImg->cb = sizeof(DRAGIMAGE);
312        pDImg->cptl = 0;
313        pDImg->hImage = pci->rc.hptrIcon;
314        if (!pDImg->hImage)
315          pDImg->hImage = isdir ? hptrDir : hptrFile;
316        pDImg->fl = DRG_ICON;
317        pDImg->sizlStretch.cx = 32;
318        pDImg->sizlStretch.cy = 32;
319        pDImg->cxOffset = -16 + (ulNumfiles * 3);
320        pDImg->cyOffset = 0 + (ulNumfiles * 6);
321      }
322      // Initialize DRAGITEM
323      memset(pDItem, 0, sizeof(DRAGITEM));
324      pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
325      pDItem->hwndItem = hwndCnr;
326      pDItem->ulItemID = (ULONG) pci;
327      pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
328      ok = pDItem->hstrType;
329      pDItem->hstrRMF = DrgAddStrHandle(DRMDRFLIST);
330      ok = ok && pDItem->hstrRMF;
331      pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
332      ok = ok && pDItem->hstrContainerName;
333      pDItem->hstrSourceName = DrgAddStrHandle(szFile);
334      ok = ok && pDItem->hstrSourceName;
335      pDItem->hstrTargetName = DrgAddStrHandle(szFile);
336      ok = ok && pDItem->hstrTargetName;
337      if (!ok) {
338        DbgMsg(pszSrcFile, __LINE__, "DrgAddStrHandle failed at %lu for %s", ulNumfiles, szFile);
339        // If we have string handle add overflow, release corrupt DragItem
340        // We release 3 more to work around 1st time drag failure reported by Gregg
341        // fixme to know why this happens - PM may need to create a handle?
342        c = first_drag ? 4 : 1;
343        first_drag = FALSE;
344        for (; c > 0 && ulNumfiles > 0; c--) {
345          if (pDItem->hstrType)
346            DrgDeleteStrHandle(pDItem->hstrType);
347          if (pDItem->hstrRMF)
348            DrgDeleteStrHandle(pDItem->hstrRMF);
349          if (pDItem->hstrContainerName)
350            DrgDeleteStrHandle(pDItem->hstrContainerName);
351          if (pDItem->hstrSourceName)
352            DrgDeleteStrHandle(pDItem->hstrSourceName);
353          if (pDItem->hstrTargetName)
354            DrgDeleteStrHandle(pDItem->hstrTargetName);
355          xfree(pDItem);
356          // Last item not yet count so only decrement by one less than loop count
357          // Unhilite code will adjust this when unhighliting
358          if (c > 1) {
359            ulNumfiles--;
360            pDItem = ppDItem[ulNumfiles];
361          }
362        }
363        // Set count to actual count + 1 to ensure count non-zero on any failure
364        NumItemsToUnhilite = ulNumfiles + 1;
365        break;
366      }
367      pDItem->fsControl = isdir ? DC_CONTAINER : 0;
368      if (IsFullName(pci->szFileName) &&
369          (driveflags[toupper(*pci->szFileName) - 'A'] & DRIVE_REMOVABLE))
370        pDItem->fsControl |= DC_REMOVEABLEMEDIA;
371      pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
372      if (moveok && IsFullName(pci->szFileName) &&
373          !(driveflags[toupper(*pci->szFileName) - 'A'] &
374            DRIVE_NOTWRITEABLE))
375        pDItem->fsSupportedOps |= DO_MOVEABLE;
376      if (IsRoot(pci->szFileName)) {
377        pDItem->fsSupportedOps = DO_LINKABLE;
378        rooting = TRUE;
379      }
380      ulNumfiles++;
381      // ppDItem[ulNumfiles] = NULL;    // Why bother - can't we count - fixme to be gone?
382    } // if filesystem object
383    else {
384      // Archive object
385      if (ulNumfiles + 3L > ulNumDIAlloc) {
386        ppDITest =
387          xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 5L),
388                   pszSrcFile, __LINE__);
389        if (!ppDITest)
390          break;
391        ppDItem = ppDITest;
392        ulNumDIAlloc += 5L;
393      }
394      pDItem = xmalloc(sizeof(DRAGITEM), pszSrcFile, __LINE__);
395      if (!pDItem)
396        break;
397      ppDItem[ulNumfiles] = pDItem;
398      dimgFakeIcon.hImage = hptrFile;
399      // Initialize DRAGITEM
400      memset(pDItem, 0, sizeof(DRAGITEM));
401      pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
402      pDItem->hwndItem = hwndCnr;
403      pDItem->ulItemID = (ULONG) pci;
404      pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
405      ok = pDItem->hstrType;
406      pDItem->hstrRMF = DrgAddStrHandle(DRMDRFOS2FILE);
407      ok = ok && pDItem->hstrRMF;
408      pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
409      ok = ok && pDItem->hstrContainerName;
410      pDItem->hstrSourceName = DrgAddStrHandle(szFile);
411      ok = ok && pDItem->hstrSourceName;
412      pDItem->hstrTargetName = DrgAddStrHandle(szFile);
413      ok = ok && pDItem->hstrTargetName;
414      if (!ok){
415        if (pDItem->hstrType)
416          DrgDeleteStrHandle(pDItem->hstrType);
417        if (pDItem->hstrRMF)
418          DrgDeleteStrHandle(pDItem->hstrRMF);
419        if (pDItem->hstrContainerName)
420          DrgDeleteStrHandle(pDItem->hstrContainerName);
421        if (pDItem->hstrSourceName)
422          DrgDeleteStrHandle(pDItem->hstrSourceName);
423        if (pDItem->hstrTargetName)
424          DrgDeleteStrHandle(pDItem->hstrTargetName);
425        xfree(pDItem);
426        NumItemsToUnhilite = ulNumfiles + 1;    // +1 to ensure non-zero
427        break;
428     }
429      pDItem->fsControl = DC_PREPARE;
430      if (IsFullName(arcfile) &&
431          (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
432        pDItem->fsControl |= DC_REMOVEABLEMEDIA;
433      pDItem->fsSupportedOps = DO_COPYABLE;
434      ulNumfiles++;
435
436      pDItem = xmalloc(sizeof(DRAGITEM), pszSrcFile, __LINE__);
437      if (pDItem) {
438        ppDItem[ulNumfiles] = pDItem;
439        dimgFakeIcon.hImage = hptrFile;
440        // Initialize DRAGITEM
441        memset(pDItem, 0, sizeof(DRAGITEM));
442        pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
443        pDItem->hwndItem = hwndCnr;
444        pDItem->ulItemID = ulSelect++;
445        pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
446        ok = ok && pDItem->hstrType;
447        pDItem->hstrRMF = DrgAddStrHandle(DRMDRFFM2ARC);
448        ok = ok && pDItem->hstrRMF;
449        pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
450        ok = ok && pDItem->hstrContainerName;
451        pDItem->hstrSourceName = DrgAddStrHandle(szFile);
452        ok = ok && pDItem->hstrSourceName;
453        pDItem->hstrTargetName = DrgAddStrHandle(szFile);
454        ok = ok && pDItem->hstrTargetName;
455        if (!ok) {
456          DbgMsg(pszSrcFile, __LINE__, "DrgAddStrHandle failed at %lu for %s", ulNumfiles, szFile);
457          // If we have string handle add overflow, release corrupt DragItem
458          // We release 3 more to work around 1st time drag failure reported by Gregg
459          // fixme to know why this happens - PM may need to create a handle?
460          c = first_drag ? 4 : 1;
461          first_drag = FALSE;
462          for (; c > 0 && ulNumfiles > 0; c--) {
463            if (pDItem->hstrType)
464              DrgDeleteStrHandle(pDItem->hstrType);
465            if (pDItem->hstrRMF)
466              DrgDeleteStrHandle(pDItem->hstrRMF);
467            if (pDItem->hstrContainerName)
468              DrgDeleteStrHandle(pDItem->hstrContainerName);
469            if (pDItem->hstrSourceName)
470              DrgDeleteStrHandle(pDItem->hstrSourceName);
471            if (pDItem->hstrTargetName)
472              DrgDeleteStrHandle(pDItem->hstrTargetName);
473            xfree(pDItem);
474            // Last item not yet count so only decrement by one less than loop count
475            if (c > 1) {
476              ulNumfiles--;
477              pDItem = ppDItem[ulNumfiles];
478            }
479          }
480          // Set count to actual count + 1 to ensure count non-zero on any failure
481          // Unhilite code will adjust this when unhighliting
482          NumItemsToUnhilite = ulNumfiles + 1;
483          break;
484        }
485        pDItem->fsControl = 0;
486        if (IsFullName(arcfile) &&
487            (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
488          pDItem->fsControl |= DC_REMOVEABLEMEDIA;
489        pDItem->fsSupportedOps = DO_COPYABLE;
490        ulNumfiles++;
491      }
492      // ppDItem[ulNumfiles] = NULL;    // Why bother - fixme to be gone?
493    } // if archive object
494    WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
495               MPFROM2SHORT(TRUE, CRA_SOURCE));
496
497  Continuing:
498
499    if (!attribute)
500      break;
501    pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
502                     MPFROMSHORT(attribute));
503  } // while
504
505  if (ulNumfiles) {
506    pDInfo = DrgAllocDraginfo(ulNumfiles);
507    if (pDInfo) {
508      if ((arcfile && *arcfile) || (IsFullName(szBuffer) &&
509                                    (driveflags[toupper(*szBuffer) - 'A'] &
510                                     DRIVE_NOTWRITEABLE)))
511        pDInfo->usOperation = DO_COPY;
512      else
513        pDInfo->usOperation = DO_DEFAULT;
514      if ((!arcfile || !*arcfile) && rooting)
515        pDInfo->usOperation = DO_LINK;
516      pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
517      // pDInfo->hwndSource = hwndCnr;
518      for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
519        DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect);
520        xfree(ppDItem[ulSelect]);
521      }
522#ifdef __DEBUG_ALLOC__
523      _heap_check();
524#endif
525      xfree(ppDItem);
526      ppDItem = NULL;                   // Remember gone
527      DosPostEventSem(CompactSem);
528
529      if (arcfile) {
530        dimgFakeIcon.cb = sizeof(DRAGIMAGE);
531        dimgFakeIcon.cptl = 0;
532        if (ulNumfiles > 1)
533          dimgFakeIcon.hImage = hptrFile;
534        dimgFakeIcon.fl = DRG_ICON;
535        dimgFakeIcon.sizlStretch.cx = 32;
536        dimgFakeIcon.sizlStretch.cy = 32;
537        dimgFakeIcon.cxOffset = -16;
538        dimgFakeIcon.cyOffset = 0;
539        paDImgIcons = &dimgFakeIcon;
540      }
541      if (!arcfile) {
542        if (!ulNumIcon)
543          ulNumIcon = ulNumfiles;
544      }
545      else
546        ulNumIcon = 1;
547
548      WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
549      hDrop = DrgDrag(hwndCnr,
550                      pDInfo,
551                      paDImgIcons,
552                      ulNumIcon,
553                      VK_ENDDRAG,       // Drag end button
554                      NULL);
555      WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
556    }
557  }
558
559  if (hDrop == NULLHANDLE ) {
560    NumItemsToUnhilite = 0;
561    if (pDInfo)
562      FreeDragInfoData(hwndCnr, pDInfo);
563  }
564
565  if (ppDItem)
566    xfree(ppDItem);
567  if (paDImgIcons && paDImgIcons != &dimgFakeIcon)
568    xfree(paDImgIcons);
569  DosPostEventSem(CompactSem);
570  MarkAll(hwndCnr, TRUE, FALSE, TRUE);
571  return hDrop;
572}
573
574HWND DragList(HWND hwnd, HWND hwndObj, CHAR ** list, BOOL moveok)
575{
576  // Drag a linked list of files
577
578  BOOL isdir;
579  register CHAR *p;
580  PDRAGINFO pDInfo = NULL;
581  DRAGITEM **ppDItem = NULL, **ppDITest;
582  DRAGITEM *pDItem;
583  HWND hDrop = (HWND) 0;
584  ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
585  CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
586  DRAGIMAGE *paDImgIcons = NULL, *pDImg;
587  FILESTATUS3 fs3;
588  BOOL ok;
589
590  if (!list || !list[0])
591    return hDrop;
592  for (ulSelect = 0; list[ulSelect]; ulSelect++) {
593    if ((!IsRoot(list[ulSelect]) || !IsValidDrive(*list[ulSelect])) &&
594        DosQueryPathInfo(list[ulSelect], FIL_STANDARD, &fs3, sizeof(fs3)))
595      continue;
596    strcpy(szBuffer, list[ulSelect]);
597    p = strrchr(szBuffer, '\\');
598    if (p) {
599      p++;
600      strcpy(szFile, p);
601      *p = 0;
602    }
603    else
604      continue;
605    if (*szFile) {
606      isdir = IsRoot(list[ulSelect]) || fs3.attrFile & FILE_DIRECTORY;
607      // fixme to expand smarter - expand fast at first - do same for similar code
608      if (ulNumfiles + 2 > ulNumDIAlloc) {
609        if (!paDImgIcons) {
610          pDImg =
611            xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
612                     pszSrcFile, __LINE__);
613          if (!pDImg)
614            break;
615          paDImgIcons = pDImg;
616        }
617        else if (!ulNumIcon) {
618          pDImg = &paDImgIcons[ulNumfiles];
619          pDImg->cb = sizeof(DRAGIMAGE);
620          pDImg->cptl = 0;
621          pDImg->hImage = hptrLast;
622          pDImg->fl = DRG_ICON;
623          pDImg->sizlStretch.cx = 32;
624          pDImg->sizlStretch.cy = 32;
625          pDImg->cxOffset = -16 + (ulNumfiles * 4);
626          pDImg->cyOffset = 0 + (ulNumfiles * 7);
627          ulNumIcon = ulNumfiles + 1;
628        }
629        ppDITest =
630          xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
631                   pszSrcFile, __LINE__);
632        if (!ppDITest)
633          break;
634        ppDItem = ppDITest;
635        ulNumDIAlloc += 4L;
636      }
637      pDItem = xmalloc(sizeof(DRAGITEM), pszSrcFile, __LINE__);
638      if (!pDItem)
639        break;
640      ppDItem[ulNumfiles] = pDItem;
641      if (!ulNumIcon) {
642        pDImg = &paDImgIcons[ulNumfiles];
643        pDImg->cb = sizeof(DRAGIMAGE);
644        pDImg->cptl = 0;
645        pDImg->hImage = isdir ? hptrDir : hptrFile;
646        pDImg->fl = DRG_ICON;
647        pDImg->sizlStretch.cx = 32;
648        pDImg->sizlStretch.cy = 32;
649        pDImg->cxOffset = -16 + (ulNumfiles * 3);
650        pDImg->cyOffset = 0 + (ulNumfiles * 6);
651      }
652      memset(pDItem, 0, sizeof(DRAGITEM));
653      pDItem->hwndItem = (hwndObj) ? hwndObj : hwnd;
654      // pDItem->hwndItem = hwnd;
655      pDItem->ulItemID = (ULONG) ulSelect;
656      pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
657      ok = pDItem->hstrType;
658      pDItem->hstrRMF = DrgAddStrHandle(DRMDRFLIST);
659      ok = ok && pDItem->hstrRMF;
660      pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
661      ok = ok && pDItem->hstrContainerName;
662      pDItem->hstrSourceName = DrgAddStrHandle(szFile);
663      ok = ok && pDItem->hstrSourceName;
664      pDItem->hstrTargetName = DrgAddStrHandle(szFile);
665      ok = ok && pDItem->hstrTargetName;
666      if (!ok) {
667        if (pDItem->hstrType)
668          DrgDeleteStrHandle(pDItem->hstrType);
669        if (pDItem->hstrRMF)
670          DrgDeleteStrHandle(pDItem->hstrRMF);
671        if (pDItem->hstrContainerName)
672          DrgDeleteStrHandle(pDItem->hstrContainerName);
673        if (pDItem->hstrSourceName)
674          DrgDeleteStrHandle(pDItem->hstrSourceName);
675        if (pDItem->hstrTargetName)
676          DrgDeleteStrHandle(pDItem->hstrTargetName);
677        xfree(pDItem);
678        // pDItem = NULL;       // Why bother, we can count - fixme to be gone
679        NumItemsToUnhilite = ulNumfiles + 1;
680        break;
681      }
682      pDItem->fsControl = isdir ? DC_CONTAINER : 0;
683      if (IsFullName(list[ulSelect]) &&
684          (driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_REMOVABLE))
685        pDItem->fsControl |= DC_REMOVEABLEMEDIA;
686      pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
687      if (moveok && IsFullName(list[ulSelect]) &&
688          !(driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_NOTWRITEABLE))
689        pDItem->fsSupportedOps |= DO_MOVEABLE;
690      if (IsRoot(list[ulSelect]))
691        pDItem->fsControl = DO_LINKABLE;
692      ulNumfiles++;
693      // ppDItem[ulNumfiles] = NULL;    // Why bother - fixme to be gone
694    }
695  } // for
696  if (ulNumfiles) {
697    pDInfo = DrgAllocDraginfo(ulNumfiles);
698    if (pDInfo) {
699      if ((IsFullName(szBuffer) &&
700           (driveflags[toupper(*szBuffer) - 'A'] & DRIVE_NOTWRITEABLE)))
701        pDInfo->usOperation = DO_COPY;
702      else
703        pDInfo->usOperation = DO_DEFAULT;
704      if (IsRoot(list[0]))
705        pDInfo->usOperation = DO_LINK;
706      pDInfo->hwndSource = hwndObj ? hwndObj : hwnd;
707      // pDInfo->hwndSource = hwnd;
708      for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
709        if (!DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect)) {
710          Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
711                   "DrgSetDragitem");
712        }
713        free(ppDItem[ulSelect]);
714      } // for
715#ifdef __DEBUG_ALLOC__
716      _heap_check();
717#endif
718      free(ppDItem);
719      ppDItem = NULL;                   // Remember gone
720      DosPostEventSem(CompactSem);
721
722      if (!ulNumIcon)
723        ulNumIcon = ulNumfiles;
724
725      WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
726      hDrop = DrgDrag(hwnd,
727                      pDInfo,
728                      paDImgIcons,
729                      ulNumIcon,
730                      VK_ENDDRAG,       // Drag end button
731                      (PVOID) NULL);
732      if (hDrop == NULLHANDLE) {
733        NumItemsToUnhilite = 0;
734        FreeDragInfoData(hwnd, pDInfo);
735      }
736      xfree(paDImgIcons);
737      paDImgIcons = NULL;               // Remember gone
738      WinSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
739      DosPostEventSem(CompactSem);
740    }
741  }
742  if (ppDItem)
743    free(ppDItem);
744  if (paDImgIcons)
745    free(paDImgIcons);
746  return hDrop;
747}
748
749#ifdef NEVER                            // fixme to be enabled someday?
750
751BOOL PickUp(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd)
752{
753
754  PCNRITEM pci;
755  BOOL loop = TRUE;
756  PDRAGINFO pdinfoOld = NULL, pdinfoCurrent = NULL;
757  ULONG cditem = 0;
758  DRAGITEM ditem;
759  DRAGIMAGE dimgFakeIcon;
760  CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
761
762  pci = (PCNRITEM) pcd->pRecord;
763  if (pci && (INT) pci != -1) {
764    if (pci->rc.flRecordAttr & CRA_SELECTED) {
765      loop = TRUE;
766      pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
767                       MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_SELECTED));
768    }
769    while (pci && (INT) pci != -1 && *pci->szFileName) {
770      if (pdinfoOld || DrgQueryDragStatus() & DGS_LAZYDRAGINPROGRESS) {
771        if (!pdinfoOld)
772          pdinfoOld = DrgQueryDraginfoPtr(NULL);
773        if (pdinfoOld) {
774          cditem = pdinfoOld->cditem + 1;
775          pdinfoCurrent = DrgReallocDraginfo(pdinfoOld, cditem);
776          pdinfoOld = pdinfoCurrent;
777        }
778      }
779      else
780        pdinfoCurrent = pdinfoOld = DrgAllocDraginfo(1);
781      if (pdinfoCurrent) {
782        strcpy(szDir, pci->szFileName);
783        p = szDir;
784        while (*p) {
785          if (*p == '/')
786            *p = '\\';
787          p++;
788        }
789        p = strrchr(szDir, '\\');
790        if (p) {
791          *p = 0;
792          p++;
793          strcpy(szFile, p);
794          strcat(szDir, "\\");
795        }
796        else {
797          strcpy(szFile, pci->szFileName);
798          *szDir = 0;
799        }
800        ditem.ulItemID = (ULONG) pci;
801        ditem.hwndItem = (hwndObj) ? hwndObj : hwndCnr;
802        ditem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
803        ditem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
804        ditem.hstrContainerName = DrgAddStrHandle(szDir);
805        ditem.hstrSourceName = DrgAddStrHandle(szFile);
806        // fixme to check better if code ever enabled
807        if (!ditem.hstrSourceName) {
808          Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
809                   "DrgAddStrHandle");
810        }
811        ditem.hstrTargetName = DrgAddStrHandle(szFile);
812        ditem.fsControl = 0;
813        if (IsRoot(pci->szFileName) || (pci->attrFile & FILE_DIRECTORY) != 0)
814          ditem.fsControl |= DC_CONTAINER;
815        if (IsFullName(pci->szFileName) &&
816            (driveflags[toupper(*pci->szFileName) - 'A'] & DRIVE_REMOVABLE))
817          ditem.fsControl |= DC_REMOVEABLEMEDIA;
818        ditem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
819        if (IsFullName(pci->szFileName) &&
820            !(driveflags[toupper(*pci->szFileName) - 'A'] &
821              DRIVE_NOTWRITEABLE))
822          ditem.fsSupportedOps |= DO_MOVEABLE;
823        if (IsRoot(pci->szFileName))
824          ditem.fsSupportedOps = DO_LINKABLE;
825        memset(&dimgFakeIcon, 0, sizeof(DRAGIMAGE));
826        dimgFakeIcon.hImage = pci->rc.hptrIcon;
827        dimgFakeIcon.cb = sizeof(DRAGIMAGE);
828        dimgFakeIcon.cptl = 0;
829        dimgFakeIcon.fl = DRG_ICON;
830        dimgFakeIcon.sizlStretch.cx = 32;
831        dimgFakeIcon.sizlStretch.cy = 32;
832        dimgFakeIcon.cxOffset = -16;
833        dimgFakeIcon.cyOffset = 0;
834        if (IsFullName(pci->szFileName) &&
835            (driveflags[toupper(*pci->szFileName) - 'A'] &
836             DRIVE_NOTWRITEABLE))
837          pdinfoCurrent->usOperation = DO_COPY;
838        else
839          pdinfoCurrent->usOperation = DO_DEFAULT;
840        if (IsRoot(pci->szFileName))
841          pdinfoCurrent->usOperation = DO_LINK;
842        pdinfoCurrent->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
843        DrgSetDragitem(pdinfoCurrent, &ditem, sizeof(DRAGITEM), cditem);
844      }
845      if (!loop)
846        break;
847      pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
848                       MPFROMP(pci), MPFROMSHORT(CRA_SELECTED));
849    } // while
850    if (pdinfoCurrent)
851      return DrgLazyDrag(hwndCnr, pdinfoCurrent, &dimgFakeIcon, 1, NULL);
852  }
853  return FALSE;
854}
855
856#endif // NEVER
Note: See TracBrowser for help on using the repository browser.