source: trunk/dll/draglist.c@ 959

Last change on this file since 959 was 959, checked in by Gregg Young, 18 years ago

Use xfree where appropriate. Check that buffer exists following all xmallocs. Stopped at eas.c with xfree checking. One remaining xmalloc without test in dirsize.c

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.5 KB
Line 
1
2/***********************************************************************
3
4 $Id: draglist.c 959 2008-02-18 00:47:31Z gyoung $
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 05 Jul 07 FreeDragInfoData: suppress PMERR_SOURCE_SAME_AS_TARGET notices
22 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
23
24***********************************************************************/
25
26#include <stdlib.h>
27#include <string.h>
28#include <ctype.h>
29
30#define INCL_DOS
31#define INCL_WIN
32#define INCL_SHLERRORS
33#define INCL_LONGLONG
34
35#include "errutil.h" // Dos_Error...
36#include "fm3dll.h"
37
38static PSZ pszSrcFile = __FILE__;
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 // PMERR_SOURCE_SAME_AS_TARGET is not an error if dragging within same fm/2 process
101 if (!IsFm2Window(pDInfo->hwndSource, FALSE) ||
102 (WinGetLastError(WinQueryAnchorBlock(hwnd)) & 0xffff) != PMERR_SOURCE_SAME_AS_TARGET)
103 {
104 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__, "DrgFreeDraginfo");
105 }
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 DIRCNRDATA *dcd;
223
224 static BOOL first_drag = TRUE;
225
226 // Count items to unhilite, pass to UnHilite when partial unhilite required
227 dcd = INSTDATA(hwndCnr);
228 dcd->ulItemsToUnHilite = 0;
229 if (!pciRec && directory && *directory)
230 return DragOne(hwndCnr, hwndObj, directory, moveok);
231
232 if (!pciRec) {
233 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
234 MPFROMLONG(CMA_FIRST),
235 MPFROMSHORT(attribute));
236 if (pci && (INT) pci > -1) {
237 if (pci->rc.flRecordAttr & CRA_SELECTED) {
238 attribute = CRA_SELECTED;
239 pci =
240 WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
241 MPFROMSHORT(attribute));
242 }
243 }
244 }
245 else {
246 pci = pciRec;
247 attribute = (pci->rc.flRecordAttr & CRA_SELECTED) ? CRA_SELECTED : 0;
248 if (attribute) {
249 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
250 MPFROMSHORT(attribute));
251 }
252 }
253
254 ulSelect = 0;
255 while (pci && (INT) pci > -1) {
256 if (!(pci->rc.flRecordAttr & CRA_FILTERED)) {
257 if (IsRoot(pci->pszFileName) && !IsValidDrive(*pci->pszFileName))
258 goto Continuing;
259 if (!arcfile) {
260 strcpy(szBuffer, pci->pszFileName);
261 p = strrchr(szBuffer, '\\');
262 if (p) {
263 p++;
264 strcpy(szFile, p);
265 *p = 0;
266 }
267 else
268 goto Continuing;
269 }
270 else
271 strcpy(szFile, pci->pszFileName);
272 }
273 if (!arcfile) {
274 // Filesystem object
275 isdir = pci->attrFile & FILE_DIRECTORY;
276 // fixme to expand smarter - expand fast at first - do same for similar code
277 if (ulNumfiles + 2 > ulNumDIAlloc) {
278 // Expand
279 if (!paDImgIcons) {
280 pDImg =
281 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
282 pszSrcFile, __LINE__);
283 if (!pDImg)
284 break;
285 paDImgIcons = pDImg;
286 }
287 else if (!ulNumIcon) {
288 pDImg = &paDImgIcons[ulNumfiles];
289 pDImg->cb = sizeof(DRAGIMAGE);
290 pDImg->cptl = 0;
291 pDImg->hImage = hptrLast;
292 pDImg->fl = DRG_ICON;
293 pDImg->sizlStretch.cx = 32;
294 pDImg->sizlStretch.cy = 32;
295 pDImg->cxOffset = -16 + (ulNumfiles * 4);
296 pDImg->cyOffset = 0 + (ulNumfiles * 7);
297 ulNumIcon = ulNumfiles + 1;
298 }
299 ppDITest =
300 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
301 pszSrcFile, __LINE__);
302 if (!ppDITest)
303 break;
304 ppDItem = ppDITest;
305 ulNumDIAlloc += 4L;
306 }
307 pDItem = xmalloc(sizeof(DRAGITEM), pszSrcFile, __LINE__);
308 if (!pDItem)
309 break; // Already complained
310 ppDItem[ulNumfiles] = pDItem;
311 if (!ulNumIcon) {
312 pDImg = &paDImgIcons[ulNumfiles];
313 pDImg->cb = sizeof(DRAGIMAGE);
314 pDImg->cptl = 0;
315 pDImg->hImage = pci->rc.hptrIcon;
316 if (!pDImg->hImage)
317 pDImg->hImage = isdir ? hptrDir : hptrFile;
318 pDImg->fl = DRG_ICON;
319 pDImg->sizlStretch.cx = 32;
320 pDImg->sizlStretch.cy = 32;
321 pDImg->cxOffset = -16 + (ulNumfiles * 3);
322 pDImg->cyOffset = 0 + (ulNumfiles * 6);
323 }
324 // Initialize DRAGITEM
325 memset(pDItem, 0, sizeof(DRAGITEM));
326 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
327 pDItem->hwndItem = hwndCnr;
328 pDItem->ulItemID = (ULONG) pci;
329 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
330 ok = pDItem->hstrType;
331 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFLIST);
332 ok = ok && pDItem->hstrRMF;
333 pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
334 ok = ok && pDItem->hstrContainerName;
335 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
336 ok = ok && pDItem->hstrSourceName;
337 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
338 ok = ok && pDItem->hstrTargetName;
339 if (!ok) {
340 DbgMsg(pszSrcFile, __LINE__, "DrgAddStrHandle failed at %lu for %s", ulNumfiles, szFile);
341 // If we have string handle add overflow, release corrupt DragItem
342 // We release 3 more to work around 1st time drag failure reported by Gregg
343 // fixme to know why this happens - PM may need to create a handle?
344 c = first_drag ? 4 : 1;
345 first_drag = FALSE;
346 for (; c > 0 && ulNumfiles > 0; c--) {
347 if (pDItem->hstrType)
348 DrgDeleteStrHandle(pDItem->hstrType);
349 if (pDItem->hstrRMF)
350 DrgDeleteStrHandle(pDItem->hstrRMF);
351 if (pDItem->hstrContainerName)
352 DrgDeleteStrHandle(pDItem->hstrContainerName);
353 if (pDItem->hstrSourceName)
354 DrgDeleteStrHandle(pDItem->hstrSourceName);
355 if (pDItem->hstrTargetName)
356 DrgDeleteStrHandle(pDItem->hstrTargetName);
357 xfree(pDItem);
358 // Last item not yet count so only decrement by one less than loop count
359 // Unhilite code will adjust this when unhighliting
360 if (c > 1) {
361 ulNumfiles--;
362 pDItem = ppDItem[ulNumfiles];
363 }
364 }
365 // Set count to actual count + 1 to ensure count non-zero on any failure
366 dcd->ulItemsToUnHilite = ulNumfiles + 1;
367 break;
368 }
369 pDItem->fsControl = isdir ? DC_CONTAINER : 0;
370 if (IsFullName(pci->pszFileName) &&
371 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
372 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
373 pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
374 if (moveok && IsFullName(pci->pszFileName) &&
375 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
376 DRIVE_NOTWRITEABLE))
377 pDItem->fsSupportedOps |= DO_MOVEABLE;
378 if (IsRoot(pci->pszFileName)) {
379 pDItem->fsSupportedOps = DO_LINKABLE;
380 rooting = TRUE;
381 }
382 ulNumfiles++;
383 // ppDItem[ulNumfiles] = NULL; // Why bother - can't we count - fixme to be gone?
384 } // if filesystem object
385 else {
386 // Archive object
387 if (ulNumfiles + 3L > ulNumDIAlloc) {
388 ppDITest =
389 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 5L),
390 pszSrcFile, __LINE__);
391 if (!ppDITest)
392 break;
393 ppDItem = ppDITest;
394 ulNumDIAlloc += 5L;
395 }
396 pDItem = xmalloc(sizeof(DRAGITEM), pszSrcFile, __LINE__);
397 if (!pDItem)
398 break;
399 ppDItem[ulNumfiles] = pDItem;
400 dimgFakeIcon.hImage = hptrFile;
401 // Initialize DRAGITEM
402 memset(pDItem, 0, sizeof(DRAGITEM));
403 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
404 pDItem->hwndItem = hwndCnr;
405 pDItem->ulItemID = (ULONG) pci;
406 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
407 ok = pDItem->hstrType;
408 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFOS2FILE);
409 ok = ok && pDItem->hstrRMF;
410 pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
411 ok = ok && pDItem->hstrContainerName;
412 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
413 ok = ok && pDItem->hstrSourceName;
414 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
415 ok = ok && pDItem->hstrTargetName;
416 if (!ok){
417 if (pDItem->hstrType)
418 DrgDeleteStrHandle(pDItem->hstrType);
419 if (pDItem->hstrRMF)
420 DrgDeleteStrHandle(pDItem->hstrRMF);
421 if (pDItem->hstrContainerName)
422 DrgDeleteStrHandle(pDItem->hstrContainerName);
423 if (pDItem->hstrSourceName)
424 DrgDeleteStrHandle(pDItem->hstrSourceName);
425 if (pDItem->hstrTargetName)
426 DrgDeleteStrHandle(pDItem->hstrTargetName);
427 xfree(pDItem);
428 dcd->ulItemsToUnHilite = ulNumfiles + 1; // +1 to ensure non-zero
429 break;
430 }
431 pDItem->fsControl = DC_PREPARE;
432 if (IsFullName(arcfile) &&
433 (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
434 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
435 pDItem->fsSupportedOps = DO_COPYABLE;
436 ulNumfiles++;
437
438 pDItem = xmalloc(sizeof(DRAGITEM), pszSrcFile, __LINE__);
439 if (pDItem) {
440 ppDItem[ulNumfiles] = pDItem;
441 dimgFakeIcon.hImage = hptrFile;
442 // Initialize DRAGITEM
443 memset(pDItem, 0, sizeof(DRAGITEM));
444 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
445 pDItem->hwndItem = hwndCnr;
446 pDItem->ulItemID = ulSelect++;
447 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
448 ok = ok && pDItem->hstrType;
449 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFFM2ARC);
450 ok = ok && pDItem->hstrRMF;
451 pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
452 ok = ok && pDItem->hstrContainerName;
453 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
454 ok = ok && pDItem->hstrSourceName;
455 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
456 ok = ok && pDItem->hstrTargetName;
457 if (!ok) {
458 DbgMsg(pszSrcFile, __LINE__, "DrgAddStrHandle failed at %lu for %s", ulNumfiles, szFile);
459 // If we have string handle add overflow, release corrupt DragItem
460 // We release 3 more to work around 1st time drag failure reported by Gregg
461 // fixme to know why this happens - PM may need to create a handle?
462 c = first_drag ? 4 : 1;
463 first_drag = FALSE;
464 for (; c > 0 && ulNumfiles > 0; c--) {
465 if (pDItem->hstrType)
466 DrgDeleteStrHandle(pDItem->hstrType);
467 if (pDItem->hstrRMF)
468 DrgDeleteStrHandle(pDItem->hstrRMF);
469 if (pDItem->hstrContainerName)
470 DrgDeleteStrHandle(pDItem->hstrContainerName);
471 if (pDItem->hstrSourceName)
472 DrgDeleteStrHandle(pDItem->hstrSourceName);
473 if (pDItem->hstrTargetName)
474 DrgDeleteStrHandle(pDItem->hstrTargetName);
475 xfree(pDItem);
476 // Last item not yet count so only decrement by one less than loop count
477 if (c > 1) {
478 ulNumfiles--;
479 pDItem = ppDItem[ulNumfiles];
480 }
481 }
482 // Set count to actual count + 1 to ensure count non-zero on any failure
483 // Unhilite code will adjust this when unhighliting
484 dcd->ulItemsToUnHilite = ulNumfiles + 1;
485 break;
486 }
487 pDItem->fsControl = 0;
488 if (IsFullName(arcfile) &&
489 (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
490 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
491 pDItem->fsSupportedOps = DO_COPYABLE;
492 ulNumfiles++;
493 }
494 // ppDItem[ulNumfiles] = NULL; // Why bother - fixme to be gone?
495 } // if archive object
496 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
497 MPFROM2SHORT(TRUE, CRA_SOURCE));
498
499 Continuing:
500
501 if (!attribute)
502 break;
503 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
504 MPFROMSHORT(attribute));
505 } // while
506
507 if (ulNumfiles) {
508 pDInfo = DrgAllocDraginfo(ulNumfiles);
509 if (pDInfo) {
510 if ((arcfile && *arcfile) || (IsFullName(szBuffer) &&
511 (driveflags[toupper(*szBuffer) - 'A'] &
512 DRIVE_NOTWRITEABLE)))
513 pDInfo->usOperation = DO_COPY;
514 else
515 pDInfo->usOperation = DO_DEFAULT;
516 if ((!arcfile || !*arcfile) && rooting)
517 pDInfo->usOperation = DO_LINK;
518 pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
519 // pDInfo->hwndSource = hwndCnr;
520 for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
521 DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect);
522 xfree(ppDItem[ulSelect]);
523 }
524#ifdef __DEBUG_ALLOC__
525 _heap_check();
526#endif
527 xfree(ppDItem);
528 ppDItem = NULL; // Remember gone
529 DosPostEventSem(CompactSem);
530
531 if (arcfile) {
532 dimgFakeIcon.cb = sizeof(DRAGIMAGE);
533 dimgFakeIcon.cptl = 0;
534 if (ulNumfiles > 1)
535 dimgFakeIcon.hImage = hptrFile;
536 dimgFakeIcon.fl = DRG_ICON;
537 dimgFakeIcon.sizlStretch.cx = 32;
538 dimgFakeIcon.sizlStretch.cy = 32;
539 dimgFakeIcon.cxOffset = -16;
540 dimgFakeIcon.cyOffset = 0;
541 paDImgIcons = &dimgFakeIcon;
542 }
543 if (!arcfile) {
544 if (!ulNumIcon)
545 ulNumIcon = ulNumfiles;
546 }
547 else
548 ulNumIcon = 1;
549
550 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
551 hDrop = DrgDrag(hwndCnr,
552 pDInfo,
553 paDImgIcons,
554 ulNumIcon,
555 VK_ENDDRAG, // Drag end button
556 NULL);
557 WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
558 }
559 }
560
561 if (hDrop == NULLHANDLE ) {
562 dcd->ulItemsToUnHilite = 0;
563 if (pDInfo)
564 FreeDragInfoData(hwndCnr, pDInfo);
565 }
566
567 if (ppDItem)
568 xfree(ppDItem);
569 if (paDImgIcons && paDImgIcons != &dimgFakeIcon)
570 xfree(paDImgIcons);
571 DosPostEventSem(CompactSem);
572 MarkAll(hwndCnr, TRUE, FALSE, TRUE);
573 return hDrop;
574}
575
576HWND DragList(HWND hwnd, HWND hwndObj, CHAR ** list, BOOL moveok)
577{
578 // Drag a linked list of files
579
580 BOOL isdir;
581 register CHAR *p;
582 PDRAGINFO pDInfo = NULL;
583 DRAGITEM **ppDItem = NULL, **ppDITest;
584 DRAGITEM *pDItem;
585 HWND hDrop = (HWND) 0;
586 ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
587 CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
588 DRAGIMAGE *paDImgIcons = NULL, *pDImg;
589 FILESTATUS3 fs3;
590 BOOL ok;
591 DIRCNRDATA *dcd;
592
593 if (!list || !list[0])
594 return hDrop;
595
596 dcd = INSTDATA(hwnd);
597
598 for (ulSelect = 0; list[ulSelect]; ulSelect++) {
599 if ((!IsRoot(list[ulSelect]) || !IsValidDrive(*list[ulSelect])) &&
600 DosQueryPathInfo(list[ulSelect], FIL_STANDARD, &fs3, sizeof(fs3)))
601 continue;
602 strcpy(szBuffer, list[ulSelect]);
603 p = strrchr(szBuffer, '\\');
604 if (p) {
605 p++;
606 strcpy(szFile, p);
607 *p = 0;
608 }
609 else
610 continue;
611 if (*szFile) {
612 isdir = IsRoot(list[ulSelect]) || fs3.attrFile & FILE_DIRECTORY;
613 // fixme to expand smarter - expand fast at first - do same for similar code
614 if (ulNumfiles + 2 > ulNumDIAlloc) {
615 if (!paDImgIcons) {
616 pDImg =
617 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
618 pszSrcFile, __LINE__);
619 if (!pDImg)
620 break;
621 paDImgIcons = pDImg;
622 }
623 else if (!ulNumIcon) {
624 pDImg = &paDImgIcons[ulNumfiles];
625 pDImg->cb = sizeof(DRAGIMAGE);
626 pDImg->cptl = 0;
627 pDImg->hImage = hptrLast;
628 pDImg->fl = DRG_ICON;
629 pDImg->sizlStretch.cx = 32;
630 pDImg->sizlStretch.cy = 32;
631 pDImg->cxOffset = -16 + (ulNumfiles * 4);
632 pDImg->cyOffset = 0 + (ulNumfiles * 7);
633 ulNumIcon = ulNumfiles + 1;
634 }
635 ppDITest =
636 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
637 pszSrcFile, __LINE__);
638 if (!ppDITest)
639 break;
640 ppDItem = ppDITest;
641 ulNumDIAlloc += 4L;
642 }
643 pDItem = xmalloc(sizeof(DRAGITEM), pszSrcFile, __LINE__);
644 if (!pDItem)
645 break;
646 ppDItem[ulNumfiles] = pDItem;
647 if (!ulNumIcon) {
648 pDImg = &paDImgIcons[ulNumfiles];
649 pDImg->cb = sizeof(DRAGIMAGE);
650 pDImg->cptl = 0;
651 pDImg->hImage = isdir ? hptrDir : hptrFile;
652 pDImg->fl = DRG_ICON;
653 pDImg->sizlStretch.cx = 32;
654 pDImg->sizlStretch.cy = 32;
655 pDImg->cxOffset = -16 + (ulNumfiles * 3);
656 pDImg->cyOffset = 0 + (ulNumfiles * 6);
657 }
658 memset(pDItem, 0, sizeof(DRAGITEM));
659 pDItem->hwndItem = (hwndObj) ? hwndObj : hwnd;
660 // pDItem->hwndItem = hwnd;
661 pDItem->ulItemID = (ULONG) ulSelect;
662 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
663 ok = pDItem->hstrType;
664 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFLIST);
665 ok = ok && pDItem->hstrRMF;
666 pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
667 ok = ok && pDItem->hstrContainerName;
668 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
669 ok = ok && pDItem->hstrSourceName;
670 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
671 ok = ok && pDItem->hstrTargetName;
672 if (!ok) {
673 if (pDItem->hstrType)
674 DrgDeleteStrHandle(pDItem->hstrType);
675 if (pDItem->hstrRMF)
676 DrgDeleteStrHandle(pDItem->hstrRMF);
677 if (pDItem->hstrContainerName)
678 DrgDeleteStrHandle(pDItem->hstrContainerName);
679 if (pDItem->hstrSourceName)
680 DrgDeleteStrHandle(pDItem->hstrSourceName);
681 if (pDItem->hstrTargetName)
682 DrgDeleteStrHandle(pDItem->hstrTargetName);
683 xfree(pDItem);
684 // pDItem = NULL; // Why bother, we can count - fixme to be gone
685 dcd->ulItemsToUnHilite = ulNumfiles + 1;
686 break;
687 }
688 pDItem->fsControl = isdir ? DC_CONTAINER : 0;
689 if (IsFullName(list[ulSelect]) &&
690 (driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_REMOVABLE))
691 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
692 pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
693 if (moveok && IsFullName(list[ulSelect]) &&
694 !(driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_NOTWRITEABLE))
695 pDItem->fsSupportedOps |= DO_MOVEABLE;
696 if (IsRoot(list[ulSelect]))
697 pDItem->fsControl = DO_LINKABLE;
698 ulNumfiles++;
699 // ppDItem[ulNumfiles] = NULL; // Why bother - fixme to be gone
700 }
701 } // for
702 if (ulNumfiles) {
703 pDInfo = DrgAllocDraginfo(ulNumfiles);
704 if (pDInfo) {
705 if ((IsFullName(szBuffer) &&
706 (driveflags[toupper(*szBuffer) - 'A'] & DRIVE_NOTWRITEABLE)))
707 pDInfo->usOperation = DO_COPY;
708 else
709 pDInfo->usOperation = DO_DEFAULT;
710 if (IsRoot(list[0]))
711 pDInfo->usOperation = DO_LINK;
712 pDInfo->hwndSource = hwndObj ? hwndObj : hwnd;
713 // pDInfo->hwndSource = hwnd;
714 for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
715 if (!DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect)) {
716 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
717 "DrgSetDragitem");
718 }
719 free(ppDItem[ulSelect]);
720 } // for
721#ifdef __DEBUG_ALLOC__
722 _heap_check();
723#endif
724 xfree(ppDItem);
725 ppDItem = NULL; // Remember gone
726 DosPostEventSem(CompactSem);
727
728 if (!ulNumIcon)
729 ulNumIcon = ulNumfiles;
730
731 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
732 hDrop = DrgDrag(hwnd,
733 pDInfo,
734 paDImgIcons,
735 ulNumIcon,
736 VK_ENDDRAG, // Drag end button
737 (PVOID) NULL);
738 if (hDrop == NULLHANDLE) {
739 dcd->ulItemsToUnHilite = 0;
740 FreeDragInfoData(hwnd, pDInfo);
741 }
742 xfree(paDImgIcons);
743 paDImgIcons = NULL; // Remember gone
744 WinSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
745 DosPostEventSem(CompactSem);
746 }
747 }
748 xfree(ppDItem);
749 xfree(paDImgIcons);
750 return hDrop;
751}
752
753#ifdef NEVER // fixme to be enabled someday?
754
755BOOL PickUp(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd)
756{
757
758 PCNRITEM pci;
759 BOOL loop = TRUE;
760 PDRAGINFO pdinfoOld = NULL, pdinfoCurrent = NULL;
761 ULONG cditem = 0;
762 DRAGITEM ditem;
763 DRAGIMAGE dimgFakeIcon;
764 CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
765
766 pci = (PCNRITEM) pcd->pRecord;
767 if (pci && (INT) pci != -1) {
768 if (pci->rc.flRecordAttr & CRA_SELECTED) {
769 loop = TRUE;
770 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
771 MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_SELECTED));
772 }
773 while (pci && (INT) pci != -1 && *pci->pszFileName) {
774 if (pdinfoOld || DrgQueryDragStatus() & DGS_LAZYDRAGINPROGRESS) {
775 if (!pdinfoOld)
776 pdinfoOld = DrgQueryDraginfoPtr(NULL);
777 if (pdinfoOld) {
778 cditem = pdinfoOld->cditem + 1;
779 pdinfoCurrent = DrgReallocDraginfo(pdinfoOld, cditem);
780 pdinfoOld = pdinfoCurrent;
781 }
782 }
783 else
784 pdinfoCurrent = pdinfoOld = DrgAllocDraginfo(1);
785 if (pdinfoCurrent) {
786 strcpy(szDir, pci->pszFileName);
787 p = szDir;
788 while (*p) {
789 if (*p == '/')
790 *p = '\\';
791 p++;
792 }
793 p = strrchr(szDir, '\\');
794 if (p) {
795 *p = 0;
796 p++;
797 strcpy(szFile, p);
798 strcat(szDir, "\\");
799 }
800 else {
801 strcpy(szFile, pci->pszFileName);
802 *szDir = 0;
803 }
804 ditem.ulItemID = (ULONG) pci;
805 ditem.hwndItem = (hwndObj) ? hwndObj : hwndCnr;
806 ditem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
807 ditem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
808 ditem.hstrContainerName = DrgAddStrHandle(szDir);
809 ditem.hstrSourceName = DrgAddStrHandle(szFile);
810 // fixme to check better if code ever enabled
811 if (!ditem.hstrSourceName) {
812 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
813 "DrgAddStrHandle");
814 }
815 ditem.hstrTargetName = DrgAddStrHandle(szFile);
816 ditem.fsControl = 0;
817 if (IsRoot(pci->pszFileName) || (pci->attrFile & FILE_DIRECTORY) != 0)
818 ditem.fsControl |= DC_CONTAINER;
819 if (IsFullName(pci->pszFileName) &&
820 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
821 ditem.fsControl |= DC_REMOVEABLEMEDIA;
822 ditem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
823 if (IsFullName(pci->pszFileName) &&
824 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
825 DRIVE_NOTWRITEABLE))
826 ditem.fsSupportedOps |= DO_MOVEABLE;
827 if (IsRoot(pci->pszFileName))
828 ditem.fsSupportedOps = DO_LINKABLE;
829 memset(&dimgFakeIcon, 0, sizeof(DRAGIMAGE));
830 dimgFakeIcon.hImage = pci->rc.hptrIcon;
831 dimgFakeIcon.cb = sizeof(DRAGIMAGE);
832 dimgFakeIcon.cptl = 0;
833 dimgFakeIcon.fl = DRG_ICON;
834 dimgFakeIcon.sizlStretch.cx = 32;
835 dimgFakeIcon.sizlStretch.cy = 32;
836 dimgFakeIcon.cxOffset = -16;
837 dimgFakeIcon.cyOffset = 0;
838 if (IsFullName(pci->pszFileName) &&
839 (driveflags[toupper(*pci->pszFileName) - 'A'] &
840 DRIVE_NOTWRITEABLE))
841 pdinfoCurrent->usOperation = DO_COPY;
842 else
843 pdinfoCurrent->usOperation = DO_DEFAULT;
844 if (IsRoot(pci->pszFileName))
845 pdinfoCurrent->usOperation = DO_LINK;
846 pdinfoCurrent->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
847 DrgSetDragitem(pdinfoCurrent, &ditem, sizeof(DRAGITEM), cditem);
848 }
849 if (!loop)
850 break;
851 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
852 MPFROMP(pci), MPFROMSHORT(CRA_SELECTED));
853 } // while
854 if (pdinfoCurrent)
855 return DrgLazyDrag(hwndCnr, pdinfoCurrent, &dimgFakeIcon, 1, NULL);
856 }
857 return FALSE;
858}
859
860#endif // NEVER
861
862#pragma alloc_text(DRAGLIST,DragOne,DoFileDrag,DragList,PickUp,FreeDragInfoData)
Note: See TracBrowser for help on using the repository browser.