source: trunk/dll/draglist.c@ 1438

Last change on this file since 1438 was 1438, checked in by Gregg Young, 16 years ago

Improved drivebar changes; Added AddBackslashToPath() to remove repeatative code. replaced "
" with PCSZ variable; ANY_OBJ added the DosAlloc... (experimental)

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