source: trunk/dll/draglist.c@ 1505

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

Changes to get FM2 to compile with the latest watcom 1.9 beta (mostly type casts of CHAR CONSTANT * to CHAR *). Changes to get the environment settings working everywhere again (broken by the change that moved commands to the INI); Added an environment size variable (set to 2048 which was the largest I found hard coded). Still need to find everywhere the environment size is set and use this variable.

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