source: trunk/dll/draglist.c@ 1570

Last change on this file since 1570 was 1545, checked in by Gregg Young, 15 years ago

Added ForwardslashToBackslash function to streamline code.

  • 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 1545 2010-10-23 22:00:47Z 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 dcd->ulItemsToUnHilite = 0;
263 if (!pciRec && directory && *directory)
264 return DragOne(hwndCnr, hwndObj, directory, moveok);
265
266 if (!pciRec) {
267 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
268 MPFROMLONG(CMA_FIRST),
269 MPFROMSHORT(attribute));
270 if (pci && (INT) pci > -1) {
271 if (pci->rc.flRecordAttr & CRA_SELECTED) {
272 attribute = CRA_SELECTED;
273 pci =
274 WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
275 MPFROMSHORT(attribute));
276 }
277 }
278 }
279 else {
280 pci = pciRec;
281 attribute = (pci->rc.flRecordAttr & CRA_SELECTED) ? CRA_SELECTED : 0;
282 if (attribute) {
283 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMLONG(CMA_FIRST),
284 MPFROMSHORT(attribute));
285 }
286 }
287
288 ulSelect = 0;
289 while (pci && (INT) pci > -1) {
290 if (!(pci->rc.flRecordAttr & CRA_FILTERED)) {
291 if (IsRoot(pci->pszFileName) && !IsValidDrive(*pci->pszFileName))
292 goto Continuing;
293 if (!arcfile) {
294 strcpy(szBuffer, pci->pszFileName);
295 p = strrchr(szBuffer, '\\');
296 if (p) {
297 p++;
298 strcpy(szFile, p);
299 *p = 0;
300 }
301 else
302 goto Continuing;
303 }
304 else
305 strcpy(szFile, pci->pszFileName);
306 }
307 if (!arcfile) {
308 // Filesystem object
309 isdir = pci->attrFile & FILE_DIRECTORY;
310 // fixme to expand smarter - expand fast at first - do same for similar code
311 if (ulNumfiles + 2 > ulNumDIAlloc) {
312 // Expand
313 if (!paDImgIcons) {
314 pDImg =
315 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
316 pszSrcFile, __LINE__);
317 if (!pDImg)
318 break;
319 paDImgIcons = pDImg;
320 }
321 else if (!ulNumIcon) {
322 pDImg = &paDImgIcons[ulNumfiles];
323 pDImg->cb = sizeof(DRAGIMAGE);
324 pDImg->cptl = 0;
325 pDImg->hImage = hptrLast;
326 pDImg->fl = DRG_ICON;
327 pDImg->sizlStretch.cx = 32;
328 pDImg->sizlStretch.cy = 32;
329 pDImg->cxOffset = -16 + ((SHORT) ulNumfiles * 4);
330 pDImg->cyOffset = 0 + ((SHORT) ulNumfiles * 7);
331 ulNumIcon = ulNumfiles + 1;
332 }
333 ppDITest =
334 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
335 pszSrcFile, __LINE__);
336 if (!ppDITest)
337 break;
338 ppDItem = ppDITest;
339 ulNumDIAlloc += 4L;
340 }
341 // Create & Initialize DRAGITEM
342 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
343 if (!pDItem)
344 break; // Already complained
345 ppDItem[ulNumfiles] = pDItem;
346 if (!ulNumIcon) {
347 pDImg = &paDImgIcons[ulNumfiles];
348 pDImg->cb = sizeof(DRAGIMAGE);
349 pDImg->cptl = 0;
350 pDImg->hImage = pci->rc.hptrIcon;
351 if (!pDImg->hImage)
352 pDImg->hImage = isdir ? hptrDir : hptrFile;
353 pDImg->fl = DRG_ICON;
354 pDImg->sizlStretch.cx = 32;
355 pDImg->sizlStretch.cy = 32;
356 pDImg->cxOffset = -16 + ((SHORT) ulNumfiles * 3);
357 pDImg->cyOffset = 0 + ((SHORT) ulNumfiles * 6);
358 }
359 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
360 pDItem->hwndItem = hwndCnr;
361 pDItem->ulItemID = (ULONG) pci;
362 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
363 ok = pDItem->hstrType;
364 pDItem->hstrRMF = DrgAddStrHandle((CHAR *) DRMDRFLIST);
365 ok = ok && pDItem->hstrRMF;
366 pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
367 ok = ok && pDItem->hstrContainerName;
368 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
369 ok = ok && pDItem->hstrSourceName;
370 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
371 ok = ok && pDItem->hstrTargetName;
372 if (!ok) {
373 //DbgMsg(pszSrcFile, __LINE__, "DrgAddStrHandle failed at %lu for %s", ulNumfiles, szFile);
374 // If we have string handle add overflow, release corrupt DragItem
375 // We release 3 more to work around 1st time drag failure reported by Gregg
376 // fixme to know why this happens - PM may need to create a handle?
377 c = first_drag ? 4 : 1;
378 first_drag = FALSE;
379 for (; c > 0 && ulNumfiles > 0; c--) {
380 if (pDItem->hstrType)
381 DrgDeleteStrHandle(pDItem->hstrType);
382 if (pDItem->hstrRMF)
383 DrgDeleteStrHandle(pDItem->hstrRMF);
384 if (pDItem->hstrContainerName)
385 DrgDeleteStrHandle(pDItem->hstrContainerName);
386 if (pDItem->hstrSourceName)
387 DrgDeleteStrHandle(pDItem->hstrSourceName);
388 if (pDItem->hstrTargetName)
389 DrgDeleteStrHandle(pDItem->hstrTargetName);
390 free(pDItem);
391 // Last item not yet count so only decrement by one less than loop count
392 // Unhilite code will adjust this when unhighliting
393 if (c > 1) {
394 ulNumfiles--;
395 pDItem = ppDItem[ulNumfiles];
396 }
397 }
398 // Set count to actual count + 1 to ensure count non-zero on any failure
399 dcd->ulItemsToUnHilite = ulNumfiles + 1;
400 break;
401 }
402 pDItem->fsControl = isdir ? DC_CONTAINER : 0;
403 if (IsFullName(pci->pszFileName) &&
404 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
405 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
406 pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
407 if (moveok && IsFullName(pci->pszFileName) &&
408 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
409 DRIVE_NOTWRITEABLE))
410 pDItem->fsSupportedOps |= DO_MOVEABLE;
411 if (IsRoot(pci->pszFileName)) {
412 pDItem->fsSupportedOps = DO_LINKABLE;
413 rooting = TRUE;
414 }
415 ulNumfiles++;
416 // ppDItem[ulNumfiles] = NULL; // Why bother - can't we count - fixme to be gone?
417 } // if filesystem object
418 else {
419 // Archive object
420 if (ulNumfiles + 3L > ulNumDIAlloc) {
421 ppDITest =
422 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 5L),
423 pszSrcFile, __LINE__);
424 if (!ppDITest)
425 break;
426 ppDItem = ppDITest;
427 ulNumDIAlloc += 5L;
428 }
429 // Create & Initialize DRAGITEM
430 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
431 if (!pDItem)
432 break;
433 ppDItem[ulNumfiles] = pDItem;
434 dimgFakeIcon.hImage = hptrFile;
435 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
436 pDItem->hwndItem = hwndCnr;
437 pDItem->ulItemID = (ULONG) pci;
438 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
439 ok = pDItem->hstrType;
440 pDItem->hstrRMF = DrgAddStrHandle((CHAR *) DRMDRFOS2FILE);
441 ok = ok && pDItem->hstrRMF;
442 pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
443 ok = ok && pDItem->hstrContainerName;
444 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
445 ok = ok && pDItem->hstrSourceName;
446 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
447 ok = ok && pDItem->hstrTargetName;
448 if (!ok){
449 if (pDItem->hstrType)
450 DrgDeleteStrHandle(pDItem->hstrType);
451 if (pDItem->hstrRMF)
452 DrgDeleteStrHandle(pDItem->hstrRMF);
453 if (pDItem->hstrContainerName)
454 DrgDeleteStrHandle(pDItem->hstrContainerName);
455 if (pDItem->hstrSourceName)
456 DrgDeleteStrHandle(pDItem->hstrSourceName);
457 if (pDItem->hstrTargetName)
458 DrgDeleteStrHandle(pDItem->hstrTargetName);
459 free(pDItem);
460 dcd->ulItemsToUnHilite = ulNumfiles + 1; // +1 to ensure non-zero
461 break;
462 }
463 pDItem->fsControl = DC_PREPARE;
464 if (IsFullName(arcfile) &&
465 (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
466 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
467 pDItem->fsSupportedOps = DO_COPYABLE;
468 ulNumfiles++;
469 // Create & Initialize DRAGITEM
470 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
471 if (pDItem) {
472 ppDItem[ulNumfiles] = pDItem;
473 dimgFakeIcon.hImage = hptrFile;
474 pDItem->hwndItem = (hwndObj) ? hwndObj : hwndCnr;
475 pDItem->hwndItem = hwndCnr;
476 pDItem->ulItemID = ulSelect++;
477 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
478 ok = ok && pDItem->hstrType;
479 pDItem->hstrRMF = DrgAddStrHandle((CHAR *) DRMDRFFM2ARC);
480 ok = ok && pDItem->hstrRMF;
481 pDItem->hstrContainerName = DrgAddStrHandle(arcfile);
482 ok = ok && pDItem->hstrContainerName;
483 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
484 ok = ok && pDItem->hstrSourceName;
485 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
486 ok = ok && pDItem->hstrTargetName;
487 if (!ok) {
488 //DbgMsg(pszSrcFile, __LINE__, "DrgAddStrHandle failed at %lu for %s", ulNumfiles, szFile);
489 // If we have string handle add overflow, release corrupt DragItem
490 // We release 3 more to work around 1st time drag failure reported by Gregg
491 // fixme to know why this happens - PM may need to create a handle?
492 c = first_drag ? 4 : 1;
493 first_drag = FALSE;
494 for (; c > 0 && ulNumfiles > 0; c--) {
495 if (pDItem->hstrType)
496 DrgDeleteStrHandle(pDItem->hstrType);
497 if (pDItem->hstrRMF)
498 DrgDeleteStrHandle(pDItem->hstrRMF);
499 if (pDItem->hstrContainerName)
500 DrgDeleteStrHandle(pDItem->hstrContainerName);
501 if (pDItem->hstrSourceName)
502 DrgDeleteStrHandle(pDItem->hstrSourceName);
503 if (pDItem->hstrTargetName)
504 DrgDeleteStrHandle(pDItem->hstrTargetName);
505 free(pDItem);
506 // Last item not yet count so only decrement by one less than loop count
507 if (c > 1) {
508 ulNumfiles--;
509 pDItem = ppDItem[ulNumfiles];
510 }
511 }
512 // Set count to actual count + 1 to ensure count non-zero on any failure
513 // Unhilite code will adjust this when unhighliting
514 dcd->ulItemsToUnHilite = ulNumfiles + 1;
515 break;
516 }
517 pDItem->fsControl = 0;
518 if (IsFullName(arcfile) &&
519 (driveflags[toupper(*arcfile) - 'A'] & DRIVE_REMOVABLE))
520 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
521 pDItem->fsSupportedOps = DO_COPYABLE;
522 ulNumfiles++;
523 }
524 // ppDItem[ulNumfiles] = NULL; // Why bother - fixme to be gone?
525 } // if archive object
526 WinSendMsg(hwndCnr, CM_SETRECORDEMPHASIS, MPFROMP(pci),
527 MPFROM2SHORT(TRUE, CRA_SOURCE));
528
529 Continuing:
530
531 if (!attribute)
532 break;
533 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS, MPFROMP(pci),
534 MPFROMSHORT(attribute));
535 } // while
536
537 if (ulNumfiles) {
538 pDInfo = DrgAllocDraginfo(ulNumfiles);
539 if (pDInfo) {
540 if ((arcfile && *arcfile) || (IsFullName(szBuffer) &&
541 (driveflags[toupper(*szBuffer) - 'A'] &
542 DRIVE_NOTWRITEABLE)))
543 pDInfo->usOperation = DO_COPY;
544 else
545 pDInfo->usOperation = DO_DEFAULT;
546 if ((!arcfile || !*arcfile) && rooting)
547 pDInfo->usOperation = DO_LINK;
548 pDInfo->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
549 // pDInfo->hwndSource = hwndCnr;
550 for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
551 DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect);
552 xfree(ppDItem[ulSelect], pszSrcFile, __LINE__);
553 }
554#ifdef __DEBUG_ALLOC__
555 _heap_check();
556#endif
557 xfree(ppDItem, pszSrcFile, __LINE__);
558 ppDItem = NULL; // Remember gone
559 DosPostEventSem(CompactSem);
560
561 if (arcfile) {
562 dimgFakeIcon.cb = sizeof(DRAGIMAGE);
563 dimgFakeIcon.cptl = 0;
564 if (ulNumfiles > 1)
565 dimgFakeIcon.hImage = hptrFile;
566 dimgFakeIcon.fl = DRG_ICON;
567 dimgFakeIcon.sizlStretch.cx = 32;
568 dimgFakeIcon.sizlStretch.cy = 32;
569 dimgFakeIcon.cxOffset = -16;
570 dimgFakeIcon.cyOffset = 0;
571 paDImgIcons = &dimgFakeIcon;
572 }
573 if (!arcfile) {
574 if (!ulNumIcon)
575 ulNumIcon = ulNumfiles;
576 }
577 else
578 ulNumIcon = 1;
579
580 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
581 hDrop = DrgDrag(hwndCnr,
582 pDInfo,
583 paDImgIcons,
584 ulNumIcon,
585 VK_ENDDRAG, // Drag end button
586 NULL);
587 WinSetWindowPos(hwndCnr, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
588 }
589 }
590
591 if (hDrop == NULLHANDLE ) {
592 dcd->ulItemsToUnHilite = 0;
593 if (pDInfo)
594 FreeDragInfoData(hwndCnr, pDInfo);
595 }
596 xfree(ppDItem, pszSrcFile, __LINE__);
597 if (paDImgIcons && paDImgIcons != &dimgFakeIcon)
598 free(paDImgIcons);
599 DosPostEventSem(CompactSem);
600 MarkAll(hwndCnr, TRUE, FALSE, TRUE);
601 return hDrop;
602}
603
604HWND DragList(HWND hwnd, HWND hwndObj, CHAR ** list, BOOL moveok)
605{
606 // Drag a linked list of files
607
608 BOOL isdir;
609 register CHAR *p;
610 PDRAGINFO pDInfo = NULL;
611 DRAGITEM **ppDItem = NULL, **ppDITest;
612 DRAGITEM *pDItem;
613 HWND hDrop = (HWND) 0;
614 ULONG ulNumfiles = 0, ulNumDIAlloc = 0, ulSelect, ulNumIcon = 0;
615 CHAR szFile[CCHMAXPATH], szBuffer[CCHMAXPATH];
616 DRAGIMAGE *paDImgIcons = NULL, *pDImg;
617 FILESTATUS3 fs3;
618 BOOL ok;
619 DIRCNRDATA *dcd;
620
621 if (!list || !list[0])
622 return hDrop;
623
624 dcd = INSTDATA(hwnd);
625
626 for (ulSelect = 0; list[ulSelect]; ulSelect++) {
627 if ((!IsRoot(list[ulSelect]) || !IsValidDrive(*list[ulSelect])) &&
628 DosQueryPathInfo(list[ulSelect], FIL_STANDARD, &fs3, sizeof(fs3)))
629 continue;
630 strcpy(szBuffer, list[ulSelect]);
631 p = strrchr(szBuffer, '\\');
632 if (p) {
633 p++;
634 strcpy(szFile, p);
635 *p = 0;
636 }
637 else
638 continue;
639 if (*szFile) {
640 isdir = IsRoot(list[ulSelect]) || fs3.attrFile & FILE_DIRECTORY;
641 // fixme to expand smarter - expand fast at first - do same for similar code
642 if (ulNumfiles + 2 > ulNumDIAlloc) {
643 if (!paDImgIcons) {
644 pDImg =
645 xrealloc(paDImgIcons, sizeof(DRAGIMAGE) * (ulNumDIAlloc + 4L),
646 pszSrcFile, __LINE__);
647 if (!pDImg)
648 break;
649 paDImgIcons = pDImg;
650 }
651 else if (!ulNumIcon) {
652 pDImg = &paDImgIcons[ulNumfiles];
653 pDImg->cb = sizeof(DRAGIMAGE);
654 pDImg->cptl = 0;
655 pDImg->hImage = hptrLast;
656 pDImg->fl = DRG_ICON;
657 pDImg->sizlStretch.cx = 32;
658 pDImg->sizlStretch.cy = 32;
659 pDImg->cxOffset = -16 + ((SHORT) ulNumfiles * 4);
660 pDImg->cyOffset = 0 + ((SHORT) ulNumfiles * 7);
661 ulNumIcon = ulNumfiles + 1;
662 }
663 ppDITest =
664 xrealloc(ppDItem, sizeof(DRAGITEM *) * (ulNumDIAlloc + 4L),
665 pszSrcFile, __LINE__);
666 if (!ppDITest)
667 break;
668 ppDItem = ppDITest;
669 ulNumDIAlloc += 4L;
670 }
671 // Create & Initialize DRAGITEM
672 pDItem = xmallocz(sizeof(DRAGITEM), pszSrcFile, __LINE__);
673 if (!pDItem)
674 break;
675 ppDItem[ulNumfiles] = pDItem;
676 if (!ulNumIcon) {
677 pDImg = &paDImgIcons[ulNumfiles];
678 pDImg->cb = sizeof(DRAGIMAGE);
679 pDImg->cptl = 0;
680 pDImg->hImage = isdir ? hptrDir : hptrFile;
681 pDImg->fl = DRG_ICON;
682 pDImg->sizlStretch.cx = 32;
683 pDImg->sizlStretch.cy = 32;
684 pDImg->cxOffset = -16 + ((SHORT) ulNumfiles * 3);
685 pDImg->cyOffset = 0 + ((SHORT) ulNumfiles * 6);
686 }
687 pDItem->hwndItem = (hwndObj) ? hwndObj : hwnd;
688 pDItem->ulItemID = (ULONG) ulSelect;
689 pDItem->hstrType = DrgAddStrHandle(DRT_UNKNOWN);
690 ok = pDItem->hstrType;
691 pDItem->hstrRMF = DrgAddStrHandle((CHAR *) DRMDRFLIST);
692 ok = ok && pDItem->hstrRMF;
693 pDItem->hstrContainerName = DrgAddStrHandle(szBuffer);
694 ok = ok && pDItem->hstrContainerName;
695 pDItem->hstrSourceName = DrgAddStrHandle(szFile);
696 ok = ok && pDItem->hstrSourceName;
697 pDItem->hstrTargetName = DrgAddStrHandle(szFile);
698 ok = ok && pDItem->hstrTargetName;
699 if (!ok) {
700 if (pDItem->hstrType)
701 DrgDeleteStrHandle(pDItem->hstrType);
702 if (pDItem->hstrRMF)
703 DrgDeleteStrHandle(pDItem->hstrRMF);
704 if (pDItem->hstrContainerName)
705 DrgDeleteStrHandle(pDItem->hstrContainerName);
706 if (pDItem->hstrSourceName)
707 DrgDeleteStrHandle(pDItem->hstrSourceName);
708 if (pDItem->hstrTargetName)
709 DrgDeleteStrHandle(pDItem->hstrTargetName);
710 free(pDItem);
711 // pDItem = NULL; // Why bother, we can count - fixme to be gone
712 dcd->ulItemsToUnHilite = ulNumfiles + 1;
713 break;
714 }
715 pDItem->fsControl = isdir ? DC_CONTAINER : 0;
716 if (IsFullName(list[ulSelect]) &&
717 (driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_REMOVABLE))
718 pDItem->fsControl |= DC_REMOVEABLEMEDIA;
719 pDItem->fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
720 if (moveok && IsFullName(list[ulSelect]) &&
721 !(driveflags[toupper(*list[ulSelect]) - 'A'] & DRIVE_NOTWRITEABLE))
722 pDItem->fsSupportedOps |= DO_MOVEABLE;
723 if (IsRoot(list[ulSelect]))
724 pDItem->fsControl = DO_LINKABLE;
725 ulNumfiles++;
726 // ppDItem[ulNumfiles] = NULL; // Why bother - fixme to be gone
727 }
728 } // for
729 if (ulNumfiles) {
730 pDInfo = DrgAllocDraginfo(ulNumfiles);
731 if (pDInfo) {
732 if ((IsFullName(szBuffer) &&
733 (driveflags[toupper(*szBuffer) - 'A'] & DRIVE_NOTWRITEABLE)))
734 pDInfo->usOperation = DO_COPY;
735 else
736 pDInfo->usOperation = DO_DEFAULT;
737 if (IsRoot(list[0]))
738 pDInfo->usOperation = DO_LINK;
739 pDInfo->hwndSource = hwndObj ? hwndObj : hwnd;
740 // pDInfo->hwndSource = hwnd;
741 for (ulSelect = 0; ulSelect < ulNumfiles; ulSelect++) {
742 if (!DrgSetDragitem(pDInfo, ppDItem[ulSelect], sizeof(DRAGITEM), ulSelect)) {
743 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
744 "DrgSetDragitem");
745 }
746 xfree(ppDItem[ulSelect], pszSrcFile, __LINE__);
747 } // for
748#ifdef __DEBUG_ALLOC__
749 _heap_check();
750#endif
751 xfree(ppDItem, pszSrcFile, __LINE__);
752 ppDItem = NULL; // Remember gone
753 DosPostEventSem(CompactSem);
754
755 if (!ulNumIcon)
756 ulNumIcon = ulNumfiles;
757
758 WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
759 hDrop = DrgDrag(hwnd,
760 pDInfo,
761 paDImgIcons,
762 ulNumIcon,
763 VK_ENDDRAG, // Drag end button
764 (PVOID) NULL);
765 if (hDrop == NULLHANDLE) {
766 dcd->ulItemsToUnHilite = 0;
767 FreeDragInfoData(hwnd, pDInfo);
768 }
769 xfree(paDImgIcons, pszSrcFile, __LINE__);
770 paDImgIcons = NULL; // Remember gone
771 WinSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE);
772 DosPostEventSem(CompactSem);
773 }
774 }
775 xfree(ppDItem, pszSrcFile, __LINE__);
776 xfree(paDImgIcons, pszSrcFile, __LINE__);
777 return hDrop;
778}
779
780#ifdef NEVER // fixme to be enabled someday?
781
782BOOL PickUp(HWND hwndCnr, HWND hwndObj, PCNRDRAGINIT pcd)
783{
784
785 PCNRITEM pci;
786 BOOL loop = TRUE;
787 PDRAGINFO pdinfoOld = NULL, pdinfoCurrent = NULL;
788 ULONG cditem = 0;
789 DRAGITEM ditem;
790 DRAGIMAGE dimgFakeIcon;
791 CHAR szDir[CCHMAXPATH], szFile[CCHMAXPATH], *p;
792
793 pci = (PCNRITEM) pcd->pRecord;
794 if (pci && (INT) pci != -1) {
795 if (pci->rc.flRecordAttr & CRA_SELECTED) {
796 loop = TRUE;
797 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
798 MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_SELECTED));
799 }
800 while (pci && (INT) pci != -1 && *pci->pszFileName) {
801 if (pdinfoOld || DrgQueryDragStatus() & DGS_LAZYDRAGINPROGRESS) {
802 if (!pdinfoOld)
803 pdinfoOld = DrgQueryDraginfoPtr(NULL);
804 if (pdinfoOld) {
805 cditem = pdinfoOld->cditem + 1;
806 pdinfoCurrent = DrgReallocDraginfo(pdinfoOld, cditem);
807 pdinfoOld = pdinfoCurrent;
808 }
809 }
810 else
811 pdinfoCurrent = pdinfoOld = DrgAllocDraginfo(1);
812 if (pdinfoCurrent) {
813 strcpy(szDir, pci->pszFileName);
814 ForwardslashToBackslash(szDir);
815 p = strrchr(szDir, '\\');
816 if (p) {
817 *p = 0;
818 p++;
819 strcpy(szFile, p);
820 strcat(szDir, PCSZ_BACKSLASH);
821 }
822 else {
823 strcpy(szFile, pci->pszFileName);
824 *szDir = 0;
825 }
826 ditem.ulItemID = (ULONG) pci;
827 ditem.hwndItem = (hwndObj) ? hwndObj : hwndCnr;
828 ditem.hstrType = DrgAddStrHandle(DRT_UNKNOWN);
829 ditem.hstrRMF = DrgAddStrHandle(DRMDRFLIST);
830 ditem.hstrContainerName = DrgAddStrHandle(szDir);
831 ditem.hstrSourceName = DrgAddStrHandle(szFile);
832 // fixme to check better if code ever enabled
833 if (!ditem.hstrSourceName) {
834 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
835 "DrgAddStrHandle");
836 }
837 ditem.hstrTargetName = DrgAddStrHandle(szFile);
838 ditem.fsControl = 0;
839 if (IsRoot(pci->pszFileName) || (pci->attrFile & FILE_DIRECTORY) != 0)
840 ditem.fsControl |= DC_CONTAINER;
841 if (IsFullName(pci->pszFileName) &&
842 (driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_REMOVABLE))
843 ditem.fsControl |= DC_REMOVEABLEMEDIA;
844 ditem.fsSupportedOps = DO_COPYABLE | DO_LINKABLE;
845 if (IsFullName(pci->pszFileName) &&
846 !(driveflags[toupper(*pci->pszFileName) - 'A'] &
847 DRIVE_NOTWRITEABLE))
848 ditem.fsSupportedOps |= DO_MOVEABLE;
849 if (IsRoot(pci->pszFileName))
850 ditem.fsSupportedOps = DO_LINKABLE;
851 memset(&dimgFakeIcon, 0, sizeof(DRAGIMAGE));
852 dimgFakeIcon.hImage = pci->rc.hptrIcon;
853 dimgFakeIcon.cb = sizeof(DRAGIMAGE);
854 dimgFakeIcon.cptl = 0;
855 dimgFakeIcon.fl = DRG_ICON;
856 dimgFakeIcon.sizlStretch.cx = 32;
857 dimgFakeIcon.sizlStretch.cy = 32;
858 dimgFakeIcon.cxOffset = -16;
859 dimgFakeIcon.cyOffset = 0;
860 if (IsFullName(pci->pszFileName) &&
861 (driveflags[toupper(*pci->pszFileName) - 'A'] &
862 DRIVE_NOTWRITEABLE))
863 pdinfoCurrent->usOperation = DO_COPY;
864 else
865 pdinfoCurrent->usOperation = DO_DEFAULT;
866 if (IsRoot(pci->pszFileName))
867 pdinfoCurrent->usOperation = DO_LINK;
868 pdinfoCurrent->hwndSource = (hwndObj) ? hwndObj : hwndCnr;
869 DrgSetDragitem(pdinfoCurrent, &ditem, sizeof(DRAGITEM), cditem);
870 }
871 if (!loop)
872 break;
873 pci = WinSendMsg(hwndCnr, CM_QUERYRECORDEMPHASIS,
874 MPFROMP(pci), MPFROMSHORT(CRA_SELECTED));
875 } // while
876 if (pdinfoCurrent)
877 return DrgLazyDrag(hwndCnr, pdinfoCurrent, &dimgFakeIcon, 1, NULL);
878 }
879 return FALSE;
880}
881
882#endif // NEVER
883
884#pragma alloc_text(DRAGLIST,DragOne,DoFileDrag,DragList,PickUp,FreeDragInfoData)
Note: See TracBrowser for help on using the repository browser.