source: trunk/dll/draglist.c@ 1453

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

Avoid (?spurrious error) when dragging multiple files from a pmmail mail message. (ticket 391)

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