source: trunk/dll/draglist.c @ 672

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

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

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