source: trunk/dll/droplist.c@ 1330

Last change on this file since 1330 was 1207, checked in by John Small, 17 years ago

Ticket 187: Move data declarations/definitions out of fm3dll.h

  • 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 1207 2008-09-13 06:49:41Z jbs $
5
6 Drop support
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2003, 2007 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 // FreeDragInfoData(hwnd, pDInfo); // 20 Apr 07 SHL
249 DrgFreeDraginfo(pDInfo);
250 }
251 }
252 return ret;
253}
254
255static ULONG GetDropCount(HWND hwnd, MPARAM mp1)
256{
257 PDRAGINFO pDInfo;
258 ULONG numitems;
259
260 pDInfo = mp1;
261 if (pDInfo) {
262 if (!DrgAccessDraginfo(pDInfo)) {
263 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
264 "DrgAccessDraginfo");
265 numitems = 0; // Oh well
266 }
267 else {
268 numitems = DrgQueryDragitemCount(pDInfo);
269 FreeDragInfoData(hwnd, pDInfo);
270 }
271 }
272 return numitems;
273}
274
275void DropHelp(MPARAM mp1, MPARAM mp2, HWND hwnd, char *text)
276{
277 ULONG numitems;
278
279 numitems = GetDropCount(hwnd, mp1);
280 saymsg(MB_ENTER | MB_ICONASTERISK,
281 hwnd, GetPString(IDS_FM2DROPHELPTEXT), text, numitems, numitems);
282}
283
284LISTINFO *DoFileDrop(HWND hwndCnr, CHAR * directory, BOOL arcfilesok,
285 MPARAM mp1, MPARAM mp2)
286{
287 /* builds a list from the dropped files */
288
289 BOOL isArc = FALSE, arctest = FALSE;
290 PDRAGITEM pDItem;
291 PDRAGINFO pDInfo;
292 PCNRITEM pci;
293 CHAR szFrom[CCHMAXPATH + 1], szArc[CCHMAXPATH + 1];
294 CHAR **files = NULL;
295 UINT numfiles = 0, numalloc = 0;
296 ULONG curitem, numitems;
297 PULONGLONG pcbFile = NULL;
298 PULONG pulitemID = NULL;
299 LISTINFO *li = NULL;
300 ARC_TYPE *arcinfo = NULL;
301 USHORT Operation;
302
303 UINT numok = 0; // 02 Aug 07 SHL fixme to be gone someday
304 UINT numfail = 0;
305
306 *szArc = 0;
307 pci = (PCNRITEM) ((PCNRDRAGINFO) mp2)->pRecord;
308 pDInfo = ((PCNRDRAGINFO) mp2)->pDragInfo;
309 if (!pDInfo) {
310 Runtime_Error(pszSrcFile, __LINE__, "No drag info");
311 return NULL;
312 }
313 if (!DrgAccessDraginfo(pDInfo)) {
314 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
315 "DrgAccessDraginfo");
316 numitems = 0; // Avoid death
317 }
318 else {
319 numitems = DrgQueryDragitemCount(pDInfo);
320 Operation = pDInfo->usOperation;
321 pDItem = DrgQueryDragitemPtr(pDInfo, 0);
322 if (!pDItem) {
323 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
324 "DrgQueryDragitemPtr");
325 }
326 else {
327 if (Operation == DO_MOVE && !(pDItem->fsSupportedOps & DO_MOVEABLE)) {
328 saymsg(MB_ENTER, HWND_DESKTOP, GetPString(IDS_WARNINGTEXT),
329 GetPString(IDS_FORCINGCOPYTEXT));
330 Operation = DO_COPY;
331 }
332 }
333 }
334
335 for (curitem = 0; curitem < numitems; curitem++) {
336 pDItem = DrgQueryDragitemPtr(pDInfo, curitem);
337 if (!pDItem) {
338 Win_Error(hwndCnr, hwndCnr, pszSrcFile, __LINE__,
339 "DrgQueryDragitemPtr(%u)", curitem);
340 break;
341 }
342
343 /* ambiguous drop request -- see what's allowed */
344 if (Operation == DO_DEFAULT || Operation >= DO_UNKNOWN) {
345 if (pDItem->fsSupportedOps & DO_COPYABLE)
346 Operation = DO_COPY;
347 else if (pDItem->fsSupportedOps & DO_MOVEABLE)
348 Operation = DO_MOVE;
349 else if (pDItem->fsSupportedOps & DO_LINKABLE)
350 Operation = DO_LINK;
351 }
352 else {
353 /* ignore object if selected command not allowed for it */
354 BOOL ok;
355 switch (Operation) {
356 case DO_MOVE:
357 ok = pDItem->fsSupportedOps & DO_MOVEABLE;
358 break;
359 case DO_COPY:
360 ok = pDItem->fsSupportedOps & DO_COPYABLE;
361 break;
362 case DO_LINK:
363 ok = pDItem->fsSupportedOps & DO_LINKABLE;
364 break;
365 default:
366 ok = FALSE;
367 }
368 if (!ok) {
369 // Fail request
370 DrgSendTransferMsg(pDItem->hwndItem,
371 DM_ENDCONVERSATION,
372 MPFROMLONG(pDItem->ulItemID),
373 MPFROMLONG(DMFL_TARGETFAIL));
374 numfail++;
375 continue;
376 }
377 }
378
379 if (DrgVerifyRMF(pDItem,
380 DRM_OS2FILE,
381 NULL) ||
382 (arcfilesok &&
383 ((arctest = DrgVerifyRMF(pDItem,
384 DRM_FM2ARCMEMBER,
385 DRF_FM2ARCHIVE)) != FALSE))) {
386 if (pDItem->fsControl & DC_PREPARE) {
387 DrgSendTransferMsg(pDItem->hwndItem,
388 DM_ENDCONVERSATION,
389 MPFROMLONG(pDItem->ulItemID),
390 MPFROMLONG(DMFL_TARGETFAIL));
391 numfail++;
392 continue;
393 }
394
395 if (arctest || isArc) {
396 if (!isArc) {
397 if (TwoDrgNames(pDItem,
398 szArc,
399 sizeof(szArc),
400 szFrom, sizeof(szFrom)) && *szArc && *szFrom) {
401 isArc = TRUE;
402 arcinfo = find_type(szArc, arcsighead);
403 }
404 if (!arcinfo || !arcinfo->extract || !*arcinfo->extract) {
405 *szArc = *szFrom = 0;
406 isArc = FALSE;
407 }
408 }
409 else
410 TwoDrgNames(pDItem, NULL, 0, szFrom, sizeof(szFrom));
411 }
412 else
413 FullDrgName(pDItem, szFrom, sizeof(szFrom));
414
415 if (!*szFrom) {
416 DrgSendTransferMsg(pDItem->hwndItem,
417 DM_ENDCONVERSATION,
418 MPFROMLONG(pDItem->ulItemID),
419 MPFROMLONG(DMFL_TARGETFAIL));
420 numfail++;
421 continue;
422 }
423
424 if (numfiles + 2 > numalloc) {
425
426 CHAR **test;
427 PULONG pltest;
428 PULONGLONG plltest;
429
430 numalloc += 12;
431 test =
432 xrealloc(files, numalloc * sizeof(CHAR *), pszSrcFile, __LINE__);
433 if (!test)
434 break;
435 files = test;
436 plltest =
437 xrealloc(pcbFile, numalloc * sizeof(ULONGLONG), pszSrcFile, __LINE__);
438 if (!plltest)
439 break;
440 pcbFile = plltest;
441 pltest =
442 xrealloc(pulitemID, numalloc * sizeof(ULONG), pszSrcFile, __LINE__);
443 if (!pltest)
444 break;
445 pulitemID = pltest;
446 }
447 pcbFile[numfiles] = 0;
448 if (!isArc) {
449
450 FILESTATUS4L fsa4;
451
452 if (!DosQueryPathInfo(szFrom, FIL_QUERYEASIZEL, &fsa4, sizeof(fsa4)))
453 pcbFile[numfiles] = fsa4.cbFile + CBLIST_TO_EASIZE(fsa4.cbList);
454 }
455 pulitemID[numfiles] = pDItem->ulItemID;
456 files[numfiles] = xstrdup(szFrom, pszSrcFile, __LINE__);
457 files[numfiles + 1] = NULL;
458 if (!files[numfiles])
459 break;
460 numfiles++;
461 DrgSendTransferMsg(pDItem->hwndItem,
462 DM_ENDCONVERSATION,
463 MPFROMLONG(pDItem->ulItemID),
464 MPFROMLONG(DMFL_TARGETSUCCESSFUL));
465 numok++;
466 }
467 else {
468 DrgSendTransferMsg(pDItem->hwndItem,
469 DM_ENDCONVERSATION,
470 MPFROMLONG(pDItem->ulItemID),
471 MPFROMLONG(DMFL_TARGETFAIL));
472 numfail++;
473 }
474 } // for curitem
475
476 if (files && numfiles && files[0] && pcbFile && pulitemID) {
477# ifdef FORTIFY
478 Fortify_EnterScope();
479# endif
480 li = xmallocz(sizeof(LISTINFO), pszSrcFile, __LINE__);
481 if (li) {
482 li->type = Operation;
483 li->hwnd = hwndCnr;
484 li->list = files;
485 li->cbFile = pcbFile;
486 li->ulitemID = pulitemID;
487 li->hwndS = pDInfo->hwndSource;
488 if (!pci && directory)
489 strcpy(li->targetpath, directory);
490 else if (pci)
491 strcpy(li->targetpath, pci->pszFileName);
492 if (isArc) {
493 strcpy(li->arcname, szArc);
494 li->info = arcinfo;
495 }
496 SortList(li);
497 }
498 else {
499 xfree(pcbFile, pszSrcFile, __LINE__);
500 xfree(pulitemID, pszSrcFile, __LINE__);
501 if (files)
502 FreeList(files);
503 }
504 }
505 else {
506 xfree(pcbFile, pszSrcFile, __LINE__);
507 xfree(pulitemID, pszSrcFile, __LINE__);
508 if (files)
509 FreeList(files);
510 }
511
512 FreeDragInfoData(hwndCnr, pDInfo);
513# ifdef FORTIFY
514 Fortify_LeaveScope();
515# endif
516
517 // 02 Aug 07 SHL fixme to be gone someday or use Runtime_Error if really an error
518 if (numfail || numok == 0)
519 DbgMsg(pszSrcFile, __LINE__, "calling FreeDragInfoData with %u ok, %u failed", numok, numfail);
520
521 return li;
522}
523
524#pragma alloc_text(DROPLIST,DoFileDrop,FullDrgName,TwoDrgNames,GetOneDrop,CheckPmDrgLimit)
Note: See TracBrowser for help on using the repository browser.