source: trunk/dll/draglist.c@ 1120

Last change on this file since 1120 was 1039, checked in by Gregg Young, 17 years ago

Removed unnecessary xfrees and included fortify.h where needed; moved several misplaced (x)frees;

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.6 KB
Line 
1
2/***********************************************************************
3
4 $Id: draglist.c 1039 2008-07-05 22:16:21Z 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 SHL FreeDragInfoData: suppress PMERR_SOURCE_SAME_AS_TARGET notices
22 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
23 29 Feb 08 GKY Use xmallocz where appropriate
24
25***********************************************************************/
26
27#include <stdlib.h>
28#include <string.h>
29#include <ctype.h>
30
31#define INCL_DOS
32#define INCL_WIN
33#define INCL_SHLERRORS
34#define INCL_LONGLONG
35
36#include "errutil.h" // Dos_Error...
37#include "fm3dll.h"
38#include "fortify.h"
39
40static PSZ pszSrcFile = __FILE__;
41
42/**
43 * Delete drag item string handles.
44 * Work around for DrgDeleteDraginfoStrHandles
45 * which seems to fail with a large number of strings
46 * Assume called after successful DrgAccessDraginfo
47 */
48
49
50// #define USE_FAST_FREE // Define to let PM do free
51
52VOID FreeDragInfoData (HWND hwnd, PDRAGINFO pDInfo)
53{
54 PDRAGITEM pDItem;
55 ULONG cDitem;
56 ULONG curitem;
57 APIRET ok;
58
59# ifdef USE_FAST_FREE
60 if (!DrgDeleteDraginfoStrHandles(pDInfo)) {
61 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
62 "DrgDeleteDraginfoStrHandles");
63 }
64# else // The slow way
65 cDitem = DrgQueryDragitemCount(pDInfo);
66 for (curitem = 0; curitem < cDitem; curitem++) {
67 pDItem = DrgQueryDragitemPtr(pDInfo, curitem);
68 if (!pDItem) {
69 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
70 "DrgQueryDragitemPtr(%u)", curitem);
71 }
72 else {
73 ok = DrgDeleteStrHandle(pDItem->hstrType);
74 if (!ok) {
75 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
76 "DrgDeleteStrHandle(0x%x) hstrType",pDItem->hstrType);
77 }
78 ok = DrgDeleteStrHandle(pDItem->hstrRMF);
79 if (!ok) {
80 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
81 "DrgDeleteStrHandle(0x%x) hstrRMF",pDItem->hstrRMF);
82 }
83 ok = DrgDeleteStrHandle(pDItem->hstrContainerName);
84 if (!ok) {
85 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
86 "DrgDeleteStrHandle(0x%x) hstrContainerName",pDItem->hstrContainerName);
87 }
88 ok = DrgDeleteStrHandle(pDItem->hstrSourceName);
89 if (!ok) {
90 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
91 "DrgDeleteStrHandle(0x%x) hstrSourceName",pDItem->hstrSourceName);
92 }
93 ok = DrgDeleteStrHandle(pDItem->hstrTargetName);
94 if (!ok) {
95 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
96 "DrgDeleteStrHandle(0x%x) hstrTargetName",pDItem->hstrTargetName);
97 }
98 }
99 } // for
100# endif
101 if (!DrgFreeDraginfo(pDInfo)) {
102 // PMERR_SOURCE_SAME_AS_TARGET is not an error if dragging within same fm/2 process
103 if (!IsFm2Window(pDInfo->hwndSource, FALSE) ||
104 (WinGetLastError(WinQueryAnchorBlock(hwnd)) & 0xffff) != PMERR_SOURCE_SAME_AS_TARGET)
105 {
106 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__, "DrgFreeDraginfo");
107 }
108 }
109}
110
111HWND DragOne(HWND hwndCnr, HWND hwndObj, CHAR * filename, BOOL moveok)
112{
113
114 DRAGITEM DItem;
115 HWND hDrop = 0;
116 DRAGIMAGE fakeicon;
117 PDRAGINFO pDInfo;
118 FILESTATUS3 fs3;
119 CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
120
121 if (filename && *filename) {
122 if ((IsRoot(filename) && IsValidDrive(*filename)) ||
123 !DosQueryPathInfo(filename, FIL_STANDARD, &fs3, sizeof(fs3))) {
124 strcpy(szDir, filename);
125 p = szDir;
126 while (*p) {
127 if (*p == '/')
128 *p = '\\';
129 p++;
130 }
131 p = strrchr(szDir, '\\');
132 if (p) {
133 *p = 0;
134 p++;
135 strcpy(szFile, p);
136 strcat(szDir, "\\");
137 }
138 else {
139 strcpy(szFile, filename);
140 *szDir = 0;
141 }
142 memset(&fakeicon, 0, sizeof(DRAGIMAGE));
143 fakeicon.hImage = (IsRoot(filename) ||
144 (fs3.attrFile & FILE_DIRECTORY) != 0) ?
145 hptrDir : hptrFile;
146 memset(&DItem, 0, sizeof(DRAGITEM));
147 DItem.hwndItem = (hwndObj) ? hwndObj : hwndCnr; // Initialize DRAGITEM
148 // DItem.hwndItem = hwndCnr;
149 DItem.ulItemID = 1;
150 DItem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
151 DItem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
152 DItem.hstrContainerName = DrgAddStrHandle(szDir);
153 DItem.hstrSourceName = DrgAddStrHandle(szFile);
154 if (!DItem.hstrSourceName)
155 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
156 "DrgQueryStrName");
157 DItem.hstrTargetName = DrgAddStrHandle(szFile);
158 DItem.fsControl = 0;
159 if (IsRoot(filename) || (fs3.attrFile & FILE_DIRECTORY) != 0)
160 DItem.fsControl |= DC_CONTAINER;
161 if (IsFullName(filename) &&
162 (driveflags[toupper(*filename) - 'A'] & DRIVE_REMOVABLE))
163 DItem.fsControl |= DC_REMOVEABLEMEDIA;
164 DItem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
165 if (moveok && IsFullName(filename) &&
166 !(driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
167 DItem.fsSupportedOps |= DO_MOVEABLE;
168 if (IsRoot(filename))
169 DItem.fsSupportedOps = DO_LINKABLE;
170 fakeicon.cb = sizeof(DRAGIMAGE);
171 fakeicon.cptl = 0;
172 fakeicon.fl = DRG_ICON;
173 fakeicon.sizlStretch.cx = 32;
174 fakeicon.sizlStretch.cy = 32;
175 fakeicon.cxOffset = -16;
176 fakeicon.cyOffset = 0;
177 pDInfo = DrgAllocDraginfo(1);
178 if (pDInfo) {
179 if (IsFullName(filename) &&
180 (driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
181 pDInfo->usOperation = DO_COPY;
182 else
183 pDInfo->usOperation = DO_DEFAULT;
184 if (IsRoot(filename))
185 pDInfo->usOperation = DO_LINK;
186 pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
187 // pDInfo->hwndSource = hwndCnr;
188 DrgSetDragitem(pDInfo, &DItem, sizeof(DRAGITEM), 0);
189 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
190 hDrop = DrgDrag(hwndCnr,
191 pDInfo,
192 &fakeicon,
193 1, // DragImage count
194 VK_ENDDRAG, // Drag end button
195 NULL);
196 if (hDrop == NULLHANDLE)
197 FreeDragInfoData(hwndCnr, pDInfo);
198 WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
199 }
200 }
201 }
202 return hDrop;
203}
204
205HWND DoFileDrag(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd, CHAR * arcfile,
206 CHAR * directory, BOOL moveok)
207{
208 // Drag files from a container
209
210 BOOL isdir, rooting = FALSE;
211 PCNRITEM pci;
212 CHAR *p;
213 INT attribute = CRA_CURSORED;
214 PDRAGINFO pDInfo = NULL;
215 DRAGITEM **ppDItem = NULL, **ppDITest;
216 DRAGITEM *pDItem;
217 PCNRITEM pciRec = (PCNRITEM) pcd->pRecord;
218 HWND hDrop = NULLHANDLE;
219 ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
220 CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
221 DRAGIMAGE *paDImgIcons = NULL, *pDImg, dimgFakeIcon;
222 BOOL ok;
223 UINT c;
224 DIRCNRDATA *dcd;
225
226 static BOOL first_drag = TRUE;
227
228 // Count items to unhilite, pass to UnHilite when partial unhilite required
229 dcd = INSTDATA(hwndCnr);
230 dcd->ulItemsToUnHilite = 0;
231 if (!pciRec && directory && *directory)
232 return DragOne(hwndCnr, hwndObj, directory, moveok);
233
234 if (!pciRec) {
235 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
236 MPFROMLONG(CMA_FIRST),
237 MPFROMSHORT(attribute));
238 if (pci && (INT) pci > -1) {
239 if (pci->rc.flRecordAttr & CRA_SELECTED) {
240 attribute = CRA_SELECTED;
241 pci =
242 WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
243 MPFROMSHORT(attribute));
244 }
245 }
246 }
247 else {
248 pci = pciRec;
249 attribute = (pci->rc.flRecordAttr & CRA_SELECTED) ? CRA_SELECTED : 0;
250 if (attribute) {
251 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
252 MPFROMSHORT(attribute));
253 }
254 }
255
256 ulSelect = 0;
257 while (pci && (INT) pci > -1) {
258 if (!(pci->rc.flRecordAttr & CRA_FILTERED)) {
259 if (IsRoot(pci->pszFileName) && !IsValidDrive(*pci->pszFileName))
260 goto Continuing;
261 if (!arcfile) {
262 strcpy(szBuffer, pci->pszFileName);
263 p = strrchr(szBuffer, '\\');
264 if (p) {
265 p++;
266 strcpy(szFile, p);
267 *p = 0;
268 }
269 else
270 goto Continuing;
271 }
272 else
273 strcpy(szFile, pci->pszFileName);
274 }
275 if (!arcfile) {
276 // Filesystem object
277 isdir = pci->attrFile & FILE_DIRECTORY;
278 // fixme to expand smarter - expand fast at first - do same for similar code
279 if (ulNumfiles + 2 > ulNumDIAlloc) {
280 // Expand
281 if (!paDImgIcons) {
282 pDImg =
283 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
284 pszSrcFile, __LINE__);
285 if (!pDImg)
286 break;
287 paDImgIcons = pDImg;
288 }
289 else if (!ulNumIcon) {
290 pDImg = &paDImgIcons[ulNumfiles];
291 pDImg->cb = sizeof(DRAGIMAGE);
292 pDImg->cptl = 0;
293 pDImg->hImage = hptrLast;
294 pDImg->fl = DRG_ICON;
295 pDImg->sizlStretch.cx = 32;
296 pDImg->sizlStretch.cy = 32;
297 pDImg->cxOffset = -16 + (ulNumfiles * 4);
298 pDImg->cyOffset = 0 + (ulNumfiles * 7);
299 ulNumIcon = ulNumfiles + 1;
300 }
301 ppDITest =
302 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
303 pszSrcFile, __LINE__);
304 if (!ppDITest)
305 break;
306 ppDItem = ppDITest;
307 ulNumDIAlloc += 4L;
308 }
309 // Create & Initialize DRAGITEM
310 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
311 if (!pDItem)
312 break; // Already complained
313 ppDItem[ulNumfiles] = pDItem;
314 if (!ulNumIcon) {
315 pDImg = &paDImgIcons[ulNumfiles];
316 pDImg->cb = sizeof(DRAGIMAGE);
317 pDImg->cptl = 0;
318 pDImg->hImage = pci->rc.hptrIcon;
319 if (!pDImg->hImage)
320 pDImg->hImage = isdir ? hptrDir : hptrFile;
321 pDImg->fl = DRG_ICON;
322 pDImg->sizlStretch.cx = 32;
323 pDImg->sizlStretch.cy = 32;
324 pDImg->cxOffset = -16 + (ulNumfiles * 3);
325 pDImg->cyOffset = 0 + (ulNumfiles * 6);
326 }
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 free(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->pszFileName) &&
372 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
373 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
374 pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
375 if (moveok && IsFullName(pci->pszFileName) &&
376 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
377 DRIVE_NOTWRITEABLE))
378 pDItem->fsSupportedOps |= DO_MOVEABLE;
379 if (IsRoot(pci->pszFileName)) {
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 // Create & Initialize DRAGITEM
398 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
399 if (!pDItem)
400 break;
401 ppDItem[ulNumfiles] = pDItem;
402 dimgFakeIcon.hImage = hptrFile;
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 free(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 // Create & Initialize DRAGITEM
438 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
439 if (pDItem) {
440 ppDItem[ulNumfiles] = pDItem;
441 dimgFakeIcon.hImage = hptrFile;
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 free(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 dcd->ulItemsToUnHilite = 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], pszSrcFile, __LINE__);
521 }
522#ifdef __DEBUG_ALLOC__
523 _heap_check();
524#endif
525 xfree(ppDItem, pszSrcFile, __LINE__);
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 dcd->ulItemsToUnHilite = 0;
561 if (pDInfo)
562 FreeDragInfoData(hwndCnr, pDInfo);
563 }
564 xfree(ppDItem, pszSrcFile, __LINE__);
565 if (paDImgIcons && paDImgIcons != &dimgFakeIcon)
566 free(paDImgIcons);
567 DosPostEventSem(CompactSem);
568 MarkAll(hwndCnr, TRUE, FALSE, TRUE);
569 return hDrop;
570}
571
572HWND DragList(HWND hwnd, HWND hwndObj, CHAR ** list, BOOL moveok)
573{
574 // Drag a linked list of files
575
576 BOOL isdir;
577 register CHAR *p;
578 PDRAGINFO pDInfo = NULL;
579 DRAGITEM **ppDItem = NULL, **ppDITest;
580 DRAGITEM *pDItem;
581 HWND hDrop = (HWND) 0;
582 ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
583 CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
584 DRAGIMAGE *paDImgIcons = NULL, *pDImg;
585 FILESTATUS3 fs3;
586 BOOL ok;
587 DIRCNRDATA *dcd;
588
589 if (!list || !list[0])
590 return hDrop;
591
592 dcd = INSTDATA(hwnd);
593
594 for (ulSelect = 0; list[ulSelect]; ulSelect++) {
595 if ((!IsRoot(list[ulSelect]) || !IsValidDrive(*list[ulSelect])) &&
596 DosQueryPathInfo(list[ulSelect], FIL_STANDARD, &fs3, sizeof(fs3)))
597 continue;
598 strcpy(szBuffer, list[ulSelect]);
599 p = strrchr(szBuffer, '\\');
600 if (p) {
601 p++;
602 strcpy(szFile, p);
603 *p = 0;
604 }
605 else
606 continue;
607 if (*szFile) {
608 isdir = IsRoot(list[ulSelect]) || fs3.attrFile & FILE_DIRECTORY;
609 // fixme to expand smarter - expand fast at first - do same for similar code
610 if (ulNumfiles + 2 > ulNumDIAlloc) {
611 if (!paDImgIcons) {
612 pDImg =
613 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
614 pszSrcFile, __LINE__);
615 if (!pDImg)
616 break;
617 paDImgIcons = pDImg;
618 }
619 else if (!ulNumIcon) {
620 pDImg = &paDImgIcons[ulNumfiles];
621 pDImg->cb = sizeof(DRAGIMAGE);
622 pDImg->cptl = 0;
623 pDImg->hImage = hptrLast;
624 pDImg->fl = DRG_ICON;
625 pDImg->sizlStretch.cx = 32;
626 pDImg->sizlStretch.cy = 32;
627 pDImg->cxOffset = -16 + (ulNumfiles * 4);
628 pDImg->cyOffset = 0 + (ulNumfiles * 7);
629 ulNumIcon = ulNumfiles + 1;
630 }
631 ppDITest =
632 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
633 pszSrcFile, __LINE__);
634 if (!ppDITest)
635 break;
636 ppDItem = ppDITest;
637 ulNumDIAlloc += 4L;
638 }
639 // Create & Initialize DRAGITEM
640 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
641 if (!pDItem)
642 break;
643 ppDItem[ulNumfiles] = pDItem;
644 if (!ulNumIcon) {
645 pDImg = &paDImgIcons[ulNumfiles];
646 pDImg->cb = sizeof(DRAGIMAGE);
647 pDImg->cptl = 0;
648 pDImg->hImage = isdir ? hptrDir : hptrFile;
649 pDImg->fl = DRG_ICON;
650 pDImg->sizlStretch.cx = 32;
651 pDImg->sizlStretch.cy = 32;
652 pDImg->cxOffset = -16 + (ulNumfiles * 3);
653 pDImg->cyOffset = 0 + (ulNumfiles * 6);
654 }
655 pDItem->hwndItem = (hwndObj) ? hwndObj : hwnd;
656 pDItem->ulItemID = (ULONG) ulSelect;
657 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
658 ok = pDItem->hstrType;
659 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFLIST);
660 ok = ok && pDItem->hstrRMF;
661 pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
662 ok = ok && pDItem->hstrContainerName;
663 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
664 ok = ok && pDItem->hstrSourceName;
665 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
666 ok = ok && pDItem->hstrTargetName;
667 if (!ok) {
668 if (pDItem->hstrType)
669 DrgDeleteStrHandle(pDItem->hstrType);
670 if (pDItem->hstrRMF)
671 DrgDeleteStrHandle(pDItem->hstrRMF);
672 if (pDItem->hstrContainerName)
673 DrgDeleteStrHandle(pDItem->hstrContainerName);
674 if (pDItem->hstrSourceName)
675 DrgDeleteStrHandle(pDItem->hstrSourceName);
676 if (pDItem->hstrTargetName)
677 DrgDeleteStrHandle(pDItem->hstrTargetName);
678 free(pDItem);
679 // pDItem = NULL; // Why bother, we can count - fixme to be gone
680 dcd->ulItemsToUnHilite = ulNumfiles + 1;
681 break;
682 }
683 pDItem->fsControl = isdir ? DC_CONTAINER : 0;
684 if (IsFullName(list[ulSelect]) &&
685 (driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_REMOVABLE))
686 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
687 pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
688 if (moveok && IsFullName(list[ulSelect]) &&
689 !(driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_NOTWRITEABLE))
690 pDItem->fsSupportedOps |= DO_MOVEABLE;
691 if (IsRoot(list[ulSelect]))
692 pDItem->fsControl = DO_LINKABLE;
693 ulNumfiles++;
694 // ppDItem[ulNumfiles] = NULL; // Why bother - fixme to be gone
695 }
696 } // for
697 if (ulNumfiles) {
698 pDInfo = DrgAllocDraginfo(ulNumfiles);
699 if (pDInfo) {
700 if ((IsFullName(szBuffer) &&
701 (driveflags[toupper(*szBuffer) - 'A'] & DRIVE_NOTWRITEABLE)))
702 pDInfo->usOperation = DO_COPY;
703 else
704 pDInfo->usOperation = DO_DEFAULT;
705 if (IsRoot(list[0]))
706 pDInfo->usOperation = DO_LINK;
707 pDInfo->hwndSource = hwndObj ? hwndObj : hwnd;
708 // pDInfo->hwndSource = hwnd;
709 for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
710 if (!DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect)) {
711 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
712 "DrgSetDragitem");
713 }
714 xfree(ppDItem[ulSelect], pszSrcFile, __LINE__);
715 } // for
716#ifdef __DEBUG_ALLOC__
717 _heap_check();
718#endif
719 xfree(ppDItem, pszSrcFile, __LINE__);
720 ppDItem = NULL; // Remember gone
721 DosPostEventSem(CompactSem);
722
723 if (!ulNumIcon)
724 ulNumIcon = ulNumfiles;
725
726 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
727 hDrop = DrgDrag(hwnd,
728 pDInfo,
729 paDImgIcons,
730 ulNumIcon,
731 VK_ENDDRAG, // Drag end button
732 (PVOID) NULL);
733 if (hDrop == NULLHANDLE) {
734 dcd->ulItemsToUnHilite = 0;
735 FreeDragInfoData(hwnd, pDInfo);
736 }
737 xfree(paDImgIcons, pszSrcFile, __LINE__);
738 paDImgIcons = NULL; // Remember gone
739 WinSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
740 DosPostEventSem(CompactSem);
741 }
742 }
743 xfree(ppDItem, pszSrcFile, __LINE__);
744 xfree(paDImgIcons, pszSrcFile, __LINE__);
745 return hDrop;
746}
747
748#ifdef NEVER // fixme to be enabled someday?
749
750BOOL PickUp(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd)
751{
752
753 PCNRITEM pci;
754 BOOL loop = TRUE;
755 PDRAGINFO pdinfoOld = NULL, pdinfoCurrent = NULL;
756 ULONG cditem = 0;
757 DRAGITEM ditem;
758 DRAGIMAGE dimgFakeIcon;
759 CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
760
761 pci = (PCNRITEM) pcd->pRecord;
762 if (pci && (INT) pci != -1) {
763 if (pci->rc.flRecordAttr & CRA_SELECTED) {
764 loop = TRUE;
765 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
766 MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_SELECTED));
767 }
768 while (pci && (INT) pci != -1 && *pci->pszFileName) {
769 if (pdinfoOld || DrgQueryDragStatus() & DGS_LAZYDRAGINPROGRESS) {
770 if (!pdinfoOld)
771 pdinfoOld = DrgQueryDraginfoPtr(NULL);
772 if (pdinfoOld) {
773 cditem = pdinfoOld->cditem + 1;
774 pdinfoCurrent = DrgReallocDraginfo(pdinfoOld, cditem);
775 pdinfoOld = pdinfoCurrent;
776 }
777 }
778 else
779 pdinfoCurrent = pdinfoOld = DrgAllocDraginfo(1);
780 if (pdinfoCurrent) {
781 strcpy(szDir, pci->pszFileName);
782 p = szDir;
783 while (*p) {
784 if (*p == '/')
785 *p = '\\';
786 p++;
787 }
788 p = strrchr(szDir, '\\');
789 if (p) {
790 *p = 0;
791 p++;
792 strcpy(szFile, p);
793 strcat(szDir, "\\");
794 }
795 else {
796 strcpy(szFile, pci->pszFileName);
797 *szDir = 0;
798 }
799 ditem.ulItemID = (ULONG) pci;
800 ditem.hwndItem = (hwndObj) ? hwndObj : hwndCnr;
801 ditem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
802 ditem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
803 ditem.hstrContainerName = DrgAddStrHandle(szDir);
804 ditem.hstrSourceName = DrgAddStrHandle(szFile);
805 // fixme to check better if code ever enabled
806 if (!ditem.hstrSourceName) {
807 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
808 "DrgAddStrHandle");
809 }
810 ditem.hstrTargetName = DrgAddStrHandle(szFile);
811 ditem.fsControl = 0;
812 if (IsRoot(pci->pszFileName) || (pci->attrFile & FILE_DIRECTORY) != 0)
813 ditem.fsControl |= DC_CONTAINER;
814 if (IsFullName(pci->pszFileName) &&
815 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
816 ditem.fsControl |= DC_REMOVEABLEMEDIA;
817 ditem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
818 if (IsFullName(pci->pszFileName) &&
819 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
820 DRIVE_NOTWRITEABLE))
821 ditem.fsSupportedOps |= DO_MOVEABLE;
822 if (IsRoot(pci->pszFileName))
823 ditem.fsSupportedOps = DO_LINKABLE;
824 memset(&dimgFakeIcon, 0, sizeof(DRAGIMAGE));
825 dimgFakeIcon.hImage = pci->rc.hptrIcon;
826 dimgFakeIcon.cb = sizeof(DRAGIMAGE);
827 dimgFakeIcon.cptl = 0;
828 dimgFakeIcon.fl = DRG_ICON;
829 dimgFakeIcon.sizlStretch.cx = 32;
830 dimgFakeIcon.sizlStretch.cy = 32;
831 dimgFakeIcon.cxOffset = -16;
832 dimgFakeIcon.cyOffset = 0;
833 if (IsFullName(pci->pszFileName) &&
834 (driveflags[toupper(*pci->pszFileName) - 'A'] &
835 DRIVE_NOTWRITEABLE))
836 pdinfoCurrent->usOperation = DO_COPY;
837 else
838 pdinfoCurrent->usOperation = DO_DEFAULT;
839 if (IsRoot(pci->pszFileName))
840 pdinfoCurrent->usOperation = DO_LINK;
841 pdinfoCurrent->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
842 DrgSetDragitem(pdinfoCurrent, &ditem, sizeof(DRAGITEM), cditem);
843 }
844 if (!loop)
845 break;
846 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
847 MPFROMP(pci), MPFROMSHORT(CRA_SELECTED));
848 } // while
849 if (pdinfoCurrent)
850 return DrgLazyDrag(hwndCnr, pdinfoCurrent, &dimgFakeIcon, 1, NULL);
851 }
852 return FALSE;
853}
854
855#endif // NEVER
856
857#pragma alloc_text(DRAGLIST,DragOne,DoFileDrag,DragList,PickUp,FreeDragInfoData)
Note: See TracBrowser for help on using the repository browser.