source: trunk/dll/draglist.c@ 1011

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

Fortify updates to get it working everywhere

  • 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 1011 2008-05-11 03:00:39Z 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 xfree(pDItem, pszSrcFile, __LINE__);
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 xfree(pDItem, pszSrcFile, __LINE__);
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 xfree(pDItem, pszSrcFile, __LINE__);
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
565 if (ppDItem)
566 xfree(ppDItem, pszSrcFile, __LINE__);
567 if (paDImgIcons && paDImgIcons != &dimgFakeIcon)
568 xfree(paDImgIcons, pszSrcFile, __LINE__);
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 DIRCNRDATA *dcd;
590
591 if (!list || !list[0])
592 return hDrop;
593
594 dcd = INSTDATA(hwnd);
595
596 for (ulSelect = 0; list[ulSelect]; ulSelect++) {
597 if ((!IsRoot(list[ulSelect]) || !IsValidDrive(*list[ulSelect])) &&
598 DosQueryPathInfo(list[ulSelect], FIL_STANDARD, &fs3, sizeof(fs3)))
599 continue;
600 strcpy(szBuffer, list[ulSelect]);
601 p = strrchr(szBuffer, '\\');
602 if (p) {
603 p++;
604 strcpy(szFile, p);
605 *p = 0;
606 }
607 else
608 continue;
609 if (*szFile) {
610 isdir = IsRoot(list[ulSelect]) || fs3.attrFile & FILE_DIRECTORY;
611 // fixme to expand smarter - expand fast at first - do same for similar code
612 if (ulNumfiles + 2 > ulNumDIAlloc) {
613 if (!paDImgIcons) {
614 pDImg =
615 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
616 pszSrcFile, __LINE__);
617 if (!pDImg)
618 break;
619 paDImgIcons = pDImg;
620 }
621 else if (!ulNumIcon) {
622 pDImg = &paDImgIcons[ulNumfiles];
623 pDImg->cb = sizeof(DRAGIMAGE);
624 pDImg->cptl = 0;
625 pDImg->hImage = hptrLast;
626 pDImg->fl = DRG_ICON;
627 pDImg->sizlStretch.cx = 32;
628 pDImg->sizlStretch.cy = 32;
629 pDImg->cxOffset = -16 + (ulNumfiles * 4);
630 pDImg->cyOffset = 0 + (ulNumfiles * 7);
631 ulNumIcon = ulNumfiles + 1;
632 }
633 ppDITest =
634 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
635 pszSrcFile, __LINE__);
636 if (!ppDITest)
637 break;
638 ppDItem = ppDITest;
639 ulNumDIAlloc += 4L;
640 }
641 // Create & Initialize DRAGITEM
642 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
643 if (!pDItem)
644 break;
645 ppDItem[ulNumfiles] = pDItem;
646 if (!ulNumIcon) {
647 pDImg = &paDImgIcons[ulNumfiles];
648 pDImg->cb = sizeof(DRAGIMAGE);
649 pDImg->cptl = 0;
650 pDImg->hImage = isdir ? hptrDir : hptrFile;
651 pDImg->fl = DRG_ICON;
652 pDImg->sizlStretch.cx = 32;
653 pDImg->sizlStretch.cy = 32;
654 pDImg->cxOffset = -16 + (ulNumfiles * 3);
655 pDImg->cyOffset = 0 + (ulNumfiles * 6);
656 }
657 pDItem->hwndItem = (hwndObj) ? hwndObj : hwnd;
658 pDItem->ulItemID = (ULONG) ulSelect;
659 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
660 ok = pDItem->hstrType;
661 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFLIST);
662 ok = ok && pDItem->hstrRMF;
663 pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
664 ok = ok && pDItem->hstrContainerName;
665 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
666 ok = ok && pDItem->hstrSourceName;
667 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
668 ok = ok && pDItem->hstrTargetName;
669 if (!ok) {
670 if (pDItem->hstrType)
671 DrgDeleteStrHandle(pDItem->hstrType);
672 if (pDItem->hstrRMF)
673 DrgDeleteStrHandle(pDItem->hstrRMF);
674 if (pDItem->hstrContainerName)
675 DrgDeleteStrHandle(pDItem->hstrContainerName);
676 if (pDItem->hstrSourceName)
677 DrgDeleteStrHandle(pDItem->hstrSourceName);
678 if (pDItem->hstrTargetName)
679 DrgDeleteStrHandle(pDItem->hstrTargetName);
680 xfree(pDItem, pszSrcFile, __LINE__);
681 // pDItem = NULL; // Why bother, we can count - fixme to be gone
682 dcd->ulItemsToUnHilite = ulNumfiles + 1;
683 break;
684 }
685 pDItem->fsControl = isdir ? DC_CONTAINER : 0;
686 if (IsFullName(list[ulSelect]) &&
687 (driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_REMOVABLE))
688 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
689 pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
690 if (moveok && IsFullName(list[ulSelect]) &&
691 !(driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_NOTWRITEABLE))
692 pDItem->fsSupportedOps |= DO_MOVEABLE;
693 if (IsRoot(list[ulSelect]))
694 pDItem->fsControl = DO_LINKABLE;
695 ulNumfiles++;
696 // ppDItem[ulNumfiles] = NULL; // Why bother - fixme to be gone
697 }
698 } // for
699 if (ulNumfiles) {
700 pDInfo = DrgAllocDraginfo(ulNumfiles);
701 if (pDInfo) {
702 if ((IsFullName(szBuffer) &&
703 (driveflags[toupper(*szBuffer) - 'A'] & DRIVE_NOTWRITEABLE)))
704 pDInfo->usOperation = DO_COPY;
705 else
706 pDInfo->usOperation = DO_DEFAULT;
707 if (IsRoot(list[0]))
708 pDInfo->usOperation = DO_LINK;
709 pDInfo->hwndSource = hwndObj ? hwndObj : hwnd;
710 // pDInfo->hwndSource = hwnd;
711 for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
712 if (!DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect)) {
713 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
714 "DrgSetDragitem");
715 }
716 free(ppDItem[ulSelect]);
717 } // for
718#ifdef __DEBUG_ALLOC__
719 _heap_check();
720#endif
721 xfree(ppDItem, pszSrcFile, __LINE__);
722 ppDItem = NULL; // Remember gone
723 DosPostEventSem(CompactSem);
724
725 if (!ulNumIcon)
726 ulNumIcon = ulNumfiles;
727
728 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
729 hDrop = DrgDrag(hwnd,
730 pDInfo,
731 paDImgIcons,
732 ulNumIcon,
733 VK_ENDDRAG, // Drag end button
734 (PVOID) NULL);
735 if (hDrop == NULLHANDLE) {
736 dcd->ulItemsToUnHilite = 0;
737 FreeDragInfoData(hwnd, pDInfo);
738 }
739 xfree(paDImgIcons, pszSrcFile, __LINE__);
740 paDImgIcons = NULL; // Remember gone
741 WinSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
742 DosPostEventSem(CompactSem);
743 }
744 }
745 xfree(ppDItem, pszSrcFile, __LINE__);
746 xfree(paDImgIcons, pszSrcFile, __LINE__);
747 return hDrop;
748}
749
750#ifdef NEVER // fixme to be enabled someday?
751
752BOOL PickUp(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd)
753{
754
755 PCNRITEM pci;
756 BOOL loop = TRUE;
757 PDRAGINFO pdinfoOld = NULL, pdinfoCurrent = NULL;
758 ULONG cditem = 0;
759 DRAGITEM ditem;
760 DRAGIMAGE dimgFakeIcon;
761 CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
762
763 pci = (PCNRITEM) pcd->pRecord;
764 if (pci && (INT) pci != -1) {
765 if (pci->rc.flRecordAttr & CRA_SELECTED) {
766 loop = TRUE;
767 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
768 MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_SELECTED));
769 }
770 while (pci && (INT) pci != -1 && *pci->pszFileName) {
771 if (pdinfoOld || DrgQueryDragStatus() & DGS_LAZYDRAGINPROGRESS) {
772 if (!pdinfoOld)
773 pdinfoOld = DrgQueryDraginfoPtr(NULL);
774 if (pdinfoOld) {
775 cditem = pdinfoOld->cditem + 1;
776 pdinfoCurrent = DrgReallocDraginfo(pdinfoOld, cditem);
777 pdinfoOld = pdinfoCurrent;
778 }
779 }
780 else
781 pdinfoCurrent = pdinfoOld = DrgAllocDraginfo(1);
782 if (pdinfoCurrent) {
783 strcpy(szDir, pci->pszFileName);
784 p = szDir;
785 while (*p) {
786 if (*p == '/')
787 *p = '\\';
788 p++;
789 }
790 p = strrchr(szDir, '\\');
791 if (p) {
792 *p = 0;
793 p++;
794 strcpy(szFile, p);
795 strcat(szDir, "\\");
796 }
797 else {
798 strcpy(szFile, pci->pszFileName);
799 *szDir = 0;
800 }
801 ditem.ulItemID = (ULONG) pci;
802 ditem.hwndItem = (hwndObj) ? hwndObj : hwndCnr;
803 ditem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
804 ditem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
805 ditem.hstrContainerName = DrgAddStrHandle(szDir);
806 ditem.hstrSourceName = DrgAddStrHandle(szFile);
807 // fixme to check better if code ever enabled
808 if (!ditem.hstrSourceName) {
809 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
810 "DrgAddStrHandle");
811 }
812 ditem.hstrTargetName = DrgAddStrHandle(szFile);
813 ditem.fsControl = 0;
814 if (IsRoot(pci->pszFileName) || (pci->attrFile & FILE_DIRECTORY) != 0)
815 ditem.fsControl |= DC_CONTAINER;
816 if (IsFullName(pci->pszFileName) &&
817 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
818 ditem.fsControl |= DC_REMOVEABLEMEDIA;
819 ditem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
820 if (IsFullName(pci->pszFileName) &&
821 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
822 DRIVE_NOTWRITEABLE))
823 ditem.fsSupportedOps |= DO_MOVEABLE;
824 if (IsRoot(pci->pszFileName))
825 ditem.fsSupportedOps = DO_LINKABLE;
826 memset(&dimgFakeIcon, 0, sizeof(DRAGIMAGE));
827 dimgFakeIcon.hImage = pci->rc.hptrIcon;
828 dimgFakeIcon.cb = sizeof(DRAGIMAGE);
829 dimgFakeIcon.cptl = 0;
830 dimgFakeIcon.fl = DRG_ICON;
831 dimgFakeIcon.sizlStretch.cx = 32;
832 dimgFakeIcon.sizlStretch.cy = 32;
833 dimgFakeIcon.cxOffset = -16;
834 dimgFakeIcon.cyOffset = 0;
835 if (IsFullName(pci->pszFileName) &&
836 (driveflags[toupper(*pci->pszFileName) - 'A'] &
837 DRIVE_NOTWRITEABLE))
838 pdinfoCurrent->usOperation = DO_COPY;
839 else
840 pdinfoCurrent->usOperation = DO_DEFAULT;
841 if (IsRoot(pci->pszFileName))
842 pdinfoCurrent->usOperation = DO_LINK;
843 pdinfoCurrent->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
844 DrgSetDragitem(pdinfoCurrent, &ditem, sizeof(DRAGITEM), cditem);
845 }
846 if (!loop)
847 break;
848 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
849 MPFROMP(pci), MPFROMSHORT(CRA_SELECTED));
850 } // while
851 if (pdinfoCurrent)
852 return DrgLazyDrag(hwndCnr, pdinfoCurrent, &dimgFakeIcon, 1, NULL);
853 }
854 return FALSE;
855}
856
857#endif // NEVER
858
859#pragma alloc_text(DRAGLIST,DragOne,DoFileDrag,DragList,PickUp,FreeDragInfoData)
Note: See TracBrowser for help on using the repository browser.