source: trunk/dll/draglist.c@ 1009

Last change on this file since 1009 was 1009, checked in by Steven Levine, 17 years ago

Add xfree xstrdup Fortify support
Add MT capable Fortify scope logic

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.7 KB
Line 
1
2/***********************************************************************
3
4 $Id: draglist.c 1009 2008-05-10 07:51:58Z stevenhl $
5
6 Drag drop support
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2007 Steven H.Levine
10
11 16 Oct 02 SHL DoFileDrag: don't free stack
12 26 Jul 06 SHL Check more run time errors
13 06 Apr 07 GKY Work around PM DragInfo and DrgFreeDISH limits
14 06 Apr 07 GKY Add DeleteDragitemStrHandles
15 06 Apr 07 GKY Add some error checking in drag/drop
16 19 Apr 07 SHL Rework DeleteDragitemStrHandles to be FreeDragInfoData
17 19 Apr 07 SHL Add more drag/drop error checking
18 19 Apr 07 SHL Optimize DRAGITEM DRAGIMAGE array access
19 21 Apr 07 SHL Avoid odd first time drag failure
20 12 May 07 SHL Use dcd->ulItemsToUnHilite
21 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
39static PSZ pszSrcFile = __FILE__;
40
41/**
42 * Delete drag item string handles.
43 * Work around for DrgDeleteDraginfoStrHandles
44 * which seems to fail with a large number of strings
45 * Assume called after successful DrgAccessDraginfo
46 */
47
48
49// #define USE_FAST_FREE // Define to let PM do free
50
51VOID FreeDragInfoData (HWND hwnd, PDRAGINFO pDInfo)
52{
53 PDRAGITEM pDItem;
54 ULONG cDitem;
55 ULONG curitem;
56 APIRET ok;
57
58# ifdef USE_FAST_FREE
59 if (!DrgDeleteDraginfoStrHandles(pDInfo)) {
60 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
61 "DrgDeleteDraginfoStrHandles");
62 }
63# else // The slow way
64 cDitem = DrgQueryDragitemCount(pDInfo);
65 for (curitem = 0; curitem < cDitem; curitem++) {
66 pDItem = DrgQueryDragitemPtr(pDInfo, curitem);
67 if (!pDItem) {
68 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
69 "DrgQueryDragitemPtr(%u)", curitem);
70 }
71 else {
72 ok = DrgDeleteStrHandle(pDItem->hstrType);
73 if (!ok) {
74 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
75 "DrgDeleteStrHandle(0x%x) hstrType",pDItem->hstrType);
76 }
77 ok = DrgDeleteStrHandle(pDItem->hstrRMF);
78 if (!ok) {
79 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
80 "DrgDeleteStrHandle(0x%x) hstrRMF",pDItem->hstrRMF);
81 }
82 ok = DrgDeleteStrHandle(pDItem->hstrContainerName);
83 if (!ok) {
84 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
85 "DrgDeleteStrHandle(0x%x) hstrContainerName",pDItem->hstrContainerName);
86 }
87 ok = DrgDeleteStrHandle(pDItem->hstrSourceName);
88 if (!ok) {
89 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
90 "DrgDeleteStrHandle(0x%x) hstrSourceName",pDItem->hstrSourceName);
91 }
92 ok = DrgDeleteStrHandle(pDItem->hstrTargetName);
93 if (!ok) {
94 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
95 "DrgDeleteStrHandle(0x%x) hstrTargetName",pDItem->hstrTargetName);
96 }
97 }
98 } // for
99# endif
100 if (!DrgFreeDraginfo(pDInfo)) {
101 // PMERR_SOURCE_SAME_AS_TARGET is not an error if dragging within same fm/2 process
102 if (!IsFm2Window(pDInfo->hwndSource, FALSE) ||
103 (WinGetLastError(WinQueryAnchorBlock(hwnd)) & 0xffff) != PMERR_SOURCE_SAME_AS_TARGET)
104 {
105 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__, "DrgFreeDraginfo");
106 }
107 }
108}
109
110HWND DragOne(HWND hwndCnr, HWND hwndObj, CHAR * filename, BOOL moveok)
111{
112
113 DRAGITEM DItem;
114 HWND hDrop = 0;
115 DRAGIMAGE fakeicon;
116 PDRAGINFO pDInfo;
117 FILESTATUS3 fs3;
118 CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
119
120 if (filename && *filename) {
121 if ((IsRoot(filename) && IsValidDrive(*filename)) ||
122 !DosQueryPathInfo(filename, FIL_STANDARD, &fs3, sizeof(fs3))) {
123 strcpy(szDir, filename);
124 p = szDir;
125 while (*p) {
126 if (*p == '/')
127 *p = '\\';
128 p++;
129 }
130 p = strrchr(szDir, '\\');
131 if (p) {
132 *p = 0;
133 p++;
134 strcpy(szFile, p);
135 strcat(szDir, "\\");
136 }
137 else {
138 strcpy(szFile, filename);
139 *szDir = 0;
140 }
141 memset(&fakeicon, 0, sizeof(DRAGIMAGE));
142 fakeicon.hImage = (IsRoot(filename) ||
143 (fs3.attrFile & FILE_DIRECTORY) != 0) ?
144 hptrDir : hptrFile;
145 memset(&DItem, 0, sizeof(DRAGITEM));
146 DItem.hwndItem = (hwndObj) ? hwndObj : hwndCnr; // Initialize DRAGITEM
147 // DItem.hwndItem = hwndCnr;
148 DItem.ulItemID = 1;
149 DItem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
150 DItem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
151 DItem.hstrContainerName = DrgAddStrHandle(szDir);
152 DItem.hstrSourceName = DrgAddStrHandle(szFile);
153 if (!DItem.hstrSourceName)
154 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
155 "DrgQueryStrName");
156 DItem.hstrTargetName = DrgAddStrHandle(szFile);
157 DItem.fsControl = 0;
158 if (IsRoot(filename) || (fs3.attrFile & FILE_DIRECTORY) != 0)
159 DItem.fsControl |= DC_CONTAINER;
160 if (IsFullName(filename) &&
161 (driveflags[toupper(*filename) - 'A'] & DRIVE_REMOVABLE))
162 DItem.fsControl |= DC_REMOVEABLEMEDIA;
163 DItem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
164 if (moveok && IsFullName(filename) &&
165 !(driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
166 DItem.fsSupportedOps |= DO_MOVEABLE;
167 if (IsRoot(filename))
168 DItem.fsSupportedOps = DO_LINKABLE;
169 fakeicon.cb = sizeof(DRAGIMAGE);
170 fakeicon.cptl = 0;
171 fakeicon.fl = DRG_ICON;
172 fakeicon.sizlStretch.cx = 32;
173 fakeicon.sizlStretch.cy = 32;
174 fakeicon.cxOffset = -16;
175 fakeicon.cyOffset = 0;
176 pDInfo = DrgAllocDraginfo(1);
177 if (pDInfo) {
178 if (IsFullName(filename) &&
179 (driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
180 pDInfo->usOperation = DO_COPY;
181 else
182 pDInfo->usOperation = DO_DEFAULT;
183 if (IsRoot(filename))
184 pDInfo->usOperation = DO_LINK;
185 pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
186 // pDInfo->hwndSource = hwndCnr;
187 DrgSetDragitem(pDInfo, &DItem, sizeof(DRAGITEM), 0);
188 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
189 hDrop = DrgDrag(hwndCnr,
190 pDInfo,
191 &fakeicon,
192 1, // DragImage count
193 VK_ENDDRAG, // Drag end button
194 NULL);
195 if (hDrop == NULLHANDLE)
196 FreeDragInfoData(hwndCnr, pDInfo);
197 WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
198 }
199 }
200 }
201 return hDrop;
202}
203
204HWND DoFileDrag(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd, CHAR * arcfile,
205 CHAR * directory, BOOL moveok)
206{
207 // Drag files from a container
208
209 BOOL isdir, rooting = FALSE;
210 PCNRITEM pci;
211 CHAR *p;
212 INT attribute = CRA_CURSORED;
213 PDRAGINFO pDInfo = NULL;
214 DRAGITEM **ppDItem = NULL, **ppDITest;
215 DRAGITEM *pDItem;
216 PCNRITEM pciRec = (PCNRITEM) pcd->pRecord;
217 HWND hDrop = NULLHANDLE;
218 ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
219 CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
220 DRAGIMAGE *paDImgIcons = NULL, *pDImg, dimgFakeIcon;
221 BOOL ok;
222 UINT c;
223 DIRCNRDATA *dcd;
224
225 static BOOL first_drag = TRUE;
226
227 // Count items to unhilite, pass to UnHilite when partial unhilite required
228 dcd = INSTDATA(hwndCnr);
229 dcd->ulItemsToUnHilite = 0;
230 if (!pciRec && directory && *directory)
231 return DragOne(hwndCnr, hwndObj, directory, moveok);
232
233 if (!pciRec) {
234 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
235 MPFROMLONG(CMA_FIRST),
236 MPFROMSHORT(attribute));
237 if (pci && (INT) pci > -1) {
238 if (pci->rc.flRecordAttr & CRA_SELECTED) {
239 attribute = CRA_SELECTED;
240 pci =
241 WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
242 MPFROMSHORT(attribute));
243 }
244 }
245 }
246 else {
247 pci = pciRec;
248 attribute = (pci->rc.flRecordAttr & CRA_SELECTED) ? CRA_SELECTED : 0;
249 if (attribute) {
250 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
251 MPFROMSHORT(attribute));
252 }
253 }
254
255 ulSelect = 0;
256 while (pci && (INT) pci > -1) {
257 if (!(pci->rc.flRecordAttr & CRA_FILTERED)) {
258 if (IsRoot(pci->pszFileName) && !IsValidDrive(*pci->pszFileName))
259 goto Continuing;
260 if (!arcfile) {
261 strcpy(szBuffer, pci->pszFileName);
262 p = strrchr(szBuffer, '\\');
263 if (p) {
264 p++;
265 strcpy(szFile, p);
266 *p = 0;
267 }
268 else
269 goto Continuing;
270 }
271 else
272 strcpy(szFile, pci->pszFileName);
273 }
274 if (!arcfile) {
275 // Filesystem object
276 isdir = pci->attrFile & FILE_DIRECTORY;
277 // fixme to expand smarter - expand fast at first - do same for similar code
278 if (ulNumfiles + 2 > ulNumDIAlloc) {
279 // Expand
280 if (!paDImgIcons) {
281 pDImg =
282 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
283 pszSrcFile, __LINE__);
284 if (!pDImg)
285 break;
286 paDImgIcons = pDImg;
287 }
288 else if (!ulNumIcon) {
289 pDImg = &paDImgIcons[ulNumfiles];
290 pDImg->cb = sizeof(DRAGIMAGE);
291 pDImg->cptl = 0;
292 pDImg->hImage = hptrLast;
293 pDImg->fl = DRG_ICON;
294 pDImg->sizlStretch.cx = 32;
295 pDImg->sizlStretch.cy = 32;
296 pDImg->cxOffset = -16 + (ulNumfiles * 4);
297 pDImg->cyOffset = 0 + (ulNumfiles * 7);
298 ulNumIcon = ulNumfiles + 1;
299 }
300 ppDITest =
301 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
302 pszSrcFile, __LINE__);
303 if (!ppDITest)
304 break;
305 ppDItem = ppDITest;
306 ulNumDIAlloc += 4L;
307 }
308 // Create & Initialize DRAGITEM
309 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
310 if (!pDItem)
311 break; // Already complained
312 ppDItem[ulNumfiles] = pDItem;
313 if (!ulNumIcon) {
314 pDImg = &paDImgIcons[ulNumfiles];
315 pDImg->cb = sizeof(DRAGIMAGE);
316 pDImg->cptl = 0;
317 pDImg->hImage = pci->rc.hptrIcon;
318 if (!pDImg->hImage)
319 pDImg->hImage = isdir ? hptrDir : hptrFile;
320 pDImg->fl = DRG_ICON;
321 pDImg->sizlStretch.cx = 32;
322 pDImg->sizlStretch.cy = 32;
323 pDImg->cxOffset = -16 + (ulNumfiles * 3);
324 pDImg->cyOffset = 0 + (ulNumfiles * 6);
325 }
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, pszSrcFile, __LINE__);
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 // Create & Initialize DRAGITEM
397 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
398 if (!pDItem)
399 break;
400 ppDItem[ulNumfiles] = pDItem;
401 dimgFakeIcon.hImage = hptrFile;
402 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
403 pDItem->hwndItem = hwndCnr;
404 pDItem->ulItemID = (ULONG) pci;
405 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
406 ok = pDItem->hstrType;
407 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFOS2FILE);
408 ok = ok && pDItem->hstrRMF;
409 pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
410 ok = ok && pDItem->hstrContainerName;
411 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
412 ok = ok && pDItem->hstrSourceName;
413 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
414 ok = ok && pDItem->hstrTargetName;
415 if (!ok){
416 if (pDItem->hstrType)
417 DrgDeleteStrHandle(pDItem->hstrType);
418 if (pDItem->hstrRMF)
419 DrgDeleteStrHandle(pDItem->hstrRMF);
420 if (pDItem->hstrContainerName)
421 DrgDeleteStrHandle(pDItem->hstrContainerName);
422 if (pDItem->hstrSourceName)
423 DrgDeleteStrHandle(pDItem->hstrSourceName);
424 if (pDItem->hstrTargetName)
425 DrgDeleteStrHandle(pDItem->hstrTargetName);
426 xfree(pDItem, pszSrcFile, __LINE__);
427 dcd->ulItemsToUnHilite = ulNumfiles + 1; // +1 to ensure non-zero
428 break;
429 }
430 pDItem->fsControl = DC_PREPARE;
431 if (IsFullName(arcfile) &&
432 (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
433 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
434 pDItem->fsSupportedOps = DO_COPYABLE;
435 ulNumfiles++;
436 // Create & Initialize DRAGITEM
437 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
438 if (pDItem) {
439 ppDItem[ulNumfiles] = pDItem;
440 dimgFakeIcon.hImage = hptrFile;
441 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
442 pDItem->hwndItem = hwndCnr;
443 pDItem->ulItemID = ulSelect++;
444 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
445 ok = ok && pDItem->hstrType;
446 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFFM2ARC);
447 ok = ok && pDItem->hstrRMF;
448 pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
449 ok = ok && pDItem->hstrContainerName;
450 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
451 ok = ok && pDItem->hstrSourceName;
452 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
453 ok = ok && pDItem->hstrTargetName;
454 if (!ok) {
455 DbgMsg(pszSrcFile, __LINE__, "DrgAddStrHandle failed at %lu for %s", ulNumfiles, szFile);
456 // If we have string handle add overflow, release corrupt DragItem
457 // We release 3 more to work around 1st time drag failure reported by Gregg
458 // fixme to know why this happens - PM may need to create a handle?
459 c = first_drag ? 4 : 1;
460 first_drag = FALSE;
461 for (; c > 0 && ulNumfiles > 0; c--) {
462 if (pDItem->hstrType)
463 DrgDeleteStrHandle(pDItem->hstrType);
464 if (pDItem->hstrRMF)
465 DrgDeleteStrHandle(pDItem->hstrRMF);
466 if (pDItem->hstrContainerName)
467 DrgDeleteStrHandle(pDItem->hstrContainerName);
468 if (pDItem->hstrSourceName)
469 DrgDeleteStrHandle(pDItem->hstrSourceName);
470 if (pDItem->hstrTargetName)
471 DrgDeleteStrHandle(pDItem->hstrTargetName);
472 xfree(pDItem, pszSrcFile, __LINE__);
473 // Last item not yet count so only decrement by one less than loop count
474 if (c > 1) {
475 ulNumfiles--;
476 pDItem = ppDItem[ulNumfiles];
477 }
478 }
479 // Set count to actual count + 1 to ensure count non-zero on any failure
480 // Unhilite code will adjust this when unhighliting
481 dcd->ulItemsToUnHilite = ulNumfiles + 1;
482 break;
483 }
484 pDItem->fsControl = 0;
485 if (IsFullName(arcfile) &&
486 (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
487 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
488 pDItem->fsSupportedOps = DO_COPYABLE;
489 ulNumfiles++;
490 }
491 // ppDItem[ulNumfiles] = NULL; // Why bother - fixme to be gone?
492 } // if archive object
493 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
494 MPFROM2SHORT(TRUE, CRA_SOURCE));
495
496 Continuing:
497
498 if (!attribute)
499 break;
500 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
501 MPFROMSHORT(attribute));
502 } // while
503
504 if (ulNumfiles) {
505 pDInfo = DrgAllocDraginfo(ulNumfiles);
506 if (pDInfo) {
507 if ((arcfile && *arcfile) || (IsFullName(szBuffer) &&
508 (driveflags[toupper(*szBuffer) - 'A'] &
509 DRIVE_NOTWRITEABLE)))
510 pDInfo->usOperation = DO_COPY;
511 else
512 pDInfo->usOperation = DO_DEFAULT;
513 if ((!arcfile || !*arcfile) && rooting)
514 pDInfo->usOperation = DO_LINK;
515 pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
516 // pDInfo->hwndSource = hwndCnr;
517 for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
518 DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect);
519 xfree(ppDItem[ulSelect], pszSrcFile, __LINE__);
520 }
521#ifdef __DEBUG_ALLOC__
522 _heap_check();
523#endif
524 xfree(ppDItem, pszSrcFile, __LINE__);
525 ppDItem = NULL; // Remember gone
526 DosPostEventSem(CompactSem);
527
528 if (arcfile) {
529 dimgFakeIcon.cb = sizeof(DRAGIMAGE);
530 dimgFakeIcon.cptl = 0;
531 if (ulNumfiles > 1)
532 dimgFakeIcon.hImage = hptrFile;
533 dimgFakeIcon.fl = DRG_ICON;
534 dimgFakeIcon.sizlStretch.cx = 32;
535 dimgFakeIcon.sizlStretch.cy = 32;
536 dimgFakeIcon.cxOffset = -16;
537 dimgFakeIcon.cyOffset = 0;
538 paDImgIcons = &dimgFakeIcon;
539 }
540 if (!arcfile) {
541 if (!ulNumIcon)
542 ulNumIcon = ulNumfiles;
543 }
544 else
545 ulNumIcon = 1;
546
547 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
548 hDrop = DrgDrag(hwndCnr,
549 pDInfo,
550 paDImgIcons,
551 ulNumIcon,
552 VK_ENDDRAG, // Drag end button
553 NULL);
554 WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
555 }
556 }
557
558 if (hDrop == NULLHANDLE ) {
559 dcd->ulItemsToUnHilite = 0;
560 if (pDInfo)
561 FreeDragInfoData(hwndCnr, pDInfo);
562 }
563
564 if (ppDItem)
565 xfree(ppDItem, pszSrcFile, __LINE__);
566 if (paDImgIcons && paDImgIcons != &dimgFakeIcon)
567 xfree(paDImgIcons, pszSrcFile, __LINE__);
568 DosPostEventSem(CompactSem);
569 MarkAll(hwndCnr, TRUE, FALSE, TRUE);
570 return hDrop;
571}
572
573HWND DragList(HWND hwnd, HWND hwndObj, CHAR ** list, BOOL moveok)
574{
575 // Drag a linked list of files
576
577 BOOL isdir;
578 register CHAR *p;
579 PDRAGINFO pDInfo = NULL;
580 DRAGITEM **ppDItem = NULL, **ppDITest;
581 DRAGITEM *pDItem;
582 HWND hDrop = (HWND) 0;
583 ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
584 CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
585 DRAGIMAGE *paDImgIcons = NULL, *pDImg;
586 FILESTATUS3 fs3;
587 BOOL ok;
588 DIRCNRDATA *dcd;
589
590 if (!list || !list[0])
591 return hDrop;
592
593 dcd = INSTDATA(hwnd);
594
595 for (ulSelect = 0; list[ulSelect]; ulSelect++) {
596 if ((!IsRoot(list[ulSelect]) || !IsValidDrive(*list[ulSelect])) &&
597 DosQueryPathInfo(list[ulSelect], FIL_STANDARD, &fs3, sizeof(fs3)))
598 continue;
599 strcpy(szBuffer, list[ulSelect]);
600 p = strrchr(szBuffer, '\\');
601 if (p) {
602 p++;
603 strcpy(szFile, p);
604 *p = 0;
605 }
606 else
607 continue;
608 if (*szFile) {
609 isdir = IsRoot(list[ulSelect]) || fs3.attrFile & FILE_DIRECTORY;
610 // fixme to expand smarter - expand fast at first - do same for similar code
611 if (ulNumfiles + 2 > ulNumDIAlloc) {
612 if (!paDImgIcons) {
613 pDImg =
614 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
615 pszSrcFile, __LINE__);
616 if (!pDImg)
617 break;
618 paDImgIcons = pDImg;
619 }
620 else if (!ulNumIcon) {
621 pDImg = &paDImgIcons[ulNumfiles];
622 pDImg->cb = sizeof(DRAGIMAGE);
623 pDImg->cptl = 0;
624 pDImg->hImage = hptrLast;
625 pDImg->fl = DRG_ICON;
626 pDImg->sizlStretch.cx = 32;
627 pDImg->sizlStretch.cy = 32;
628 pDImg->cxOffset = -16 + (ulNumfiles * 4);
629 pDImg->cyOffset = 0 + (ulNumfiles * 7);
630 ulNumIcon = ulNumfiles + 1;
631 }
632 ppDITest =
633 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
634 pszSrcFile, __LINE__);
635 if (!ppDITest)
636 break;
637 ppDItem = ppDITest;
638 ulNumDIAlloc += 4L;
639 }
640 // Create & Initialize DRAGITEM
641 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
642 if (!pDItem)
643 break;
644 ppDItem[ulNumfiles] = pDItem;
645 if (!ulNumIcon) {
646 pDImg = &paDImgIcons[ulNumfiles];
647 pDImg->cb = sizeof(DRAGIMAGE);
648 pDImg->cptl = 0;
649 pDImg->hImage = isdir ? hptrDir : hptrFile;
650 pDImg->fl = DRG_ICON;
651 pDImg->sizlStretch.cx = 32;
652 pDImg->sizlStretch.cy = 32;
653 pDImg->cxOffset = -16 + (ulNumfiles * 3);
654 pDImg->cyOffset = 0 + (ulNumfiles * 6);
655 }
656 pDItem->hwndItem = (hwndObj) ? hwndObj : hwnd;
657 pDItem->ulItemID = (ULONG) ulSelect;
658 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
659 ok = pDItem->hstrType;
660 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFLIST);
661 ok = ok && pDItem->hstrRMF;
662 pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
663 ok = ok && pDItem->hstrContainerName;
664 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
665 ok = ok && pDItem->hstrSourceName;
666 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
667 ok = ok && pDItem->hstrTargetName;
668 if (!ok) {
669 if (pDItem->hstrType)
670 DrgDeleteStrHandle(pDItem->hstrType);
671 if (pDItem->hstrRMF)
672 DrgDeleteStrHandle(pDItem->hstrRMF);
673 if (pDItem->hstrContainerName)
674 DrgDeleteStrHandle(pDItem->hstrContainerName);
675 if (pDItem->hstrSourceName)
676 DrgDeleteStrHandle(pDItem->hstrSourceName);
677 if (pDItem->hstrTargetName)
678 DrgDeleteStrHandle(pDItem->hstrTargetName);
679 xfree(pDItem, pszSrcFile, __LINE__);
680 // pDItem = NULL; // Why bother, we can count - fixme to be gone
681 dcd->ulItemsToUnHilite = ulNumfiles + 1;
682 break;
683 }
684 pDItem->fsControl = isdir ? DC_CONTAINER : 0;
685 if (IsFullName(list[ulSelect]) &&
686 (driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_REMOVABLE))
687 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
688 pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
689 if (moveok && IsFullName(list[ulSelect]) &&
690 !(driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_NOTWRITEABLE))
691 pDItem->fsSupportedOps |= DO_MOVEABLE;
692 if (IsRoot(list[ulSelect]))
693 pDItem->fsControl = DO_LINKABLE;
694 ulNumfiles++;
695 // ppDItem[ulNumfiles] = NULL; // Why bother - fixme to be gone
696 }
697 } // for
698 if (ulNumfiles) {
699 pDInfo = DrgAllocDraginfo(ulNumfiles);
700 if (pDInfo) {
701 if ((IsFullName(szBuffer) &&
702 (driveflags[toupper(*szBuffer) - 'A'] & DRIVE_NOTWRITEABLE)))
703 pDInfo->usOperation = DO_COPY;
704 else
705 pDInfo->usOperation = DO_DEFAULT;
706 if (IsRoot(list[0]))
707 pDInfo->usOperation = DO_LINK;
708 pDInfo->hwndSource = hwndObj ? hwndObj : hwnd;
709 // pDInfo->hwndSource = hwnd;
710 for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
711 if (!DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect)) {
712 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
713 "DrgSetDragitem");
714 }
715 free(ppDItem[ulSelect]);
716 } // for
717#ifdef __DEBUG_ALLOC__
718 _heap_check();
719#endif
720 xfree(ppDItem, pszSrcFile, __LINE__);
721 ppDItem = NULL; // Remember gone
722 DosPostEventSem(CompactSem);
723
724 if (!ulNumIcon)
725 ulNumIcon = ulNumfiles;
726
727 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
728 hDrop = DrgDrag(hwnd,
729 pDInfo,
730 paDImgIcons,
731 ulNumIcon,
732 VK_ENDDRAG, // Drag end button
733 (PVOID) NULL);
734 if (hDrop == NULLHANDLE) {
735 dcd->ulItemsToUnHilite = 0;
736 FreeDragInfoData(hwnd, pDInfo);
737 }
738 xfree(paDImgIcons, pszSrcFile, __LINE__);
739 paDImgIcons = NULL; // Remember gone
740 WinSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
741 DosPostEventSem(CompactSem);
742 }
743 }
744 xfree(ppDItem, pszSrcFile, __LINE__);
745 xfree(paDImgIcons, pszSrcFile, __LINE__);
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->pszFileName) {
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->pszFileName);
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->pszFileName);
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->pszFileName) || (pci->attrFile & FILE_DIRECTORY) != 0)
814 ditem.fsControl |= DC_CONTAINER;
815 if (IsFullName(pci->pszFileName) &&
816 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
817 ditem.fsControl |= DC_REMOVEABLEMEDIA;
818 ditem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
819 if (IsFullName(pci->pszFileName) &&
820 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
821 DRIVE_NOTWRITEABLE))
822 ditem.fsSupportedOps |= DO_MOVEABLE;
823 if (IsRoot(pci->pszFileName))
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->pszFileName) &&
835 (driveflags[toupper(*pci->pszFileName) - 'A'] &
836 DRIVE_NOTWRITEABLE))
837 pdinfoCurrent->usOperation = DO_COPY;
838 else
839 pdinfoCurrent->usOperation = DO_DEFAULT;
840 if (IsRoot(pci->pszFileName))
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
857
858#pragma alloc_text(DRAGLIST,DragOne,DoFileDrag,DragList,PickUp,FreeDragInfoData)
Note: See TracBrowser for help on using the repository browser.