source: trunk/dll/droplist.c@ 1194

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

Ticket 187: Draft 2: Move remaining function declarations

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