source: trunk/dll/droplist.c@ 603

Last change on this file since 603 was 603, checked in by Gregg Young, 19 years ago

Work around for PM drag/drop limit; more drag/drop error checking

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.6 KB
Line 
1
2/***********************************************************************
3
4 $Id: droplist.c 603 2007-04-06 21:57:45Z gyoung $
5
6 Drop support
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2003, 2006 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
18***********************************************************************/
19
20#define INCL_DOS
21#define INCL_WIN
22#include <os2.h>
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <ctype.h>
28
29#include "fm3dll.h"
30#include "fm3str.h"
31
32static PSZ pszSrcFile = __FILE__;
33
34#pragma alloc_text(DROPLIST,DoFileDrop,FullDrgName,TwoDrgNames,GetOneDrop)
35
36BOOL TwoDrgNames(PDRAGITEM pDItem, CHAR * buffer1, ULONG buflen1,
37 char *buffer2, ULONG buflen2)
38{
39 /*
40 * Gets archive name from directory field, file name from file field
41 * Returns FALSE on error, TRUE on success.
42 */
43
44 register ULONG len;
45 BOOL ret = FALSE;
46
47 if (pDItem && buffer2 && buflen2) { /* else error calling function */
48 if (buffer1 && buflen1) /* zero buffers */
49 *buffer1 = 0;
50 *buffer2 = 0;
51
52 if (buffer1 && buflen1) {
53 len = DrgQueryStrName(pDItem->hstrContainerName, buflen1, buffer1);
54 buffer1[len] = 0;
55 if (len) { /* be sure we get full pathname of arc file */
56
57 char szTemp[CCHMAXPATH + 2];
58
59 if (!DosQueryPathInfo(buffer1,
60 FIL_QUERYFULLNAME, szTemp, sizeof(szTemp))) {
61 strncpy(buffer1, szTemp, buflen1);
62 buffer1[buflen1 - 1] = 0;
63 }
64 }
65 { /* be sure that file/directory is accessible */
66 FILESTATUS3 fsa3;
67
68 DosError(FERR_DISABLEHARDERR);
69 if (DosQueryPathInfo(buffer1,
70 FIL_STANDARD,
71 &fsa3,
72 sizeof(fsa3)) ||
73 (fsa3.attrFile & FILE_DIRECTORY) != 0) {
74 *buffer1 = 0;
75 return ret;
76 }
77 }
78 }
79
80 len = DrgQueryStrName(pDItem->hstrSourceName, buflen2, buffer2);
81 buffer2[len] = 0;
82 if (len)
83 ret = TRUE;
84 }
85 return ret;
86}
87
88BOOL FullDrgName(PDRAGITEM pDItem, CHAR * buffer, ULONG buflen)
89{
90 /*
91 * Gets full name of file from a dragged item.
92 * Returns FALSE on error, TRUE on success.
93 */
94
95 register ULONG len, blen;
96 BOOL ret = FALSE;
97 APIRET rc;
98
99 if (pDItem && buffer && buflen) { /* else error calling function */
100 *buffer = 0; /* zero buffer */
101
102 blen = DrgQueryStrName(pDItem->hstrContainerName, buflen, buffer);
103 if(!blen)
104 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
105 "DrgQueryStrName");
106 else {
107 if (*(buffer + (blen - 1)) != '\\') {
108 *(buffer + blen) = '\\';
109 blen++;
110 }
111 }
112 buffer[blen] = 0;
113 len = DrgQueryStrName(pDItem->hstrSourceName,
114 buflen - blen, buffer + blen);
115 if(!len)
116 // printf("%s %d\n %s\n %d %X\n", pszSrcFile, __LINE__, pDItem->hstrSourceName,
117 // buflen - blen, buffer + blen); fflush(stdout);
118 // Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
119 // "DrgQueryStrName");
120 buffer[blen + len] = 0;
121 { /* be sure we get full pathname of file/directory */
122 char szTemp[CCHMAXPATH + 2];
123 rc = DosQueryPathInfo(buffer,
124 FIL_QUERYFULLNAME, szTemp, sizeof(szTemp));
125 if (!rc) {
126 strncpy(buffer, szTemp, buflen);
127 buffer[buflen - 1] = 0;
128 }
129 else
130 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
131 "DosQueryPathInfo");
132 }
133 { /* be sure that file/directory is accessible */
134 FILESTATUS3 fsa3;
135
136 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fsa3, sizeof(fsa3));
137 if (!rc)
138 ret = TRUE;
139 else {
140 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
141 "DosQueryPathInfo");
142 *buffer = 0;
143 }
144 }
145 }
146 return ret;
147}
148
149BOOL GetOneDrop(MPARAM mp1, MPARAM mp2, char *buffer, ULONG buflen)
150{
151 PDRAGITEM pDItem; /* DRAGITEM struct ptr */
152 PDRAGINFO pDInfo; /* DRAGINFO struct ptr */
153 ULONG numitems;
154 register ULONG x;
155 BOOL ret = FALSE;
156 APIRET rc;
157
158 if (buffer && buflen)
159 *buffer = 0; /* zero buffer field */
160
161 pDInfo = (PDRAGINFO) mp1; /* Get DRAGINFO pointer */
162 if (pDInfo) {
163 DrgAccessDraginfo(pDInfo); /* Access DRAGINFO */
164 numitems = DrgQueryDragitemCount(pDInfo);
165 pDItem = DrgQueryDragitemPtr(pDInfo, /* Access DRAGITEM */
166 0); /* Index to DRAGITEM */
167 if (buflen && buffer) {
168 if (DrgVerifyRMF(pDItem, /* Check valid rendering */
169 DRM_OS2FILE, /* mechanisms and data */
170 NULL) && !(pDItem->fsControl & DC_PREPARE))
171 ret = FullDrgName(pDItem, buffer, buflen);
172 }
173 /* note: targetfail is returned to source for all items */
174 for (x = 0; x < numitems; x++) {
175 pDItem = DrgQueryDragitemPtr(pDInfo, /* Access DRAGITEM */
176 x); /* Index to DRAGITEM */
177 DrgSendTransferMsg(pDInfo->hwndSource, DM_ENDCONVERSATION,
178 MPFROMLONG(pDItem->ulItemID),
179 MPFROMLONG(DMFL_TARGETFAIL));
180 }
181 rc = DeleteDragitemStrHandles(pDInfo); //
182 if(!rc)
183 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
184 "DeleteDragitemStrHandles");
185 DrgDeleteDraginfoStrHandles (pDInfo);
186 rc = DrgFreeDraginfo(pDInfo); /* Free DRAGINFO */
187 if(!rc)
188 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
189 "DrgFreeDraginfo");
190 }
191
192 return ret;
193}
194
195BOOL AcceptOneDrop(MPARAM mp1, MPARAM mp2)
196{
197 PDRAGITEM pDItem; /* Pointer to DRAGITEM */
198 PDRAGINFO pDInfo; /* Pointer to DRAGINFO */
199 BOOL ret = FALSE;
200 APIRET rc;
201
202 pDInfo = (PDRAGINFO) mp1; /* Get DRAGINFO pointer */
203 if (pDInfo) {
204 DrgAccessDraginfo(pDInfo); /* Access DRAGINFO */
205 pDItem = DrgQueryDragitemPtr(pDInfo, /* Access DRAGITEM */
206 0); /* Index to DRAGITEM */
207 if (DrgVerifyRMF(pDItem, /* Check valid rendering */
208 DRM_OS2FILE, /* mechanisms and data */
209 NULL)) /* formats */
210 ret = TRUE;
211 rc = DeleteDragitemStrHandles(pDInfo); //
212 if(!rc)
213 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
214 "DeleteDragitemStrHandles");
215 DrgDeleteDraginfoStrHandles(pDInfo);
216 rc = DrgFreeDraginfo(pDInfo);
217 if(!rc)
218 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
219 "DrgFreeDraginfo");
220 }
221 return ret;
222}
223
224ULONG FreeDrop(MPARAM mp1, MPARAM mp2)
225{
226 PDRAGINFO pDInfo;
227 ULONG numitems;
228 APIRET rc;
229
230 pDInfo = mp1;
231 if (pDInfo) {
232 DrgAccessDraginfo(pDInfo);
233 numitems = DrgQueryDragitemCount(pDInfo);
234 rc = DeleteDragitemStrHandles(pDInfo); //
235 if(!rc)
236 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
237 "DeleteDragitemStrHandles");
238 DrgDeleteDraginfoStrHandles(pDInfo);
239 rc = DrgFreeDraginfo(pDInfo);
240 if(!rc)
241 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
242 "DrgFreeDraginfo");
243 }
244 return numitems;
245}
246
247void DropHelp(MPARAM mp1, MPARAM mp2, HWND hwnd, char *text)
248{
249 ULONG numitems;
250
251 numitems = FreeDrop(mp1, mp2);
252 saymsg(MB_ENTER | MB_ICONASTERISK,
253 hwnd, GetPString(IDS_FM2DROPHELPTEXT), text, numitems, numitems);
254}
255
256LISTINFO *DoFileDrop(HWND hwndCnr, CHAR * directory, BOOL arcfilesok,
257 MPARAM mp1, MPARAM mp2)
258{
259
260 /* builds a list from the dropped files */
261
262 BOOL isArc = FALSE, arctest = FALSE;
263 PDRAGITEM pDItem;
264 PDRAGINFO pDInfo;
265 PCNRITEM pci;
266 CHAR szFrom[CCHMAXPATH + 1], szArc[CCHMAXPATH + 1];
267 register CHAR **files = NULL;
268 INT numfiles = 0, numalloc = 0;
269 register ULONG curitem = 0L, numitems, *cbFile = NULL, *ulitemID = NULL;
270 LISTINFO *li = NULL;
271 ARC_TYPE *arcinfo = NULL;
272 USHORT Operation;
273 APIRET rc;
274
275 *szArc = 0;
276 pci = (PCNRITEM) ((PCNRDRAGINFO) mp2)->pRecord;
277 pDInfo = ((PCNRDRAGINFO) mp2)->pDragInfo;
278 if (!pDInfo)
279 return NULL;
280 rc = DrgAccessDraginfo(pDInfo);
281 if(!rc)
282 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
283 "DrgAccessDraginfo");
284 Operation = pDInfo->usOperation;
285 pDItem = DrgQueryDragitemPtr(pDInfo, 0L);
286 if(!pDItem)
287 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
288 "DrgQueryDragitemPtr");
289 if (Operation == DO_MOVE && !(pDItem->fsSupportedOps & DO_MOVEABLE)) {
290 saymsg(MB_ENTER, HWND_DESKTOP, GetPString(IDS_WARNINGTEXT),
291 GetPString(IDS_FORCINGCOPYTEXT));
292 Operation = DO_COPY;
293 }
294 numitems = DrgQueryDragitemCount(pDInfo);
295 while (curitem < numitems) {
296 pDItem = DrgQueryDragitemPtr(pDInfo, curitem);
297 if (!pDItem)
298 break;
299
300 /* ambiguous drop request -- see what's allowed */
301 if (Operation == DO_DEFAULT || Operation >= DO_UNKNOWN) {
302 if (pDItem->fsSupportedOps & DO_COPYABLE)
303 Operation = DO_COPY;
304 else if (pDItem->fsSupportedOps & DO_MOVEABLE)
305 Operation = DO_MOVE;
306 else if (pDItem->fsSupportedOps & DO_LINKABLE)
307 Operation = DO_LINK;
308 }
309 else {
310 /* ignore object if selected command not allowed for it */
311 switch (Operation) {
312 case DO_MOVE:
313 if (pDItem->fsSupportedOps & DO_MOVEABLE)
314 goto Okay;
315 break;
316 case DO_COPY:
317 if (pDItem->fsSupportedOps & DO_COPYABLE)
318 goto Okay;
319 break;
320 case DO_LINK:
321 if (pDItem->fsSupportedOps & DO_LINKABLE)
322 goto Okay;
323 break;
324 }
325 // Fail request
326 DrgSendTransferMsg(pDItem->hwndItem,
327 DM_ENDCONVERSATION,
328 MPFROMLONG(pDItem->ulItemID),
329 MPFROMLONG(DMFL_TARGETFAIL));
330 curitem++;
331 continue;
332 }
333
334 Okay:
335
336 if (DrgVerifyRMF(pDItem,
337 DRM_OS2FILE,
338 NULL) ||
339 (arcfilesok &&
340 ((arctest = DrgVerifyRMF(pDItem,
341 DRM_FM2ARCMEMBER,
342 DRF_FM2ARCHIVE)) != FALSE))) {
343 if (pDItem->fsControl & DC_PREPARE) {
344 DrgSendTransferMsg(pDItem->hwndItem,
345 DM_ENDCONVERSATION,
346 MPFROMLONG(pDItem->ulItemID),
347 MPFROMLONG(DMFL_TARGETFAIL));
348 curitem++;
349 continue;
350 }
351
352 if (arctest || isArc) {
353 if (!isArc) {
354 if (TwoDrgNames(pDItem,
355 szArc,
356 sizeof(szArc),
357 szFrom, sizeof(szFrom)) && *szArc && *szFrom) {
358 isArc = TRUE;
359 arcinfo = find_type(szArc, arcsighead);
360 }
361 if (!arcinfo || !arcinfo->extract || !*arcinfo->extract) {
362 *szArc = *szFrom = 0;
363 isArc = FALSE;
364 }
365 }
366 else
367 TwoDrgNames(pDItem, NULL, 0, szFrom, sizeof(szFrom));
368 }
369 else
370 FullDrgName(pDItem, szFrom, sizeof(szFrom));
371
372 if (!*szFrom) {
373 DrgSendTransferMsg(pDItem->hwndItem,
374 DM_ENDCONVERSATION,
375 MPFROMLONG(pDItem->ulItemID),
376 MPFROMLONG(DMFL_TARGETFAIL));
377 curitem++;
378 continue;
379 }
380
381 if (numfiles + 2 > numalloc) {
382
383 CHAR **test;
384 ULONG *ltest;
385
386 numalloc += 12;
387 test =
388 xrealloc(files, numalloc * sizeof(CHAR *), pszSrcFile, __LINE__);
389 if (!test)
390 goto AbortDrop;
391 files = test;
392 ltest =
393 xrealloc(cbFile, numalloc * sizeof(ULONG), pszSrcFile, __LINE__);
394 if (!ltest)
395 goto AbortDrop;
396 cbFile = ltest;
397 ltest =
398 xrealloc(ulitemID, numalloc * sizeof(ULONG), pszSrcFile, __LINE__);
399 if (!ltest)
400 goto AbortDrop;
401 ulitemID = ltest;
402 }
403 cbFile[numfiles] = 0;
404 if (!isArc) {
405
406 FILESTATUS4 fsa4;
407
408 if (!DosQueryPathInfo(szFrom, FIL_QUERYEASIZE, &fsa4, sizeof(fsa4)))
409 cbFile[numfiles] = fsa4.cbFile + CBLIST_TO_EASIZE(fsa4.cbList);
410 }
411 ulitemID[numfiles] = pDItem->ulItemID;
412 files[numfiles] = xstrdup(szFrom, pszSrcFile, __LINE__);
413 files[numfiles + 1] = NULL;
414 if (!files[numfiles])
415 goto AbortDrop;
416 numfiles++;
417 DrgSendTransferMsg(pDItem->hwndItem,
418 DM_ENDCONVERSATION,
419 MPFROMLONG(pDItem->ulItemID),
420 MPFROMLONG(DMFL_TARGETSUCCESSFUL));
421 }
422 else
423 DrgSendTransferMsg(pDItem->hwndItem,
424 DM_ENDCONVERSATION,
425 MPFROMLONG(pDItem->ulItemID),
426 MPFROMLONG(DMFL_TARGETFAIL));
427 curitem++;
428 }
429
430AbortDrop:
431
432 if (files && numfiles && files[0] && cbFile && ulitemID) {
433 li = xmallocz(sizeof(LISTINFO), pszSrcFile, __LINE__);
434 if (li) {
435 li->type = Operation;
436 li->hwnd = hwndCnr;
437 li->list = files;
438 li->cbFile = cbFile;
439 li->ulitemID = ulitemID;
440 li->hwndS = pDInfo->hwndSource;
441 if (!pci && directory)
442 strcpy(li->targetpath, directory);
443 else if (pci)
444 strcpy(li->targetpath, pci->szFileName);
445 if (isArc) {
446 strcpy(li->arcname, szArc);
447 li->info = arcinfo;
448 }
449 SortList(li);
450 }
451 else {
452 if (cbFile)
453 free(cbFile);
454 if (ulitemID)
455 free(ulitemID);
456 if (files)
457 FreeList(files);
458 }
459 }
460 else {
461 if (cbFile)
462 free(cbFile);
463 if (ulitemID)
464 free(ulitemID);
465 if (files)
466 FreeList(files);
467 }
468 rc = DeleteDragitemStrHandles(pDInfo); //
469 if(!rc)
470 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
471 "DeleteDragitemStrHandles");
472 DrgDeleteDraginfoStrHandles(pDInfo);
473 DrgFreeDraginfo(pDInfo);
474 return li;
475}
Note: See TracBrowser for help on using the repository browser.