source: trunk/dll/draglist.c@ 1178

Last change on this file since 1178 was 1158, checked in by John Small, 17 years ago

Ticket 187: Draft 1: Functions only

  • 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 1158 2008-09-05 21:40:35Z jbs $
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 "draglist.h"
38#include "valid.h" // IsValidDrive
39#include "fm3dll.h"
40#include "fortify.h"
41
42static PSZ pszSrcFile = __FILE__;
43
44/**
45 * Delete drag item string handles.
46 * Work around for DrgDeleteDraginfoStrHandles
47 * which seems to fail with a large number of strings
48 * Assume called after successful DrgAccessDraginfo
49 */
50
51
52// #define USE_FAST_FREE // Define to let PM do free
53
54VOID FreeDragInfoData (HWND hwnd, PDRAGINFO pDInfo)
55{
56 PDRAGITEM pDItem;
57 ULONG cDitem;
58 ULONG curitem;
59 APIRET ok;
60
61# ifdef USE_FAST_FREE
62 if (!DrgDeleteDraginfoStrHandles(pDInfo)) {
63 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
64 "DrgDeleteDraginfoStrHandles");
65 }
66# else // The slow way
67 cDitem = DrgQueryDragitemCount(pDInfo);
68 for (curitem = 0; curitem < cDitem; curitem++) {
69 pDItem = DrgQueryDragitemPtr(pDInfo, curitem);
70 if (!pDItem) {
71 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
72 "DrgQueryDragitemPtr(%u)", curitem);
73 }
74 else {
75 ok = DrgDeleteStrHandle(pDItem->hstrType);
76 if (!ok) {
77 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
78 "DrgDeleteStrHandle(0x%x) hstrType",pDItem->hstrType);
79 }
80 ok = DrgDeleteStrHandle(pDItem->hstrRMF);
81 if (!ok) {
82 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
83 "DrgDeleteStrHandle(0x%x) hstrRMF",pDItem->hstrRMF);
84 }
85 ok = DrgDeleteStrHandle(pDItem->hstrContainerName);
86 if (!ok) {
87 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
88 "DrgDeleteStrHandle(0x%x) hstrContainerName",pDItem->hstrContainerName);
89 }
90 ok = DrgDeleteStrHandle(pDItem->hstrSourceName);
91 if (!ok) {
92 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
93 "DrgDeleteStrHandle(0x%x) hstrSourceName",pDItem->hstrSourceName);
94 }
95 ok = DrgDeleteStrHandle(pDItem->hstrTargetName);
96 if (!ok) {
97 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
98 "DrgDeleteStrHandle(0x%x) hstrTargetName",pDItem->hstrTargetName);
99 }
100 }
101 } // for
102# endif
103 if (!DrgFreeDraginfo(pDInfo)) {
104 // PMERR_SOURCE_SAME_AS_TARGET is not an error if dragging within same fm/2 process
105 if (!IsFm2Window(pDInfo->hwndSource, FALSE) ||
106 (WinGetLastError(WinQueryAnchorBlock(hwnd)) & 0xffff) != PMERR_SOURCE_SAME_AS_TARGET)
107 {
108 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__, "DrgFreeDraginfo");
109 }
110 }
111}
112
113HWND DragOne(HWND hwndCnr, HWND hwndObj, CHAR * filename, BOOL moveok)
114{
115
116 DRAGITEM DItem;
117 HWND hDrop = 0;
118 DRAGIMAGE fakeicon;
119 PDRAGINFO pDInfo;
120 FILESTATUS3 fs3;
121 CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
122
123 if (filename && *filename) {
124 if ((IsRoot(filename) && IsValidDrive(*filename)) ||
125 !DosQueryPathInfo(filename, FIL_STANDARD, &fs3, sizeof(fs3))) {
126 strcpy(szDir, filename);
127 p = szDir;
128 while (*p) {
129 if (*p == '/')
130 *p = '\\';
131 p++;
132 }
133 p = strrchr(szDir, '\\');
134 if (p) {
135 *p = 0;
136 p++;
137 strcpy(szFile, p);
138 strcat(szDir, "\\");
139 }
140 else {
141 strcpy(szFile, filename);
142 *szDir = 0;
143 }
144 memset(&fakeicon, 0, sizeof(DRAGIMAGE));
145 fakeicon.hImage = (IsRoot(filename) ||
146 (fs3.attrFile & FILE_DIRECTORY) != 0) ?
147 hptrDir : hptrFile;
148 memset(&DItem, 0, sizeof(DRAGITEM));
149 DItem.hwndItem = (hwndObj) ? hwndObj : hwndCnr; // Initialize DRAGITEM
150 // DItem.hwndItem = hwndCnr;
151 DItem.ulItemID = 1;
152 DItem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
153 DItem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
154 DItem.hstrContainerName = DrgAddStrHandle(szDir);
155 DItem.hstrSourceName = DrgAddStrHandle(szFile);
156 if (!DItem.hstrSourceName)
157 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
158 "DrgQueryStrName");
159 DItem.hstrTargetName = DrgAddStrHandle(szFile);
160 DItem.fsControl = 0;
161 if (IsRoot(filename) || (fs3.attrFile & FILE_DIRECTORY) != 0)
162 DItem.fsControl |= DC_CONTAINER;
163 if (IsFullName(filename) &&
164 (driveflags[toupper(*filename) - 'A'] & DRIVE_REMOVABLE))
165 DItem.fsControl |= DC_REMOVEABLEMEDIA;
166 DItem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
167 if (moveok && IsFullName(filename) &&
168 !(driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
169 DItem.fsSupportedOps |= DO_MOVEABLE;
170 if (IsRoot(filename))
171 DItem.fsSupportedOps = DO_LINKABLE;
172 fakeicon.cb = sizeof(DRAGIMAGE);
173 fakeicon.cptl = 0;
174 fakeicon.fl = DRG_ICON;
175 fakeicon.sizlStretch.cx = 32;
176 fakeicon.sizlStretch.cy = 32;
177 fakeicon.cxOffset = -16;
178 fakeicon.cyOffset = 0;
179 pDInfo = DrgAllocDraginfo(1);
180 if (pDInfo) {
181 if (IsFullName(filename) &&
182 (driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
183 pDInfo->usOperation = DO_COPY;
184 else
185 pDInfo->usOperation = DO_DEFAULT;
186 if (IsRoot(filename))
187 pDInfo->usOperation = DO_LINK;
188 pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
189 // pDInfo->hwndSource = hwndCnr;
190 DrgSetDragitem(pDInfo, &DItem, sizeof(DRAGITEM), 0);
191 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
192 hDrop = DrgDrag(hwndCnr,
193 pDInfo,
194 &fakeicon,
195 1, // DragImage count
196 VK_ENDDRAG, // Drag end button
197 NULL);
198 if (hDrop == NULLHANDLE)
199 FreeDragInfoData(hwndCnr, pDInfo);
200 WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
201 }
202 }
203 }
204 return hDrop;
205}
206
207HWND DoFileDrag(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd, CHAR * arcfile,
208 CHAR * directory, BOOL moveok)
209{
210 // Drag files from a container
211
212 BOOL isdir, rooting = FALSE;
213 PCNRITEM pci;
214 CHAR *p;
215 INT attribute = CRA_CURSORED;
216 PDRAGINFO pDInfo = NULL;
217 DRAGITEM **ppDItem = NULL, **ppDITest;
218 DRAGITEM *pDItem;
219 PCNRITEM pciRec = (PCNRITEM) pcd->pRecord;
220 HWND hDrop = NULLHANDLE;
221 ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
222 CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
223 DRAGIMAGE *paDImgIcons = NULL, *pDImg, dimgFakeIcon;
224 BOOL ok;
225 UINT c;
226 DIRCNRDATA *dcd;
227
228 static BOOL first_drag = TRUE;
229
230 // Count items to unhilite, pass to UnHilite when partial unhilite required
231 dcd = INSTDATA(hwndCnr);
232 dcd->ulItemsToUnHilite = 0;
233 if (!pciRec && directory && *directory)
234 return DragOne(hwndCnr, hwndObj, directory, moveok);
235
236 if (!pciRec) {
237 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
238 MPFROMLONG(CMA_FIRST),
239 MPFROMSHORT(attribute));
240 if (pci && (INT) pci > -1) {
241 if (pci->rc.flRecordAttr & CRA_SELECTED) {
242 attribute = CRA_SELECTED;
243 pci =
244 WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
245 MPFROMSHORT(attribute));
246 }
247 }
248 }
249 else {
250 pci = pciRec;
251 attribute = (pci->rc.flRecordAttr & CRA_SELECTED) ? CRA_SELECTED : 0;
252 if (attribute) {
253 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
254 MPFROMSHORT(attribute));
255 }
256 }
257
258 ulSelect = 0;
259 while (pci && (INT) pci > -1) {
260 if (!(pci->rc.flRecordAttr & CRA_FILTERED)) {
261 if (IsRoot(pci->pszFileName) && !IsValidDrive(*pci->pszFileName))
262 goto Continuing;
263 if (!arcfile) {
264 strcpy(szBuffer, pci->pszFileName);
265 p = strrchr(szBuffer, '\\');
266 if (p) {
267 p++;
268 strcpy(szFile, p);
269 *p = 0;
270 }
271 else
272 goto Continuing;
273 }
274 else
275 strcpy(szFile, pci->pszFileName);
276 }
277 if (!arcfile) {
278 // Filesystem object
279 isdir = pci->attrFile & FILE_DIRECTORY;
280 // fixme to expand smarter - expand fast at first - do same for similar code
281 if (ulNumfiles + 2 > ulNumDIAlloc) {
282 // Expand
283 if (!paDImgIcons) {
284 pDImg =
285 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
286 pszSrcFile, __LINE__);
287 if (!pDImg)
288 break;
289 paDImgIcons = pDImg;
290 }
291 else if (!ulNumIcon) {
292 pDImg = &paDImgIcons[ulNumfiles];
293 pDImg->cb = sizeof(DRAGIMAGE);
294 pDImg->cptl = 0;
295 pDImg->hImage = hptrLast;
296 pDImg->fl = DRG_ICON;
297 pDImg->sizlStretch.cx = 32;
298 pDImg->sizlStretch.cy = 32;
299 pDImg->cxOffset = -16 + (ulNumfiles * 4);
300 pDImg->cyOffset = 0 + (ulNumfiles * 7);
301 ulNumIcon = ulNumfiles + 1;
302 }
303 ppDITest =
304 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
305 pszSrcFile, __LINE__);
306 if (!ppDITest)
307 break;
308 ppDItem = ppDITest;
309 ulNumDIAlloc += 4L;
310 }
311 // Create & Initialize DRAGITEM
312 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
313 if (!pDItem)
314 break; // Already complained
315 ppDItem[ulNumfiles] = pDItem;
316 if (!ulNumIcon) {
317 pDImg = &paDImgIcons[ulNumfiles];
318 pDImg->cb = sizeof(DRAGIMAGE);
319 pDImg->cptl = 0;
320 pDImg->hImage = pci->rc.hptrIcon;
321 if (!pDImg->hImage)
322 pDImg->hImage = isdir ? hptrDir : hptrFile;
323 pDImg->fl = DRG_ICON;
324 pDImg->sizlStretch.cx = 32;
325 pDImg->sizlStretch.cy = 32;
326 pDImg->cxOffset = -16 + (ulNumfiles * 3);
327 pDImg->cyOffset = 0 + (ulNumfiles * 6);
328 }
329 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
330 pDItem->hwndItem = hwndCnr;
331 pDItem->ulItemID = (ULONG) pci;
332 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
333 ok = pDItem->hstrType;
334 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFLIST);
335 ok = ok && pDItem->hstrRMF;
336 pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
337 ok = ok && pDItem->hstrContainerName;
338 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
339 ok = ok && pDItem->hstrSourceName;
340 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
341 ok = ok && pDItem->hstrTargetName;
342 if (!ok) {
343 DbgMsg(pszSrcFile, __LINE__, "DrgAddStrHandle failed at %lu for %s", ulNumfiles, szFile);
344 // If we have string handle add overflow, release corrupt DragItem
345 // We release 3 more to work around 1st time drag failure reported by Gregg
346 // fixme to know why this happens - PM may need to create a handle?
347 c = first_drag ? 4 : 1;
348 first_drag = FALSE;
349 for (; c > 0 && ulNumfiles > 0; c--) {
350 if (pDItem->hstrType)
351 DrgDeleteStrHandle(pDItem->hstrType);
352 if (pDItem->hstrRMF)
353 DrgDeleteStrHandle(pDItem->hstrRMF);
354 if (pDItem->hstrContainerName)
355 DrgDeleteStrHandle(pDItem->hstrContainerName);
356 if (pDItem->hstrSourceName)
357 DrgDeleteStrHandle(pDItem->hstrSourceName);
358 if (pDItem->hstrTargetName)
359 DrgDeleteStrHandle(pDItem->hstrTargetName);
360 free(pDItem);
361 // Last item not yet count so only decrement by one less than loop count
362 // Unhilite code will adjust this when unhighliting
363 if (c > 1) {
364 ulNumfiles--;
365 pDItem = ppDItem[ulNumfiles];
366 }
367 }
368 // Set count to actual count + 1 to ensure count non-zero on any failure
369 dcd->ulItemsToUnHilite = ulNumfiles + 1;
370 break;
371 }
372 pDItem->fsControl = isdir ? DC_CONTAINER : 0;
373 if (IsFullName(pci->pszFileName) &&
374 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
375 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
376 pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
377 if (moveok && IsFullName(pci->pszFileName) &&
378 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
379 DRIVE_NOTWRITEABLE))
380 pDItem->fsSupportedOps |= DO_MOVEABLE;
381 if (IsRoot(pci->pszFileName)) {
382 pDItem->fsSupportedOps = DO_LINKABLE;
383 rooting = TRUE;
384 }
385 ulNumfiles++;
386 // ppDItem[ulNumfiles] = NULL; // Why bother - can't we count - fixme to be gone?
387 } // if filesystem object
388 else {
389 // Archive object
390 if (ulNumfiles + 3L > ulNumDIAlloc) {
391 ppDITest =
392 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 5L),
393 pszSrcFile, __LINE__);
394 if (!ppDITest)
395 break;
396 ppDItem = ppDITest;
397 ulNumDIAlloc += 5L;
398 }
399 // Create & Initialize DRAGITEM
400 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
401 if (!pDItem)
402 break;
403 ppDItem[ulNumfiles] = pDItem;
404 dimgFakeIcon.hImage = hptrFile;
405 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
406 pDItem->hwndItem = hwndCnr;
407 pDItem->ulItemID = (ULONG) pci;
408 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
409 ok = pDItem->hstrType;
410 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFOS2FILE);
411 ok = ok && pDItem->hstrRMF;
412 pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
413 ok = ok && pDItem->hstrContainerName;
414 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
415 ok = ok && pDItem->hstrSourceName;
416 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
417 ok = ok && pDItem->hstrTargetName;
418 if (!ok){
419 if (pDItem->hstrType)
420 DrgDeleteStrHandle(pDItem->hstrType);
421 if (pDItem->hstrRMF)
422 DrgDeleteStrHandle(pDItem->hstrRMF);
423 if (pDItem->hstrContainerName)
424 DrgDeleteStrHandle(pDItem->hstrContainerName);
425 if (pDItem->hstrSourceName)
426 DrgDeleteStrHandle(pDItem->hstrSourceName);
427 if (pDItem->hstrTargetName)
428 DrgDeleteStrHandle(pDItem->hstrTargetName);
429 free(pDItem);
430 dcd->ulItemsToUnHilite = ulNumfiles + 1; // +1 to ensure non-zero
431 break;
432 }
433 pDItem->fsControl = DC_PREPARE;
434 if (IsFullName(arcfile) &&
435 (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
436 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
437 pDItem->fsSupportedOps = DO_COPYABLE;
438 ulNumfiles++;
439 // Create & Initialize DRAGITEM
440 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
441 if (pDItem) {
442 ppDItem[ulNumfiles] = pDItem;
443 dimgFakeIcon.hImage = hptrFile;
444 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
445 pDItem->hwndItem = hwndCnr;
446 pDItem->ulItemID = ulSelect++;
447 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
448 ok = ok && pDItem->hstrType;
449 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFFM2ARC);
450 ok = ok && pDItem->hstrRMF;
451 pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
452 ok = ok && pDItem->hstrContainerName;
453 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
454 ok = ok && pDItem->hstrSourceName;
455 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
456 ok = ok && pDItem->hstrTargetName;
457 if (!ok) {
458 DbgMsg(pszSrcFile, __LINE__, "DrgAddStrHandle failed at %lu for %s", ulNumfiles, szFile);
459 // If we have string handle add overflow, release corrupt DragItem
460 // We release 3 more to work around 1st time drag failure reported by Gregg
461 // fixme to know why this happens - PM may need to create a handle?
462 c = first_drag ? 4 : 1;
463 first_drag = FALSE;
464 for (; c > 0 && ulNumfiles > 0; c--) {
465 if (pDItem->hstrType)
466 DrgDeleteStrHandle(pDItem->hstrType);
467 if (pDItem->hstrRMF)
468 DrgDeleteStrHandle(pDItem->hstrRMF);
469 if (pDItem->hstrContainerName)
470 DrgDeleteStrHandle(pDItem->hstrContainerName);
471 if (pDItem->hstrSourceName)
472 DrgDeleteStrHandle(pDItem->hstrSourceName);
473 if (pDItem->hstrTargetName)
474 DrgDeleteStrHandle(pDItem->hstrTargetName);
475 free(pDItem);
476 // Last item not yet count so only decrement by one less than loop count
477 if (c > 1) {
478 ulNumfiles--;
479 pDItem = ppDItem[ulNumfiles];
480 }
481 }
482 // Set count to actual count + 1 to ensure count non-zero on any failure
483 // Unhilite code will adjust this when unhighliting
484 dcd->ulItemsToUnHilite = ulNumfiles + 1;
485 break;
486 }
487 pDItem->fsControl = 0;
488 if (IsFullName(arcfile) &&
489 (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
490 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
491 pDItem->fsSupportedOps = DO_COPYABLE;
492 ulNumfiles++;
493 }
494 // ppDItem[ulNumfiles] = NULL; // Why bother - fixme to be gone?
495 } // if archive object
496 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
497 MPFROM2SHORT(TRUE, CRA_SOURCE));
498
499 Continuing:
500
501 if (!attribute)
502 break;
503 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
504 MPFROMSHORT(attribute));
505 } // while
506
507 if (ulNumfiles) {
508 pDInfo = DrgAllocDraginfo(ulNumfiles);
509 if (pDInfo) {
510 if ((arcfile && *arcfile) || (IsFullName(szBuffer) &&
511 (driveflags[toupper(*szBuffer) - 'A'] &
512 DRIVE_NOTWRITEABLE)))
513 pDInfo->usOperation = DO_COPY;
514 else
515 pDInfo->usOperation = DO_DEFAULT;
516 if ((!arcfile || !*arcfile) && rooting)
517 pDInfo->usOperation = DO_LINK;
518 pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
519 // pDInfo->hwndSource = hwndCnr;
520 for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
521 DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect);
522 xfree(ppDItem[ulSelect], pszSrcFile, __LINE__);
523 }
524#ifdef __DEBUG_ALLOC__
525 _heap_check();
526#endif
527 xfree(ppDItem, pszSrcFile, __LINE__);
528 ppDItem = NULL; // Remember gone
529 DosPostEventSem(CompactSem);
530
531 if (arcfile) {
532 dimgFakeIcon.cb = sizeof(DRAGIMAGE);
533 dimgFakeIcon.cptl = 0;
534 if (ulNumfiles > 1)
535 dimgFakeIcon.hImage = hptrFile;
536 dimgFakeIcon.fl = DRG_ICON;
537 dimgFakeIcon.sizlStretch.cx = 32;
538 dimgFakeIcon.sizlStretch.cy = 32;
539 dimgFakeIcon.cxOffset = -16;
540 dimgFakeIcon.cyOffset = 0;
541 paDImgIcons = &dimgFakeIcon;
542 }
543 if (!arcfile) {
544 if (!ulNumIcon)
545 ulNumIcon = ulNumfiles;
546 }
547 else
548 ulNumIcon = 1;
549
550 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
551 hDrop = DrgDrag(hwndCnr,
552 pDInfo,
553 paDImgIcons,
554 ulNumIcon,
555 VK_ENDDRAG, // Drag end button
556 NULL);
557 WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
558 }
559 }
560
561 if (hDrop == NULLHANDLE ) {
562 dcd->ulItemsToUnHilite = 0;
563 if (pDInfo)
564 FreeDragInfoData(hwndCnr, pDInfo);
565 }
566 xfree(ppDItem, pszSrcFile, __LINE__);
567 if (paDImgIcons && paDImgIcons != &dimgFakeIcon)
568 free(paDImgIcons);
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 free(pDItem);
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 xfree(ppDItem[ulSelect], pszSrcFile, __LINE__);
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.