source: trunk/dll/draglist.c@ 1207

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

Ticket 187: Move data declarations/definitions out of fm3dll.h

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.0 KB
Line 
1
2/***********************************************************************
3
4 $Id: draglist.c 1207 2008-09-13 06:49:41Z 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 "fm3dll.h"
37#include "info.h" // Data declaration(s)
38#include "init.h" // Data declaration(s)
39#include "newview.h" // Data declarations
40#include "errutil.h" // Dos_Error...
41#include "draglist.h"
42#include "valid.h" // IsValidDrive
43#include "misc.h" // IsFm2Window
44#include "select.h" // MarkAll
45#include "wrappers.h" // xrealloc
46#include "fortify.h"
47
48// Data definitions
49static PSZ pszSrcFile = __FILE__;
50
51#pragma data_seg(GLOBAL1)
52HPOINTER hptrDir;
53HPOINTER hptrFile;
54HPOINTER hptrLast;
55
56#pragma data_seg(GLOBAL2)
57CHAR *DRMDRFLIST;
58
59/**
60 * Delete drag item string handles.
61 * Work around for DrgDeleteDraginfoStrHandles
62 * which seems to fail with a large number of strings
63 * Assume called after successful DrgAccessDraginfo
64 */
65
66
67// #define USE_FAST_FREE // Define to let PM do free
68
69VOID FreeDragInfoData (HWND hwnd, PDRAGINFO pDInfo)
70{
71 PDRAGITEM pDItem;
72 ULONG cDitem;
73 ULONG curitem;
74 APIRET ok;
75
76# ifdef USE_FAST_FREE
77 if (!DrgDeleteDraginfoStrHandles(pDInfo)) {
78 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
79 "DrgDeleteDraginfoStrHandles");
80 }
81# else // The slow way
82 cDitem = DrgQueryDragitemCount(pDInfo);
83 for (curitem = 0; curitem < cDitem; curitem++) {
84 pDItem = DrgQueryDragitemPtr(pDInfo, curitem);
85 if (!pDItem) {
86 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
87 "DrgQueryDragitemPtr(%u)", curitem);
88 }
89 else {
90 ok = DrgDeleteStrHandle(pDItem->hstrType);
91 if (!ok) {
92 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
93 "DrgDeleteStrHandle(0x%x) hstrType",pDItem->hstrType);
94 }
95 ok = DrgDeleteStrHandle(pDItem->hstrRMF);
96 if (!ok) {
97 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
98 "DrgDeleteStrHandle(0x%x) hstrRMF",pDItem->hstrRMF);
99 }
100 ok = DrgDeleteStrHandle(pDItem->hstrContainerName);
101 if (!ok) {
102 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
103 "DrgDeleteStrHandle(0x%x) hstrContainerName",pDItem->hstrContainerName);
104 }
105 ok = DrgDeleteStrHandle(pDItem->hstrSourceName);
106 if (!ok) {
107 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
108 "DrgDeleteStrHandle(0x%x) hstrSourceName",pDItem->hstrSourceName);
109 }
110 ok = DrgDeleteStrHandle(pDItem->hstrTargetName);
111 if (!ok) {
112 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
113 "DrgDeleteStrHandle(0x%x) hstrTargetName",pDItem->hstrTargetName);
114 }
115 }
116 } // for
117# endif
118 if (!DrgFreeDraginfo(pDInfo)) {
119 // PMERR_SOURCE_SAME_AS_TARGET is not an error if dragging within same fm/2 process
120 if (!IsFm2Window(pDInfo->hwndSource, FALSE) ||
121 (WinGetLastError(WinQueryAnchorBlock(hwnd)) & 0xffff) != PMERR_SOURCE_SAME_AS_TARGET)
122 {
123 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__, "DrgFreeDraginfo");
124 }
125 }
126}
127
128HWND DragOne(HWND hwndCnr, HWND hwndObj, CHAR * filename, BOOL moveok)
129{
130
131 DRAGITEM DItem;
132 HWND hDrop = 0;
133 DRAGIMAGE fakeicon;
134 PDRAGINFO pDInfo;
135 FILESTATUS3 fs3;
136 CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
137
138 if (filename && *filename) {
139 if ((IsRoot(filename) && IsValidDrive(*filename)) ||
140 !DosQueryPathInfo(filename, FIL_STANDARD, &fs3, sizeof(fs3))) {
141 strcpy(szDir, filename);
142 p = szDir;
143 while (*p) {
144 if (*p == '/')
145 *p = '\\';
146 p++;
147 }
148 p = strrchr(szDir, '\\');
149 if (p) {
150 *p = 0;
151 p++;
152 strcpy(szFile, p);
153 strcat(szDir, "\\");
154 }
155 else {
156 strcpy(szFile, filename);
157 *szDir = 0;
158 }
159 memset(&fakeicon, 0, sizeof(DRAGIMAGE));
160 fakeicon.hImage = (IsRoot(filename) ||
161 (fs3.attrFile & FILE_DIRECTORY) != 0) ?
162 hptrDir : hptrFile;
163 memset(&DItem, 0, sizeof(DRAGITEM));
164 DItem.hwndItem = (hwndObj) ? hwndObj : hwndCnr; // Initialize DRAGITEM
165 // DItem.hwndItem = hwndCnr;
166 DItem.ulItemID = 1;
167 DItem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
168 DItem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
169 DItem.hstrContainerName = DrgAddStrHandle(szDir);
170 DItem.hstrSourceName = DrgAddStrHandle(szFile);
171 if (!DItem.hstrSourceName)
172 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
173 "DrgQueryStrName");
174 DItem.hstrTargetName = DrgAddStrHandle(szFile);
175 DItem.fsControl = 0;
176 if (IsRoot(filename) || (fs3.attrFile & FILE_DIRECTORY) != 0)
177 DItem.fsControl |= DC_CONTAINER;
178 if (IsFullName(filename) &&
179 (driveflags[toupper(*filename) - 'A'] & DRIVE_REMOVABLE))
180 DItem.fsControl |= DC_REMOVEABLEMEDIA;
181 DItem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
182 if (moveok && IsFullName(filename) &&
183 !(driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
184 DItem.fsSupportedOps |= DO_MOVEABLE;
185 if (IsRoot(filename))
186 DItem.fsSupportedOps = DO_LINKABLE;
187 fakeicon.cb = sizeof(DRAGIMAGE);
188 fakeicon.cptl = 0;
189 fakeicon.fl = DRG_ICON;
190 fakeicon.sizlStretch.cx = 32;
191 fakeicon.sizlStretch.cy = 32;
192 fakeicon.cxOffset = -16;
193 fakeicon.cyOffset = 0;
194 pDInfo = DrgAllocDraginfo(1);
195 if (pDInfo) {
196 if (IsFullName(filename) &&
197 (driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
198 pDInfo->usOperation = DO_COPY;
199 else
200 pDInfo->usOperation = DO_DEFAULT;
201 if (IsRoot(filename))
202 pDInfo->usOperation = DO_LINK;
203 pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
204 // pDInfo->hwndSource = hwndCnr;
205 DrgSetDragitem(pDInfo, &DItem, sizeof(DRAGITEM), 0);
206 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
207 hDrop = DrgDrag(hwndCnr,
208 pDInfo,
209 &fakeicon,
210 1, // DragImage count
211 VK_ENDDRAG, // Drag end button
212 NULL);
213 if (hDrop == NULLHANDLE)
214 FreeDragInfoData(hwndCnr, pDInfo);
215 WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
216 }
217 }
218 }
219 return hDrop;
220}
221
222HWND DoFileDrag(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd, CHAR * arcfile,
223 CHAR * directory, BOOL moveok)
224{
225 // Drag files from a container
226
227 BOOL isdir, rooting = FALSE;
228 PCNRITEM pci;
229 CHAR *p;
230 INT attribute = CRA_CURSORED;
231 PDRAGINFO pDInfo = NULL;
232 DRAGITEM **ppDItem = NULL, **ppDITest;
233 DRAGITEM *pDItem;
234 PCNRITEM pciRec = (PCNRITEM) pcd->pRecord;
235 HWND hDrop = NULLHANDLE;
236 ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
237 CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
238 DRAGIMAGE *paDImgIcons = NULL, *pDImg, dimgFakeIcon;
239 BOOL ok;
240 UINT c;
241 DIRCNRDATA *dcd;
242
243 static BOOL first_drag = TRUE;
244
245 // Count items to unhilite, pass to UnHilite when partial unhilite required
246 dcd = INSTDATA(hwndCnr);
247 dcd->ulItemsToUnHilite = 0;
248 if (!pciRec && directory && *directory)
249 return DragOne(hwndCnr, hwndObj, directory, moveok);
250
251 if (!pciRec) {
252 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
253 MPFROMLONG(CMA_FIRST),
254 MPFROMSHORT(attribute));
255 if (pci && (INT) pci > -1) {
256 if (pci->rc.flRecordAttr & CRA_SELECTED) {
257 attribute = CRA_SELECTED;
258 pci =
259 WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
260 MPFROMSHORT(attribute));
261 }
262 }
263 }
264 else {
265 pci = pciRec;
266 attribute = (pci->rc.flRecordAttr & CRA_SELECTED) ? CRA_SELECTED : 0;
267 if (attribute) {
268 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
269 MPFROMSHORT(attribute));
270 }
271 }
272
273 ulSelect = 0;
274 while (pci && (INT) pci > -1) {
275 if (!(pci->rc.flRecordAttr & CRA_FILTERED)) {
276 if (IsRoot(pci->pszFileName) && !IsValidDrive(*pci->pszFileName))
277 goto Continuing;
278 if (!arcfile) {
279 strcpy(szBuffer, pci->pszFileName);
280 p = strrchr(szBuffer, '\\');
281 if (p) {
282 p++;
283 strcpy(szFile, p);
284 *p = 0;
285 }
286 else
287 goto Continuing;
288 }
289 else
290 strcpy(szFile, pci->pszFileName);
291 }
292 if (!arcfile) {
293 // Filesystem object
294 isdir = pci->attrFile & FILE_DIRECTORY;
295 // fixme to expand smarter - expand fast at first - do same for similar code
296 if (ulNumfiles + 2 > ulNumDIAlloc) {
297 // Expand
298 if (!paDImgIcons) {
299 pDImg =
300 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
301 pszSrcFile, __LINE__);
302 if (!pDImg)
303 break;
304 paDImgIcons = pDImg;
305 }
306 else if (!ulNumIcon) {
307 pDImg = &paDImgIcons[ulNumfiles];
308 pDImg->cb = sizeof(DRAGIMAGE);
309 pDImg->cptl = 0;
310 pDImg->hImage = hptrLast;
311 pDImg->fl = DRG_ICON;
312 pDImg->sizlStretch.cx = 32;
313 pDImg->sizlStretch.cy = 32;
314 pDImg->cxOffset = -16 + (ulNumfiles * 4);
315 pDImg->cyOffset = 0 + (ulNumfiles * 7);
316 ulNumIcon = ulNumfiles + 1;
317 }
318 ppDITest =
319 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
320 pszSrcFile, __LINE__);
321 if (!ppDITest)
322 break;
323 ppDItem = ppDITest;
324 ulNumDIAlloc += 4L;
325 }
326 // Create & Initialize DRAGITEM
327 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
328 if (!pDItem)
329 break; // Already complained
330 ppDItem[ulNumfiles] = pDItem;
331 if (!ulNumIcon) {
332 pDImg = &paDImgIcons[ulNumfiles];
333 pDImg->cb = sizeof(DRAGIMAGE);
334 pDImg->cptl = 0;
335 pDImg->hImage = pci->rc.hptrIcon;
336 if (!pDImg->hImage)
337 pDImg->hImage = isdir ? hptrDir : hptrFile;
338 pDImg->fl = DRG_ICON;
339 pDImg->sizlStretch.cx = 32;
340 pDImg->sizlStretch.cy = 32;
341 pDImg->cxOffset = -16 + (ulNumfiles * 3);
342 pDImg->cyOffset = 0 + (ulNumfiles * 6);
343 }
344 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
345 pDItem->hwndItem = hwndCnr;
346 pDItem->ulItemID = (ULONG) pci;
347 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
348 ok = pDItem->hstrType;
349 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFLIST);
350 ok = ok && pDItem->hstrRMF;
351 pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
352 ok = ok && pDItem->hstrContainerName;
353 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
354 ok = ok && pDItem->hstrSourceName;
355 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
356 ok = ok && pDItem->hstrTargetName;
357 if (!ok) {
358 DbgMsg(pszSrcFile, __LINE__, "DrgAddStrHandle failed at %lu for %s", ulNumfiles, szFile);
359 // If we have string handle add overflow, release corrupt DragItem
360 // We release 3 more to work around 1st time drag failure reported by Gregg
361 // fixme to know why this happens - PM may need to create a handle?
362 c = first_drag ? 4 : 1;
363 first_drag = FALSE;
364 for (; c > 0 && ulNumfiles > 0; c--) {
365 if (pDItem->hstrType)
366 DrgDeleteStrHandle(pDItem->hstrType);
367 if (pDItem->hstrRMF)
368 DrgDeleteStrHandle(pDItem->hstrRMF);
369 if (pDItem->hstrContainerName)
370 DrgDeleteStrHandle(pDItem->hstrContainerName);
371 if (pDItem->hstrSourceName)
372 DrgDeleteStrHandle(pDItem->hstrSourceName);
373 if (pDItem->hstrTargetName)
374 DrgDeleteStrHandle(pDItem->hstrTargetName);
375 free(pDItem);
376 // Last item not yet count so only decrement by one less than loop count
377 // Unhilite code will adjust this when unhighliting
378 if (c > 1) {
379 ulNumfiles--;
380 pDItem = ppDItem[ulNumfiles];
381 }
382 }
383 // Set count to actual count + 1 to ensure count non-zero on any failure
384 dcd->ulItemsToUnHilite = ulNumfiles + 1;
385 break;
386 }
387 pDItem->fsControl = isdir ? DC_CONTAINER : 0;
388 if (IsFullName(pci->pszFileName) &&
389 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
390 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
391 pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
392 if (moveok && IsFullName(pci->pszFileName) &&
393 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
394 DRIVE_NOTWRITEABLE))
395 pDItem->fsSupportedOps |= DO_MOVEABLE;
396 if (IsRoot(pci->pszFileName)) {
397 pDItem->fsSupportedOps = DO_LINKABLE;
398 rooting = TRUE;
399 }
400 ulNumfiles++;
401 // ppDItem[ulNumfiles] = NULL; // Why bother - can't we count - fixme to be gone?
402 } // if filesystem object
403 else {
404 // Archive object
405 if (ulNumfiles + 3L > ulNumDIAlloc) {
406 ppDITest =
407 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 5L),
408 pszSrcFile, __LINE__);
409 if (!ppDITest)
410 break;
411 ppDItem = ppDITest;
412 ulNumDIAlloc += 5L;
413 }
414 // Create & Initialize DRAGITEM
415 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
416 if (!pDItem)
417 break;
418 ppDItem[ulNumfiles] = pDItem;
419 dimgFakeIcon.hImage = hptrFile;
420 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
421 pDItem->hwndItem = hwndCnr;
422 pDItem->ulItemID = (ULONG) pci;
423 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
424 ok = pDItem->hstrType;
425 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFOS2FILE);
426 ok = ok && pDItem->hstrRMF;
427 pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
428 ok = ok && pDItem->hstrContainerName;
429 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
430 ok = ok && pDItem->hstrSourceName;
431 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
432 ok = ok && pDItem->hstrTargetName;
433 if (!ok){
434 if (pDItem->hstrType)
435 DrgDeleteStrHandle(pDItem->hstrType);
436 if (pDItem->hstrRMF)
437 DrgDeleteStrHandle(pDItem->hstrRMF);
438 if (pDItem->hstrContainerName)
439 DrgDeleteStrHandle(pDItem->hstrContainerName);
440 if (pDItem->hstrSourceName)
441 DrgDeleteStrHandle(pDItem->hstrSourceName);
442 if (pDItem->hstrTargetName)
443 DrgDeleteStrHandle(pDItem->hstrTargetName);
444 free(pDItem);
445 dcd->ulItemsToUnHilite = ulNumfiles + 1; // +1 to ensure non-zero
446 break;
447 }
448 pDItem->fsControl = DC_PREPARE;
449 if (IsFullName(arcfile) &&
450 (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
451 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
452 pDItem->fsSupportedOps = DO_COPYABLE;
453 ulNumfiles++;
454 // Create & Initialize DRAGITEM
455 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
456 if (pDItem) {
457 ppDItem[ulNumfiles] = pDItem;
458 dimgFakeIcon.hImage = hptrFile;
459 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
460 pDItem->hwndItem = hwndCnr;
461 pDItem->ulItemID = ulSelect++;
462 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
463 ok = ok && pDItem->hstrType;
464 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFFM2ARC);
465 ok = ok && pDItem->hstrRMF;
466 pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
467 ok = ok && pDItem->hstrContainerName;
468 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
469 ok = ok && pDItem->hstrSourceName;
470 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
471 ok = ok && pDItem->hstrTargetName;
472 if (!ok) {
473 DbgMsg(pszSrcFile, __LINE__, "DrgAddStrHandle failed at %lu for %s", ulNumfiles, szFile);
474 // If we have string handle add overflow, release corrupt DragItem
475 // We release 3 more to work around 1st time drag failure reported by Gregg
476 // fixme to know why this happens - PM may need to create a handle?
477 c = first_drag ? 4 : 1;
478 first_drag = FALSE;
479 for (; c > 0 && ulNumfiles > 0; c--) {
480 if (pDItem->hstrType)
481 DrgDeleteStrHandle(pDItem->hstrType);
482 if (pDItem->hstrRMF)
483 DrgDeleteStrHandle(pDItem->hstrRMF);
484 if (pDItem->hstrContainerName)
485 DrgDeleteStrHandle(pDItem->hstrContainerName);
486 if (pDItem->hstrSourceName)
487 DrgDeleteStrHandle(pDItem->hstrSourceName);
488 if (pDItem->hstrTargetName)
489 DrgDeleteStrHandle(pDItem->hstrTargetName);
490 free(pDItem);
491 // Last item not yet count so only decrement by one less than loop count
492 if (c > 1) {
493 ulNumfiles--;
494 pDItem = ppDItem[ulNumfiles];
495 }
496 }
497 // Set count to actual count + 1 to ensure count non-zero on any failure
498 // Unhilite code will adjust this when unhighliting
499 dcd->ulItemsToUnHilite = ulNumfiles + 1;
500 break;
501 }
502 pDItem->fsControl = 0;
503 if (IsFullName(arcfile) &&
504 (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
505 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
506 pDItem->fsSupportedOps = DO_COPYABLE;
507 ulNumfiles++;
508 }
509 // ppDItem[ulNumfiles] = NULL; // Why bother - fixme to be gone?
510 } // if archive object
511 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
512 MPFROM2SHORT(TRUE, CRA_SOURCE));
513
514 Continuing:
515
516 if (!attribute)
517 break;
518 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
519 MPFROMSHORT(attribute));
520 } // while
521
522 if (ulNumfiles) {
523 pDInfo = DrgAllocDraginfo(ulNumfiles);
524 if (pDInfo) {
525 if ((arcfile && *arcfile) || (IsFullName(szBuffer) &&
526 (driveflags[toupper(*szBuffer) - 'A'] &
527 DRIVE_NOTWRITEABLE)))
528 pDInfo->usOperation = DO_COPY;
529 else
530 pDInfo->usOperation = DO_DEFAULT;
531 if ((!arcfile || !*arcfile) && rooting)
532 pDInfo->usOperation = DO_LINK;
533 pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
534 // pDInfo->hwndSource = hwndCnr;
535 for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
536 DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect);
537 xfree(ppDItem[ulSelect], pszSrcFile, __LINE__);
538 }
539#ifdef __DEBUG_ALLOC__
540 _heap_check();
541#endif
542 xfree(ppDItem, pszSrcFile, __LINE__);
543 ppDItem = NULL; // Remember gone
544 DosPostEventSem(CompactSem);
545
546 if (arcfile) {
547 dimgFakeIcon.cb = sizeof(DRAGIMAGE);
548 dimgFakeIcon.cptl = 0;
549 if (ulNumfiles > 1)
550 dimgFakeIcon.hImage = hptrFile;
551 dimgFakeIcon.fl = DRG_ICON;
552 dimgFakeIcon.sizlStretch.cx = 32;
553 dimgFakeIcon.sizlStretch.cy = 32;
554 dimgFakeIcon.cxOffset = -16;
555 dimgFakeIcon.cyOffset = 0;
556 paDImgIcons = &dimgFakeIcon;
557 }
558 if (!arcfile) {
559 if (!ulNumIcon)
560 ulNumIcon = ulNumfiles;
561 }
562 else
563 ulNumIcon = 1;
564
565 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
566 hDrop = DrgDrag(hwndCnr,
567 pDInfo,
568 paDImgIcons,
569 ulNumIcon,
570 VK_ENDDRAG, // Drag end button
571 NULL);
572 WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
573 }
574 }
575
576 if (hDrop == NULLHANDLE ) {
577 dcd->ulItemsToUnHilite = 0;
578 if (pDInfo)
579 FreeDragInfoData(hwndCnr, pDInfo);
580 }
581 xfree(ppDItem, pszSrcFile, __LINE__);
582 if (paDImgIcons && paDImgIcons != &dimgFakeIcon)
583 free(paDImgIcons);
584 DosPostEventSem(CompactSem);
585 MarkAll(hwndCnr, TRUE, FALSE, TRUE);
586 return hDrop;
587}
588
589HWND DragList(HWND hwnd, HWND hwndObj, CHAR ** list, BOOL moveok)
590{
591 // Drag a linked list of files
592
593 BOOL isdir;
594 register CHAR *p;
595 PDRAGINFO pDInfo = NULL;
596 DRAGITEM **ppDItem = NULL, **ppDITest;
597 DRAGITEM *pDItem;
598 HWND hDrop = (HWND) 0;
599 ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
600 CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
601 DRAGIMAGE *paDImgIcons = NULL, *pDImg;
602 FILESTATUS3 fs3;
603 BOOL ok;
604 DIRCNRDATA *dcd;
605
606 if (!list || !list[0])
607 return hDrop;
608
609 dcd = INSTDATA(hwnd);
610
611 for (ulSelect = 0; list[ulSelect]; ulSelect++) {
612 if ((!IsRoot(list[ulSelect]) || !IsValidDrive(*list[ulSelect])) &&
613 DosQueryPathInfo(list[ulSelect], FIL_STANDARD, &fs3, sizeof(fs3)))
614 continue;
615 strcpy(szBuffer, list[ulSelect]);
616 p = strrchr(szBuffer, '\\');
617 if (p) {
618 p++;
619 strcpy(szFile, p);
620 *p = 0;
621 }
622 else
623 continue;
624 if (*szFile) {
625 isdir = IsRoot(list[ulSelect]) || fs3.attrFile & FILE_DIRECTORY;
626 // fixme to expand smarter - expand fast at first - do same for similar code
627 if (ulNumfiles + 2 > ulNumDIAlloc) {
628 if (!paDImgIcons) {
629 pDImg =
630 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
631 pszSrcFile, __LINE__);
632 if (!pDImg)
633 break;
634 paDImgIcons = pDImg;
635 }
636 else if (!ulNumIcon) {
637 pDImg = &paDImgIcons[ulNumfiles];
638 pDImg->cb = sizeof(DRAGIMAGE);
639 pDImg->cptl = 0;
640 pDImg->hImage = hptrLast;
641 pDImg->fl = DRG_ICON;
642 pDImg->sizlStretch.cx = 32;
643 pDImg->sizlStretch.cy = 32;
644 pDImg->cxOffset = -16 + (ulNumfiles * 4);
645 pDImg->cyOffset = 0 + (ulNumfiles * 7);
646 ulNumIcon = ulNumfiles + 1;
647 }
648 ppDITest =
649 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
650 pszSrcFile, __LINE__);
651 if (!ppDITest)
652 break;
653 ppDItem = ppDITest;
654 ulNumDIAlloc += 4L;
655 }
656 // Create & Initialize DRAGITEM
657 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
658 if (!pDItem)
659 break;
660 ppDItem[ulNumfiles] = pDItem;
661 if (!ulNumIcon) {
662 pDImg = &paDImgIcons[ulNumfiles];
663 pDImg->cb = sizeof(DRAGIMAGE);
664 pDImg->cptl = 0;
665 pDImg->hImage = isdir ? hptrDir : hptrFile;
666 pDImg->fl = DRG_ICON;
667 pDImg->sizlStretch.cx = 32;
668 pDImg->sizlStretch.cy = 32;
669 pDImg->cxOffset = -16 + (ulNumfiles * 3);
670 pDImg->cyOffset = 0 + (ulNumfiles * 6);
671 }
672 pDItem->hwndItem = (hwndObj) ? hwndObj : hwnd;
673 pDItem->ulItemID = (ULONG) ulSelect;
674 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
675 ok = pDItem->hstrType;
676 pDItem->hstrRMF = DrgAddStrHandle(DRMDRFLIST);
677 ok = ok && pDItem->hstrRMF;
678 pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
679 ok = ok && pDItem->hstrContainerName;
680 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
681 ok = ok && pDItem->hstrSourceName;
682 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
683 ok = ok && pDItem->hstrTargetName;
684 if (!ok) {
685 if (pDItem->hstrType)
686 DrgDeleteStrHandle(pDItem->hstrType);
687 if (pDItem->hstrRMF)
688 DrgDeleteStrHandle(pDItem->hstrRMF);
689 if (pDItem->hstrContainerName)
690 DrgDeleteStrHandle(pDItem->hstrContainerName);
691 if (pDItem->hstrSourceName)
692 DrgDeleteStrHandle(pDItem->hstrSourceName);
693 if (pDItem->hstrTargetName)
694 DrgDeleteStrHandle(pDItem->hstrTargetName);
695 free(pDItem);
696 // pDItem = NULL; // Why bother, we can count - fixme to be gone
697 dcd->ulItemsToUnHilite = ulNumfiles + 1;
698 break;
699 }
700 pDItem->fsControl = isdir ? DC_CONTAINER : 0;
701 if (IsFullName(list[ulSelect]) &&
702 (driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_REMOVABLE))
703 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
704 pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
705 if (moveok && IsFullName(list[ulSelect]) &&
706 !(driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_NOTWRITEABLE))
707 pDItem->fsSupportedOps |= DO_MOVEABLE;
708 if (IsRoot(list[ulSelect]))
709 pDItem->fsControl = DO_LINKABLE;
710 ulNumfiles++;
711 // ppDItem[ulNumfiles] = NULL; // Why bother - fixme to be gone
712 }
713 } // for
714 if (ulNumfiles) {
715 pDInfo = DrgAllocDraginfo(ulNumfiles);
716 if (pDInfo) {
717 if ((IsFullName(szBuffer) &&
718 (driveflags[toupper(*szBuffer) - 'A'] & DRIVE_NOTWRITEABLE)))
719 pDInfo->usOperation = DO_COPY;
720 else
721 pDInfo->usOperation = DO_DEFAULT;
722 if (IsRoot(list[0]))
723 pDInfo->usOperation = DO_LINK;
724 pDInfo->hwndSource = hwndObj ? hwndObj : hwnd;
725 // pDInfo->hwndSource = hwnd;
726 for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
727 if (!DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect)) {
728 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
729 "DrgSetDragitem");
730 }
731 xfree(ppDItem[ulSelect], pszSrcFile, __LINE__);
732 } // for
733#ifdef __DEBUG_ALLOC__
734 _heap_check();
735#endif
736 xfree(ppDItem, pszSrcFile, __LINE__);
737 ppDItem = NULL; // Remember gone
738 DosPostEventSem(CompactSem);
739
740 if (!ulNumIcon)
741 ulNumIcon = ulNumfiles;
742
743 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
744 hDrop = DrgDrag(hwnd,
745 pDInfo,
746 paDImgIcons,
747 ulNumIcon,
748 VK_ENDDRAG, // Drag end button
749 (PVOID) NULL);
750 if (hDrop == NULLHANDLE) {
751 dcd->ulItemsToUnHilite = 0;
752 FreeDragInfoData(hwnd, pDInfo);
753 }
754 xfree(paDImgIcons, pszSrcFile, __LINE__);
755 paDImgIcons = NULL; // Remember gone
756 WinSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
757 DosPostEventSem(CompactSem);
758 }
759 }
760 xfree(ppDItem, pszSrcFile, __LINE__);
761 xfree(paDImgIcons, pszSrcFile, __LINE__);
762 return hDrop;
763}
764
765#ifdef NEVER // fixme to be enabled someday?
766
767BOOL PickUp(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd)
768{
769
770 PCNRITEM pci;
771 BOOL loop = TRUE;
772 PDRAGINFO pdinfoOld = NULL, pdinfoCurrent = NULL;
773 ULONG cditem = 0;
774 DRAGITEM ditem;
775 DRAGIMAGE dimgFakeIcon;
776 CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
777
778 pci = (PCNRITEM) pcd->pRecord;
779 if (pci && (INT) pci != -1) {
780 if (pci->rc.flRecordAttr & CRA_SELECTED) {
781 loop = TRUE;
782 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
783 MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_SELECTED));
784 }
785 while (pci && (INT) pci != -1 && *pci->pszFileName) {
786 if (pdinfoOld || DrgQueryDragStatus() & DGS_LAZYDRAGINPROGRESS) {
787 if (!pdinfoOld)
788 pdinfoOld = DrgQueryDraginfoPtr(NULL);
789 if (pdinfoOld) {
790 cditem = pdinfoOld->cditem + 1;
791 pdinfoCurrent = DrgReallocDraginfo(pdinfoOld, cditem);
792 pdinfoOld = pdinfoCurrent;
793 }
794 }
795 else
796 pdinfoCurrent = pdinfoOld = DrgAllocDraginfo(1);
797 if (pdinfoCurrent) {
798 strcpy(szDir, pci->pszFileName);
799 p = szDir;
800 while (*p) {
801 if (*p == '/')
802 *p = '\\';
803 p++;
804 }
805 p = strrchr(szDir, '\\');
806 if (p) {
807 *p = 0;
808 p++;
809 strcpy(szFile, p);
810 strcat(szDir, "\\");
811 }
812 else {
813 strcpy(szFile, pci->pszFileName);
814 *szDir = 0;
815 }
816 ditem.ulItemID = (ULONG) pci;
817 ditem.hwndItem = (hwndObj) ? hwndObj : hwndCnr;
818 ditem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
819 ditem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
820 ditem.hstrContainerName = DrgAddStrHandle(szDir);
821 ditem.hstrSourceName = DrgAddStrHandle(szFile);
822 // fixme to check better if code ever enabled
823 if (!ditem.hstrSourceName) {
824 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
825 "DrgAddStrHandle");
826 }
827 ditem.hstrTargetName = DrgAddStrHandle(szFile);
828 ditem.fsControl = 0;
829 if (IsRoot(pci->pszFileName) || (pci->attrFile & FILE_DIRECTORY) != 0)
830 ditem.fsControl |= DC_CONTAINER;
831 if (IsFullName(pci->pszFileName) &&
832 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
833 ditem.fsControl |= DC_REMOVEABLEMEDIA;
834 ditem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
835 if (IsFullName(pci->pszFileName) &&
836 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
837 DRIVE_NOTWRITEABLE))
838 ditem.fsSupportedOps |= DO_MOVEABLE;
839 if (IsRoot(pci->pszFileName))
840 ditem.fsSupportedOps = DO_LINKABLE;
841 memset(&dimgFakeIcon, 0, sizeof(DRAGIMAGE));
842 dimgFakeIcon.hImage = pci->rc.hptrIcon;
843 dimgFakeIcon.cb = sizeof(DRAGIMAGE);
844 dimgFakeIcon.cptl = 0;
845 dimgFakeIcon.fl = DRG_ICON;
846 dimgFakeIcon.sizlStretch.cx = 32;
847 dimgFakeIcon.sizlStretch.cy = 32;
848 dimgFakeIcon.cxOffset = -16;
849 dimgFakeIcon.cyOffset = 0;
850 if (IsFullName(pci->pszFileName) &&
851 (driveflags[toupper(*pci->pszFileName) - 'A'] &
852 DRIVE_NOTWRITEABLE))
853 pdinfoCurrent->usOperation = DO_COPY;
854 else
855 pdinfoCurrent->usOperation = DO_DEFAULT;
856 if (IsRoot(pci->pszFileName))
857 pdinfoCurrent->usOperation = DO_LINK;
858 pdinfoCurrent->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
859 DrgSetDragitem(pdinfoCurrent, &ditem, sizeof(DRAGITEM), cditem);
860 }
861 if (!loop)
862 break;
863 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
864 MPFROMP(pci), MPFROMSHORT(CRA_SELECTED));
865 } // while
866 if (pdinfoCurrent)
867 return DrgLazyDrag(hwndCnr, pdinfoCurrent, &dimgFakeIcon, 1, NULL);
868 }
869 return FALSE;
870}
871
872#endif // NEVER
873
874#pragma alloc_text(DRAGLIST,DragOne,DoFileDrag,DragList,PickUp,FreeDragInfoData)
Note: See TracBrowser for help on using the repository browser.