source: trunk/dll/draglist.c@ 618

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