source: trunk/dll/draglist.c@ 628

Last change on this file since 628 was 628, checked in by Steven Levine, 18 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.