source: trunk/dll/draglist.c@ 1463

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

Fixed typo in changes to fix ticket 391 (drag from pmmail error messages)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.1 KB
Line 
1
2/***********************************************************************
3
4 $Id: draglist.c 1463 2009-09-20 18:08:46Z 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 (!IsFm2Window(pDInfo->hwndSource, FALSE)) {
77 if (!DrgDeleteDraginfoStrHandles(pDInfo)) {
78 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
79 "DrgDeleteDraginfoStrHandles");
80 }
81 }
82 //# else // The slow way
83 else {
84 PDRAGITEM pDItem;
85 ULONG cDitem;
86 ULONG curitem;
87 APIRET ok;
88
89 cDitem = DrgQueryDragitemCount(pDInfo);
90 for (curitem = 0; curitem < cDitem; curitem++) {
91 pDItem = DrgQueryDragitemPtr(pDInfo, curitem);
92 if (!pDItem) {
93 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
94 "DrgQueryDragitemPtr(%u)", curitem);
95 }
96 else {
97 ok = DrgDeleteStrHandle(pDItem->hstrType);
98 if (!ok) {
99 HAB hab = WinQueryAnchorBlock(hwnd);
100 PERRINFO pErrInfoBlk = WinGetErrorInfo(hab);
101 if (ERRORIDERROR(pErrInfoBlk->idError) != PMERR_INVALID_PARAMETER)
102 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
103 "DrgDeleteStrHandle(0x%x) hstrType",pDItem->hstrType);
104 }
105 ok = DrgDeleteStrHandle(pDItem->hstrRMF);
106 if (!ok) {
107 HAB hab = WinQueryAnchorBlock(hwnd);
108 PERRINFO pErrInfoBlk = WinGetErrorInfo(hab);
109 if (ERRORIDERROR(pErrInfoBlk->idError) != PMERR_INVALID_PARAMETER)
110 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
111 "DrgDeleteStrHandle(0x%x) hstrRMF",pDItem->hstrRMF);
112 }
113 ok = DrgDeleteStrHandle(pDItem->hstrContainerName);
114 if (!ok) {
115 HAB hab = WinQueryAnchorBlock(hwnd);
116 PERRINFO pErrInfoBlk = WinGetErrorInfo(hab);
117 if (ERRORIDERROR(pErrInfoBlk->idError) != PMERR_INVALID_PARAMETER)
118 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
119 "DrgDeleteStrHandle(0x%x) hstrContainerName",pDItem->hstrContainerName);
120 }
121 ok = DrgDeleteStrHandle(pDItem->hstrSourceName);
122 if (!ok) {
123 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
124 "DrgDeleteStrHandle(0x%x) hstrSourceName",pDItem->hstrSourceName);
125 }
126 ok = DrgDeleteStrHandle(pDItem->hstrTargetName);
127 if (!ok) {
128 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__,
129 "DrgDeleteStrHandle(0x%x) hstrTargetName",pDItem->hstrTargetName);
130 }
131 }
132 } // for
133 }
134//# endif
135 if (!DrgFreeDraginfo(pDInfo)) {
136 // PMERR_SOURCE_SAME_AS_TARGET is not an error if dragging within same fm/2 process
137 if (!IsFm2Window(pDInfo->hwndSource, FALSE) ||
138 (WinGetLastError(WinQueryAnchorBlock(hwnd)) & 0xffff) != PMERR_SOURCE_SAME_AS_TARGET)
139 {
140 Win_Error(hwnd, hwnd, pszSrcFile, __LINE__, "DrgFreeDraginfo");
141 }
142 }
143}
144
145HWND DragOne(HWND hwndCnr, HWND hwndObj, CHAR * filename, BOOL moveok)
146{
147
148 DRAGITEM DItem;
149 HWND hDrop = 0;
150 DRAGIMAGE fakeicon;
151 PDRAGINFO pDInfo;
152 FILESTATUS3 fs3;
153 CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
154
155 if (filename && *filename) {
156 if ((IsRoot(filename) && IsValidDrive(*filename)) ||
157 !DosQueryPathInfo(filename, FIL_STANDARD, &fs3, sizeof(fs3))) {
158 strcpy(szDir, filename);
159 p = szDir;
160 while (*p) {
161 if (*p == '/')
162 *p = '\\';
163 p++;
164 }
165 p = strrchr(szDir, '\\');
166 if (p) {
167 *p = 0;
168 p++;
169 strcpy(szFile, p);
170 strcat(szDir, PCSZ_BACKSLASH);
171 }
172 else {
173 strcpy(szFile, filename);
174 *szDir = 0;
175 }
176 memset(&fakeicon, 0, sizeof(DRAGIMAGE));
177 fakeicon.hImage = (IsRoot(filename) ||
178 (fs3.attrFile & FILE_DIRECTORY) != 0) ?
179 hptrDir : hptrFile;
180 memset(&DItem, 0, sizeof(DRAGITEM));
181 DItem.hwndItem = (hwndObj) ? hwndObj : hwndCnr; // Initialize DRAGITEM
182 // DItem.hwndItem = hwndCnr;
183 DItem.ulItemID = 1;
184 DItem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
185 DItem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
186 DItem.hstrContainerName = DrgAddStrHandle(szDir);
187 DItem.hstrSourceName = DrgAddStrHandle(szFile);
188 if (!DItem.hstrSourceName)
189 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
190 "DrgQueryStrName");
191 DItem.hstrTargetName = DrgAddStrHandle(szFile);
192 DItem.fsControl = 0;
193 if (IsRoot(filename) || (fs3.attrFile & FILE_DIRECTORY) != 0)
194 DItem.fsControl |= DC_CONTAINER;
195 if (IsFullName(filename) &&
196 (driveflags[toupper(*filename) - 'A'] & DRIVE_REMOVABLE))
197 DItem.fsControl |= DC_REMOVEABLEMEDIA;
198 DItem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
199 if (moveok && IsFullName(filename) &&
200 !(driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
201 DItem.fsSupportedOps |= DO_MOVEABLE;
202 if (IsRoot(filename))
203 DItem.fsSupportedOps = DO_LINKABLE;
204 fakeicon.cb = sizeof(DRAGIMAGE);
205 fakeicon.cptl = 0;
206 fakeicon.fl = DRG_ICON;
207 fakeicon.sizlStretch.cx = 32;
208 fakeicon.sizlStretch.cy = 32;
209 fakeicon.cxOffset = -16;
210 fakeicon.cyOffset = 0;
211 pDInfo = DrgAllocDraginfo(1);
212 if (pDInfo) {
213 if (IsFullName(filename) &&
214 (driveflags[toupper(*filename) - 'A'] & DRIVE_NOTWRITEABLE))
215 pDInfo->usOperation = DO_COPY;
216 else
217 pDInfo->usOperation = DO_DEFAULT;
218 if (IsRoot(filename))
219 pDInfo->usOperation = DO_LINK;
220 pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
221 // pDInfo->hwndSource = hwndCnr;
222 DrgSetDragitem(pDInfo, &DItem, sizeof(DRAGITEM), 0);
223 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
224 hDrop = DrgDrag(hwndCnr,
225 pDInfo,
226 &fakeicon,
227 1, // DragImage count
228 VK_ENDDRAG, // Drag end button
229 NULL);
230 if (hDrop == NULLHANDLE)
231 FreeDragInfoData(hwndCnr, pDInfo);
232 WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
233 }
234 }
235 }
236 return hDrop;
237}
238
239HWND DoFileDrag(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd, CHAR * arcfile,
240 CHAR * directory, BOOL moveok)
241{
242 // Drag files from a container
243
244 BOOL isdir, rooting = FALSE;
245 PCNRITEM pci;
246 CHAR *p;
247 INT attribute = CRA_CURSORED;
248 PDRAGINFO pDInfo = NULL;
249 DRAGITEM **ppDItem = NULL, **ppDITest;
250 DRAGITEM *pDItem;
251 PCNRITEM pciRec = (PCNRITEM) pcd->pRecord;
252 HWND hDrop = NULLHANDLE;
253 ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
254 CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
255 DRAGIMAGE *paDImgIcons = NULL, *pDImg, dimgFakeIcon;
256 BOOL ok;
257 UINT c;
258 DIRCNRDATA *dcd;
259
260 static BOOL first_drag = TRUE;
261
262 // Count items to unhilite, pass to UnHilite when partial unhilite required
263 dcd = INSTDATA(hwndCnr);
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 + (ulNumfiles * 4);
332 pDImg->cyOffset = 0 + (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 + (ulNumfiles * 3);
359 pDImg->cyOffset = 0 + (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(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(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(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 + (ulNumfiles * 4);
662 pDImg->cyOffset = 0 + (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 + (ulNumfiles * 3);
687 pDImg->cyOffset = 0 + (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(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 p = szDir;
817 while (*p) {
818 if (*p == '/')
819 *p = '\\';
820 p++;
821 }
822 p = strrchr(szDir, '\\');
823 if (p) {
824 *p = 0;
825 p++;
826 strcpy(szFile, p);
827 strcat(szDir, PCSZ_BACKSLASH);
828 }
829 else {
830 strcpy(szFile, pci->pszFileName);
831 *szDir = 0;
832 }
833 ditem.ulItemID = (ULONG) pci;
834 ditem.hwndItem = (hwndObj) ? hwndObj : hwndCnr;
835 ditem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
836 ditem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
837 ditem.hstrContainerName = DrgAddStrHandle(szDir);
838 ditem.hstrSourceName = DrgAddStrHandle(szFile);
839 // fixme to check better if code ever enabled
840 if (!ditem.hstrSourceName) {
841 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
842 "DrgAddStrHandle");
843 }
844 ditem.hstrTargetName = DrgAddStrHandle(szFile);
845 ditem.fsControl = 0;
846 if (IsRoot(pci->pszFileName) || (pci->attrFile & FILE_DIRECTORY) != 0)
847 ditem.fsControl |= DC_CONTAINER;
848 if (IsFullName(pci->pszFileName) &&
849 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
850 ditem.fsControl |= DC_REMOVEABLEMEDIA;
851 ditem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
852 if (IsFullName(pci->pszFileName) &&
853 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
854 DRIVE_NOTWRITEABLE))
855 ditem.fsSupportedOps |= DO_MOVEABLE;
856 if (IsRoot(pci->pszFileName))
857 ditem.fsSupportedOps = DO_LINKABLE;
858 memset(&dimgFakeIcon, 0, sizeof(DRAGIMAGE));
859 dimgFakeIcon.hImage = pci->rc.hptrIcon;
860 dimgFakeIcon.cb = sizeof(DRAGIMAGE);
861 dimgFakeIcon.cptl = 0;
862 dimgFakeIcon.fl = DRG_ICON;
863 dimgFakeIcon.sizlStretch.cx = 32;
864 dimgFakeIcon.sizlStretch.cy = 32;
865 dimgFakeIcon.cxOffset = -16;
866 dimgFakeIcon.cyOffset = 0;
867 if (IsFullName(pci->pszFileName) &&
868 (driveflags[toupper(*pci->pszFileName) - 'A'] &
869 DRIVE_NOTWRITEABLE))
870 pdinfoCurrent->usOperation = DO_COPY;
871 else
872 pdinfoCurrent->usOperation = DO_DEFAULT;
873 if (IsRoot(pci->pszFileName))
874 pdinfoCurrent->usOperation = DO_LINK;
875 pdinfoCurrent->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
876 DrgSetDragitem(pdinfoCurrent, &ditem, sizeof(DRAGITEM), cditem);
877 }
878 if (!loop)
879 break;
880 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
881 MPFROMP(pci), MPFROMSHORT(CRA_SELECTED));
882 } // while
883 if (pdinfoCurrent)
884 return DrgLazyDrag(hwndCnr, pdinfoCurrent, &dimgFakeIcon, 1, NULL);
885 }
886 return FALSE;
887}
888
889#endif // NEVER
890
891#pragma alloc_text(DRAGLIST,DragOne,DoFileDrag,DragList,PickUp,FreeDragInfoData)
Note: See TracBrowser for help on using the repository browser.