source: trunk/dll/droplist.c@ 1178

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

Ticket 187: Draft 1: Functions only

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