source: trunk/dll/draglist.c@ 727

Last change on this file since 727 was 727, checked in by Steven Levine, 18 years ago

FreeDragInfoData: suppress PMERR_SOURCE_SAME_AS_TARGET notices

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