source: trunk/dll/draglist.c@ 1641

Last change on this file since 1641 was 1641, checked in by Gregg Young, 14 years ago

Fix trap on attempted drag from compare directory dialog

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