source: trunk/dll/droplist.c@ 1387

Last change on this file since 1387 was 1347, checked in by Gregg Young, 17 years ago

More code cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.6 KB
Line 
1
2/***********************************************************************
3
4 $Id: droplist.c 1347 2008-12-20 04:22:16Z gyoung $
5
6 Drop support
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2003, 2008 Steven H.Levine
10
11 22 Nov 02 SHL Baseline
12 08 Feb 03 SHL DropHelp: calc EA size consistently
13 21 Jul 06 SHL Drop dup code
14 22 Jul 06 SHL Check more run time errors
15 06 Apr 07 GKY Work around PM DragInfo and DrgFreeDISH limits
16 06 Apr 07 GKY Add some error checking in drag/drop
17 19 Apr 07 SHL Use FreeDragInfoData
18 19 Apr 07 SHL Add more drag/drop error checking
19 21 Apr 07 SHL Add debug code to track down reason for PMERR_SOURCE_SAME_AS_TARGET
20 10 Jun 07 GKY Add CheckPmDrgLimit including IsFm2Window as part of work around PM drag limit
21 02 Aug 07 SHL Lock in DoFileDrop sanity checks
22 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
23
24***********************************************************************/
25
26#include <string.h>
27
28#define INCL_DOS
29#define INCL_WIN
30#define INCL_LONGLONG
31
32#include "fm3dll.h"
33#include "avl.h" // Data declaration(s)
34#include "init.h" // Data declaration(s)
35#include "fm3str.h"
36#include "errutil.h" // Dos_Error...
37#include "strutil.h" // GetPString
38#include "droplist.h"
39#include "draglist.h" // FreeDragInfoData
40#include "misc.h" // IsFm2Window
41#include "wrappers.h" // xrealloc
42
43#include "fortify.h"
44
45static PSZ pszSrcFile = __FILE__;
46
47static ULONG GetDropCount(HWND hwnd, MPARAM mp1);
48static BOOL TwoDrgNames(PDRAGITEM pDItem, CHAR * buffer1, ULONG buflen1,
49 char *buffer2, ULONG buflen2);
50
51BOOL CheckPmDrgLimit(PDRAGINFO pDInfo)
52{
53 /*
54 * Checks for FM2 source window then checks window words
55 * for ulItemsToUnHilite and if it is not zero displays a
56 * message to the users that not all items are being dragged
57 * returns TRUE on success
58 */
59 if (!DrgAccessDraginfo(pDInfo)) {
60 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
61 "DrgAccessDraginfo");
62 return FALSE;
63 }
64 else if (IsFm2Window(pDInfo->hwndSource, FALSE)) {
65 DIRCNRDATA *dcdsrc = INSTDATA(pDInfo->hwndSource);
66 if (dcdsrc->ulItemsToUnHilite) {
67 saymsg(MB_OK | MB_INFORMATION,
68 HWND_DESKTOP,
69 GetPString(IDS_ERRORTEXT),
70 GetPString(IDS_EXCEEDPMDRGLMT));
71 }
72 DrgFreeDraginfo(pDInfo);
73 }
74 return TRUE;
75}
76
77BOOL TwoDrgNames(PDRAGITEM pDItem, CHAR * buffer1, ULONG buflen1,
78 char *buffer2, ULONG buflen2)
79{
80 /*
81 * Gets archive name from directory field, file name from file field
82 * Returns FALSE on error, TRUE on success.
83 */
84
85 register ULONG len;
86 BOOL ret = FALSE;
87
88 if (pDItem && buffer2 && buflen2) { /* else error calling function */
89 if (buffer1 && buflen1) /* zero buffers */
90 *buffer1 = 0;
91 *buffer2 = 0;
92
93 if (buffer1 && buflen1) {
94 len = DrgQueryStrName(pDItem->hstrContainerName, buflen1, buffer1);
95 buffer1[len] = 0;
96 if (len) { /* be sure we get full pathname of arc file */
97
98 char szTemp[CCHMAXPATH + 2];
99
100 if (!DosQueryPathInfo(buffer1,
101 FIL_QUERYFULLNAME, szTemp, sizeof(szTemp))) {
102 strncpy(buffer1, szTemp, buflen1);
103 buffer1[buflen1 - 1] = 0;
104 }
105 }
106 { /* be sure that file/directory is accessible */
107 FILESTATUS3 fsa3;
108
109 DosError(FERR_DISABLEHARDERR);
110 if (DosQueryPathInfo(buffer1,
111 FIL_STANDARD,
112 &fsa3,
113 sizeof(fsa3)) ||
114 fsa3.attrFile & FILE_DIRECTORY) {
115 *buffer1 = 0;
116 return ret;
117 }
118 }
119 }
120
121 len = DrgQueryStrName(pDItem->hstrSourceName, buflen2, buffer2);
122 buffer2[len] = 0;
123 if (len)
124 ret = TRUE;
125 }
126 return ret;
127}
128
129BOOL FullDrgName(PDRAGITEM pDItem, CHAR * buffer, ULONG buflen)
130{
131 /*
132 * Gets full name of file from a dragged item.
133 * Returns FALSE on error, TRUE on success.
134 */
135
136 ULONG len, blen;
137 BOOL ret = FALSE;
138 APIRET rc;
139 FILESTATUS3 fsa3;
140
141 if (pDItem && buffer && buflen) { /* else error calling function */
142 *buffer = 0; /* zero buffer */
143
144 blen = DrgQueryStrName(pDItem->hstrContainerName, buflen, buffer);
145 if(!blen)
146 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
147 "DrgQueryStrName");
148 else {
149 if (*(buffer + (blen - 1)) != '\\') {
150 *(buffer + blen) = '\\';
151 blen++;
152 }
153 }
154 buffer[blen] = 0;
155 len = DrgQueryStrName(pDItem->hstrSourceName,
156 buflen - blen, buffer + blen);
157 if(!len) {
158 // DbgMsg(pszSrcFile, __LINE__, "0x%x %d %d", pDItem->hstrSourceName,
159 // buflen - blen, buffer + blen);
160 // Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
161 // "DrgQueryStrName");
162 }
163 buffer[blen + len] = 0;
164 { /* be sure we get full pathname of file/directory */
165 char szTemp[CCHMAXPATH + 2];
166 rc = DosQueryPathInfo(buffer,
167 FIL_QUERYFULLNAME, szTemp, sizeof(szTemp));
168 if (!rc) {
169 strncpy(buffer, szTemp, buflen);
170 buffer[buflen - 1] = 0;
171 }
172 else
173 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
174 "DosQueryPathInfo");
175 }
176
177 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fsa3, sizeof(fsa3));
178 if (!rc)
179 ret = TRUE;
180 else {
181 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
182 "DosQueryPathInfo");
183 *buffer = 0;
184 }
185 }
186 return ret;
187}
188
189BOOL GetOneDrop(HWND hwnd, MPARAM mp1, MPARAM mp2, char *buffer, ULONG buflen)
190{
191 PDRAGITEM pDItem; /* DRAGITEM struct ptr */
192 PDRAGINFO pDInfo; /* DRAGINFO struct ptr */
193 ULONG numitems;
194 register ULONG curitem;
195 BOOL ret = FALSE;
196
197 if (buffer && buflen)
198 *buffer = 0; /* zero buffer field */
199
200 pDInfo = (PDRAGINFO) mp1; /* Get DRAGINFO pointer */
201 if (pDInfo) {
202 if (!DrgAccessDraginfo(pDInfo)) {
203 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
204 "DrgAccessDraginfo");
205 }
206 else {
207 numitems = DrgQueryDragitemCount(pDInfo);
208 pDItem = DrgQueryDragitemPtr(pDInfo,0);
209 if (buflen && buffer) {
210 if (DrgVerifyRMF(pDItem, /* Check valid rendering */
211 DRM_OS2FILE, /* mechanisms and data */
212 NULL) && !(pDItem->fsControl & DC_PREPARE))
213 ret = FullDrgName(pDItem, buffer, buflen);
214 }
215 // Return targetfail to source for all items - fixme to know why
216 for (curitem = 0; curitem < numitems; curitem++) {
217 pDItem = DrgQueryDragitemPtr(pDInfo,curitem);
218 DrgSendTransferMsg(pDInfo->hwndSource, DM_ENDCONVERSATION,
219 MPFROMLONG(pDItem->ulItemID),
220 MPFROMLONG(DMFL_TARGETFAIL));
221 }
222 FreeDragInfoData(hwnd, pDInfo);
223 }
224 }
225
226 return ret;
227}
228
229BOOL AcceptOneDrop(HWND hwnd, MPARAM mp1, MPARAM mp2)
230{
231 PDRAGITEM pDItem; /* Pointer to DRAGITEM */
232 PDRAGINFO pDInfo; /* Pointer to DRAGINFO */
233 BOOL ret = FALSE;
234
235 pDInfo = (PDRAGINFO) mp1; /* Get DRAGINFO pointer */
236 if (pDInfo) {
237 if (!DrgAccessDraginfo(pDInfo)) {
238 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
239 "DrgAccessDraginfo");
240 }
241 else {
242 pDItem = DrgQueryDragitemPtr(pDInfo, 0);
243
244 /* Check valid rendering mechanisms and data formats */
245 if (DrgVerifyRMF(pDItem, DRM_OS2FILE, NULL))
246 ret = TRUE;
247
248 DrgFreeDraginfo(pDInfo);
249 }
250 }
251 return ret;
252}
253
254static ULONG GetDropCount(HWND hwnd, MPARAM mp1)
255{
256 PDRAGINFO pDInfo;
257 ULONG numitems;
258
259 pDInfo = mp1;
260 if (pDInfo) {
261 if (!DrgAccessDraginfo(pDInfo)) {
262 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
263 "DrgAccessDraginfo");
264 numitems = 0; // Oh well
265 }
266 else {
267 numitems = DrgQueryDragitemCount(pDInfo);
268 FreeDragInfoData(hwnd, pDInfo);
269 }
270 }
271 return numitems;
272}
273
274void DropHelp(MPARAM mp1, MPARAM mp2, HWND hwnd, char *text)
275{
276 ULONG numitems;
277
278 numitems = GetDropCount(hwnd, mp1);
279 saymsg(MB_ENTER | MB_ICONASTERISK,
280 hwnd, GetPString(IDS_FM2DROPHELPTEXT), text, numitems, numitems);
281}
282
283LISTINFO *DoFileDrop(HWND hwndCnr, CHAR * directory, BOOL arcfilesok,
284 MPARAM mp1, MPARAM mp2)
285{
286 /* builds a list from the dropped files */
287
288 BOOL isArc = FALSE, arctest = FALSE;
289 PDRAGITEM pDItem;
290 PDRAGINFO pDInfo;
291 PCNRITEM pci;
292 CHAR szFrom[CCHMAXPATH + 1], szArc[CCHMAXPATH + 1];
293 CHAR **files = NULL;
294 UINT numfiles = 0, numalloc = 0;
295 ULONG curitem, numitems;
296 PULONGLONG pcbFile = NULL;
297 PULONG pulitemID = NULL;
298 LISTINFO *li = NULL;
299 ARC_TYPE *arcinfo = NULL;
300 USHORT Operation;
301
302 UINT numok = 0; // 02 Aug 07 SHL fixme to be gone someday
303 UINT numfail = 0;
304
305 *szArc = 0;
306 pci = (PCNRITEM) ((PCNRDRAGINFO) mp2)->pRecord;
307 pDInfo = ((PCNRDRAGINFO) mp2)->pDragInfo;
308 if (!pDInfo) {
309 Runtime_Error(pszSrcFile, __LINE__, "No drag info");
310 return NULL;
311 }
312 if (!DrgAccessDraginfo(pDInfo)) {
313 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
314 "DrgAccessDraginfo");
315 numitems = 0; // Avoid death
316 }
317 else {
318 numitems = DrgQueryDragitemCount(pDInfo);
319 Operation = pDInfo->usOperation;
320 pDItem = DrgQueryDragitemPtr(pDInfo, 0);
321 if (!pDItem) {
322 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
323 "DrgQueryDragitemPtr");
324 }
325 else {
326 if (Operation == DO_MOVE && !(pDItem->fsSupportedOps & DO_MOVEABLE)) {
327 saymsg(MB_ENTER, HWND_DESKTOP, GetPString(IDS_WARNINGTEXT),
328 GetPString(IDS_FORCINGCOPYTEXT));
329 Operation = DO_COPY;
330 }
331 }
332 }
333
334 for (curitem = 0; curitem < numitems; curitem++) {
335 pDItem = DrgQueryDragitemPtr(pDInfo, curitem);
336 if (!pDItem) {
337 Win_Error(hwndCnr, hwndCnr, pszSrcFile, __LINE__,
338 "DrgQueryDragitemPtr(%u)", curitem);
339 break;
340 }
341
342 /* ambiguous drop request -- see what's allowed */
343 if (Operation == DO_DEFAULT || Operation >= DO_UNKNOWN) {
344 if (pDItem->fsSupportedOps & DO_COPYABLE)
345 Operation = DO_COPY;
346 else if (pDItem->fsSupportedOps & DO_MOVEABLE)
347 Operation = DO_MOVE;
348 else if (pDItem->fsSupportedOps & DO_LINKABLE)
349 Operation = DO_LINK;
350 }
351 else {
352 /* ignore object if selected command not allowed for it */
353 BOOL ok;
354 switch (Operation) {
355 case DO_MOVE:
356 ok = pDItem->fsSupportedOps & DO_MOVEABLE;
357 break;
358 case DO_COPY:
359 ok = pDItem->fsSupportedOps & DO_COPYABLE;
360 break;
361 case DO_LINK:
362 ok = pDItem->fsSupportedOps & DO_LINKABLE;
363 break;
364 default:
365 ok = FALSE;
366 }
367 if (!ok) {
368 // Fail request
369 DrgSendTransferMsg(pDItem->hwndItem,
370 DM_ENDCONVERSATION,
371 MPFROMLONG(pDItem->ulItemID),
372 MPFROMLONG(DMFL_TARGETFAIL));
373 numfail++;
374 continue;
375 }
376 }
377
378 if (DrgVerifyRMF(pDItem,
379 DRM_OS2FILE,
380 NULL) ||
381 (arcfilesok &&
382 ((arctest = DrgVerifyRMF(pDItem,
383 DRM_FM2ARCMEMBER,
384 DRF_FM2ARCHIVE)) != FALSE))) {
385 if (pDItem->fsControl & DC_PREPARE) {
386 DrgSendTransferMsg(pDItem->hwndItem,
387 DM_ENDCONVERSATION,
388 MPFROMLONG(pDItem->ulItemID),
389 MPFROMLONG(DMFL_TARGETFAIL));
390 numfail++;
391 continue;
392 }
393
394 if (arctest || isArc) {
395 if (!isArc) {
396 if (TwoDrgNames(pDItem,
397 szArc,
398 sizeof(szArc),
399 szFrom, sizeof(szFrom)) && *szArc && *szFrom) {
400 isArc = TRUE;
401 arcinfo = find_type(szArc, arcsighead);
402 }
403 if (!arcinfo || !arcinfo->extract || !*arcinfo->extract) {
404 *szArc = *szFrom = 0;
405 isArc = FALSE;
406 }
407 }
408 else
409 TwoDrgNames(pDItem, NULL, 0, szFrom, sizeof(szFrom));
410 }
411 else
412 FullDrgName(pDItem, szFrom, sizeof(szFrom));
413
414 if (!*szFrom) {
415 DrgSendTransferMsg(pDItem->hwndItem,
416 DM_ENDCONVERSATION,
417 MPFROMLONG(pDItem->ulItemID),
418 MPFROMLONG(DMFL_TARGETFAIL));
419 numfail++;
420 continue;
421 }
422
423 if (numfiles + 2 > numalloc) {
424
425 CHAR **test;
426 PULONG pltest;
427 PULONGLONG plltest;
428
429 numalloc += 12;
430 test =
431 xrealloc(files, numalloc * sizeof(CHAR *), pszSrcFile, __LINE__);
432 if (!test)
433 break;
434 files = test;
435 plltest =
436 xrealloc(pcbFile, numalloc * sizeof(ULONGLONG), pszSrcFile, __LINE__);
437 if (!plltest)
438 break;
439 pcbFile = plltest;
440 pltest =
441 xrealloc(pulitemID, numalloc * sizeof(ULONG), pszSrcFile, __LINE__);
442 if (!pltest)
443 break;
444 pulitemID = pltest;
445 }
446 pcbFile[numfiles] = 0;
447 if (!isArc) {
448
449 FILESTATUS4L fsa4;
450
451 if (!DosQueryPathInfo(szFrom, FIL_QUERYEASIZEL, &fsa4, sizeof(fsa4)))
452 pcbFile[numfiles] = fsa4.cbFile + CBLIST_TO_EASIZE(fsa4.cbList);
453 }
454 pulitemID[numfiles] = pDItem->ulItemID;
455 files[numfiles] = xstrdup(szFrom, pszSrcFile, __LINE__);
456 files[numfiles + 1] = NULL;
457 if (!files[numfiles])
458 break;
459 numfiles++;
460 DrgSendTransferMsg(pDItem->hwndItem,
461 DM_ENDCONVERSATION,
462 MPFROMLONG(pDItem->ulItemID),
463 MPFROMLONG(DMFL_TARGETSUCCESSFUL));
464 numok++;
465 }
466 else {
467 DrgSendTransferMsg(pDItem->hwndItem,
468 DM_ENDCONVERSATION,
469 MPFROMLONG(pDItem->ulItemID),
470 MPFROMLONG(DMFL_TARGETFAIL));
471 numfail++;
472 }
473 } // for curitem
474
475 if (files && numfiles && files[0] && pcbFile && pulitemID) {
476# ifdef FORTIFY
477 Fortify_EnterScope();
478# endif
479 li = xmallocz(sizeof(LISTINFO), pszSrcFile, __LINE__);
480 if (li) {
481 li->type = Operation;
482 li->hwnd = hwndCnr;
483 li->list = files;
484 li->cbFile = pcbFile;
485 li->ulitemID = pulitemID;
486 li->hwndS = pDInfo->hwndSource;
487 if (!pci && directory)
488 strcpy(li->targetpath, directory);
489 else if (pci)
490 strcpy(li->targetpath, pci->pszFileName);
491 if (isArc) {
492 strcpy(li->arcname, szArc);
493 li->info = arcinfo;
494 }
495 SortList(li);
496 }
497 else {
498 xfree(pcbFile, pszSrcFile, __LINE__);
499 xfree(pulitemID, pszSrcFile, __LINE__);
500 if (files)
501 FreeList(files);
502 }
503 }
504 else {
505 xfree(pcbFile, pszSrcFile, __LINE__);
506 xfree(pulitemID, pszSrcFile, __LINE__);
507 if (files)
508 FreeList(files);
509 }
510
511 FreeDragInfoData(hwndCnr, pDInfo);
512# ifdef FORTIFY
513 Fortify_LeaveScope();
514# endif
515
516 // 02 Aug 07 SHL fixme to be gone someday or use Runtime_Error if really an error
517 if (numfail || numok == 0)
518 DbgMsg(pszSrcFile, __LINE__, "calling FreeDragInfoData with %u ok, %u failed", numok, numfail);
519
520 return li;
521}
522
523#pragma alloc_text(DROPLIST,DoFileDrop,FullDrgName,TwoDrgNames,GetOneDrop,CheckPmDrgLimit)
Note: See TracBrowser for help on using the repository browser.