Version:
~ [ 10.0 ] ~
** Warning: Cannot open xref database.
1
2 /* $Id: filedialog.c,v 1.7 2005/10/07 04:07:42 icreedon Exp $ */
3
4 /******************************************************************************
5
6 UserLand Frontier(tm) -- High performance Web content management,
7 object database, system-level and Internet scripting environment,
8 including source code editing and debugging.
9
10 Copyright (C) 1992-2004 UserLand Software, Inc.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
26 ******************************************************************************/
27
28 #include "frontier.h"
29 #include "standard.h"
30
31 #ifdef MACVERSION
32 #include "mac.h"
33 #endif
34
35 #include "filealias.h"
36 #include "cursor.h"
37 #include "dialogs.h"
38 #include "error.h"
39 #include "memory.h"
40 #include "ops.h"
41 #include "quickdraw.h"
42 #include "resources.h"
43 #include "scrap.h"
44 #include "strings.h"
45 #include "threads.h"
46 #include "frontierwindows.h"
47 #include "file.h"
48 #include "shell.h"
49 #include "shell.rsrc.h"
50 #include "langinternal.h" /*for langbackgroundtask*/
51 #include "versions.h" /* 2005-09-23 creedon */
52
53
54 #ifdef MACVERSION
55
56 #include "SetUpA5.h"
57
58 #define sfgetfileid 5000
59 #define sfputfileid 5001
60 #define sfgetfolderid 5002
61 #define sfgetdiskid 5003
62
63 #define sfgetfolderbutton 11
64 #define sfgetpromptitem 10
65
66
67 typedef struct tysfdata { /*data passed to hook routines*/
68
69 StandardFileReply sfreply;
70
71 bigstring sfprompt;
72
73 Str63 sfname;
74
75 ptrsftypelist sftypes;
76 } tysfdata, *ptrsfdata;
77
78
79 #if !TARGET_API_MAC_CARBON
80
81 static pascal short sfputfilehook (short item, DialogPtr pdialog, tysfdata *pdata) {
82
83 /*
84 6/11/93 dmb: added for System 7 Standard File
85 */
86 #ifdef flcomponent
87 long curA5;
88 #endif
89 if (GetWRefCon (pdialog) != sfMainDialogRefCon)
90 return (item);
91
92 #ifdef flcomponent
93
94 curA5 = SetUpAppA5 ();
95
96 #endif
97
98 if (item == sfHookFirstCall) {
99
100 if ((*pdata).sfreply.sfFile.vRefNum != 0)
101 item = sfHookChangeSelection;
102 }
103
104 #ifdef flcomponent
105
106 RestoreA5 (curA5);
107
108 #endif
109
110 return (item);
111 } /*sfputfilehook*/
112
113
114 static pascal short sfprompthook (short item, DialogPtr pdialog, tysfdata *pdata) {
115
116 /*
117 6/11/93 dmb: recoded to System 7 Standard File
118 */
119 #ifdef flcomponent
120 long curA5;
121 #endif
122 if (GetWRefCon (pdialog) != sfMainDialogRefCon)
123 return (item);
124
125 #ifdef flcomponent
126
127 curA5 = SetUpAppA5 ();
128
129 #endif
130
131 if (item == sfHookFirstCall) {
132 Rect ritem, rdialog;
133 CGrafPtr dialogPort;
134 dialoggetobjectrect (pdialog, sfgetpromptitem, &ritem);
135
136 //Code change by Timothy Paustian Sunday, April 30, 2000 9:20:45 PM
137 //Changed to Opaque call for Carbon
138 #if ACCESSOR_CALLS_ARE_FUNCTIONS == 1
139 dialogPort = GetDialogPort(pdialog);
140 GetPortBounds(dialogPort, &rdialog);
141 #else
142 //old code
143 #pragma unused(dialogPort)
144 rdialog = (*pdialog).portRect;
145 #endif
146 if (isemptystring ((*pdata).sfprompt)) {
147
148 rdialog.bottom = ritem.top;
149
150 /*
151 hidedialogitem (pdialog, sfgetpromptitem);
152 */
153 }
154 else {
155
156 rdialog.bottom = ritem.bottom + 4;
157
158 setdialogtext (pdialog, sfgetpromptitem, (*pdata).sfprompt);
159 }
160
161 sizewindow (pdialog, rdialog.right - rdialog.left, rdialog.bottom - rdialog.top);
162
163 if ((*pdata).sfreply.sfFile.vRefNum != 0)
164 item = sfHookChangeSelection;
165 }
166
167 #ifdef flcomponent
168
169 RestoreA5 (curA5);
170
171 #endif
172
173 return (item);
174 } /*sfprompthook*/
175
176
177 static pascal short sffolderhook (short item, DialogPtr pdialog, tysfdata *pdata) {
178
179 /*
180 12/5/91 dmb: if a folder is selected, use it instead of the current folder
181
182 1/30/92 dmb: added code to handle folder aliases, which are files
183
184 9/15/92 dmb: save path in sfstring (255 chars) instead of reply.fName (63 chars)
185
186 6/11/93 dmb: recoded to System 7 Standard File
187
188 2.1b9 dmb: push dialog port when ellipsizing button title
189 */
190
191 bigstring bs;
192 #ifdef flcomponent
193 long curA5;
194 #endif
195
196 if (GetWRefCon (pdialog) != sfMainDialogRefCon)
197 return (item);
198
199 #ifdef flcomponent
200
201 curA5 = SetUpAppA5 ();
202
203 #endif
204
205 item = sfprompthook (item, pdialog, pdata);
206
207 switch (item) {
208
209 case sfgetfolderbutton: {
210
211 if ((*pdata).sfreply.sfFlags & kIsAlias) { /*must be the alias of a folder*/
212 Boolean flfolder, flwasalias;
213 OSErr errcode;
214
215 errcode = ResolveAliasFile (&(*pdata).sfreply.sfFile, true, &flfolder, &flwasalias);
216
217 switch (errcode) {
218
219 case noErr:
220 break;
221
222 case userCanceledErr:
223 item = sfHookNullEvent;
224
225 goto exit;
226
227 default:
228 getsystemerrorstring (errcode, bs);
229
230 parsedialogstring (bs, (*pdata).sfreply.sfFile.name, nil, nil, nil, bs);
231
232 customalert (sferrordialogid, bs);
233
234 item = sfHookNullEvent;
235
236 goto exit;
237 }
238 }
239
240 (*pdata).sfreply.sfGood = true;
241
242 item = sfItemCancelButton; /*force exit*/
243
244 break;
245 };
246
247 case sfHookNullEvent:
248 if (!equalstrings ((*pdata).sfname, (*pdata).sfreply.sfFile.name)) { /*selection changed*/
249 FSSpec fs;
250
251 fs = (*pdata).sfreply.sfFile;
252
253 copystring (fs.name, (*pdata).sfname); /*remember for next time before changing*/
254
255 if (isemptystring (fs.name)) /*nothing selected*/
256 FSMakeFSSpec (fs.vRefNum, fs.parID, nil, &fs);
257
258 copystring (fs.name, bs);
259 //Code change by Timothy Paustian Monday, August 21, 2000 4:20:21 PM
260 //pushport must have a CGrafPtr on OS X
261 {
262 CGrafPtr thePort;
263 #if TARGET_API_MAC_CARBON == 1
264 thePort = GetDialogPort(pdialog);
265 #else
266 thePort = (CGrafPtr)pdialog;
267 #endif
268
269 pushport (thePort);
270 }
271 ellipsize (bs, 72);
272
273 popport ();
274
275 setdialogbutton (pdialog, sfgetfolderbutton, bs);
276 }
277
278 break;
279 }
280
281 exit:
282
283 #ifdef flcomponent
284
285 RestoreA5 (curA5);
286
287 #endif
288
289 return (item);
290 } /*sffolderhook*/
291
292
293 static pascal short sfdiskhook (short item, DialogPtr pdialog, tysfdata *pdata) {
294
295 /*
296 6/11/93 dmb: recoded to System 7 Standard File; back to using Drive
297 button like Frontier 1.0.
298 */
299 #ifdef flcomponent
300 long curA5;
301 #endif
302 if (GetWRefCon (pdialog) != sfMainDialogRefCon)
303 return (item);
304
305 #ifdef flcomponent
306
307 curA5 = SetUpAppA5 ();
308
309 #endif
310
311 item = sfprompthook (item, pdialog, pdata);
312
313 switch (item) {
314
315 case sfItemOpenButton:
316 case sfHookOpenFolder:
317 #if 0
318
319 (*pdata).sfreply.vRefNum = -SFSaveDisk; /*IM IV-72*/
320
321 setemptystring ((*pdata).sfreply.fName); /*we just want the volume*/
322
323 #endif
324
325 FSMakeFSSpec ((*pdata).sfreply.sfFile.vRefNum, 0, 0, &(*pdata).sfreply.sfFile);
326
327 (*pdata).sfreply.sfGood = true;
328
329 item = sfItemCancelButton; /*force exit*/
330
331 break;
332
333 case sfHookGoToDesktop:
334 item = sfHookGoToNextDrive;
335
336 break;
337
338 case sfHookNullEvent:
339 if ((*pdata).sfreply.sfIsVolume) /*need to open volume to enable Drive button*/
340 item = sfHookOpenFolder;
341 else {
342 if (isemptystring ((*pdata).sfreply.sfFile.name)) /*no selection*/
343 item = sfHookGoToParent;
344 }
345
346 break;
347
348 case sfHookGoToParent:
349 item = sfHookNullEvent;
350
351 break;
352
353 default:
354 if (item >= sfHookCharOffset) /*typing -- ignore*/
355 item = sfHookNullEvent;
356 }
357
358 #ifdef flcomponent
359
360 RestoreA5 (curA5);
361
362 #endif
363
364 return (item);
365 } /*sfdiskhook*/
366
367
368 static pascal Boolean onlyfoldersfilter (ParmBlkPtr pb, tysfdata *pdata) {
369
370 #pragma unused (pdata)
371
372 /*
373 if (foldertest (pb))
374 */
375
376 if (pb->fileParam.ioFlAttrib & ioDirMask)
377 return (0);
378
379 return (-1); /*...don't show files*/
380 } /*onlyfoldersfilter*/
381
382
383 static pascal Boolean knowntypesfilter (ParmBlkPtr pb, tysfdata *pdata) {
384
385 short i;
386
387 if (pb->fileParam.ioFlAttrib & ioDirMask)
388 return (0);
389
390 if (pdata->sftypes == nil) // show all files
391 return (0);
392
393 for (i = 0; i < pdata->sftypes->cttypes; ++i) {
394
395 OSType type = pdata->sftypes->types [i];
396 byte bstype [6];
397 bigstring bssuffix;
398
399 ostypetostring (type, bstype);
400
401 lastword (pb->fileParam.ioNamePtr, '.', bssuffix);
402
403 if (stringlength (bssuffix) == 3) //handle 8.3 names
404 setstringlength (bstype, 3);
405
406 if (equalidentifiers (bssuffix, bstype))
407 return (0);
408
409 if (pb->fileParam.ioFlFndrInfo.fdType == type)
410 return (0);
411 }
412
413 return (-1); // didn't find it in our list
414 } /*knowntypesfilter*/
415
416
417
418 #if !TARGET_RT_MAC_CFM
419
420 #define onlyfoldersfilterUPP ((FileFilterYDUPP) &onlyfoldersfilter)
421 #define knowntypesfilterUPP ((FileFilterYDUPP) &knowntypesfilter)
422 #define sfputfilehookUPP (&sfputfilehook)
423 #define sfprompthookUPP (&sfprompthook)
424 #define sffolderhookUPP (&sffolderhook)
425 #define sfdiskhookUPP (&sfdiskhook)
426
427 #else
428
429 #if !TARGET_API_MAC_CARBON
430 static RoutineDescriptor onlyfoldersfilterDesc = BUILD_ROUTINE_DESCRIPTOR (uppFileFilterYDProcInfo, onlyfoldersfilter);
431 static RoutineDescriptor knowntypesfilterDesc = BUILD_ROUTINE_DESCRIPTOR (uppFileFilterYDProcInfo, knowntypesfilter);
432 static RoutineDescriptor sfputfilehookDesc = BUILD_ROUTINE_DESCRIPTOR (uppDlgHookYDProcInfo, sfputfilehook);
433 static RoutineDescriptor sfprompthookDesc = BUILD_ROUTINE_DESCRIPTOR (uppDlgHookYDProcInfo, sfprompthook);
434 static RoutineDescriptor sffolderhookDesc = BUILD_ROUTINE_DESCRIPTOR (uppDlgHookYDProcInfo, sffolderhook);
435 static RoutineDescriptor sfdiskhookDesc = BUILD_ROUTINE_DESCRIPTOR (uppDlgHookYDProcInfo, sfdiskhook);
436
437
438 #define onlyfoldersfilterUPP (&onlyfoldersfilterDesc)
439 #define knowntypesfilterUPP (&knowntypesfilterDesc)
440 #define sfputfilehookUPP (&sfputfilehookDesc)
441 #define sfprompthookUPP (&sfprompthookDesc)
442 #define sffolderhookUPP (&sffolderhookDesc)
443 #define sfdiskhookUPP (&sfdiskhookDesc)
444
445 #endif
446
447
448 #endif
449
450 #endif /* !TARGET_API_MAC_CARBON */
451
452
453 boolean sfdialog (tysfverb sfverb, bigstring bsprompt, ptrsftypelist filetypes, tyfilespec *fspec, OSType filecreator) {
454
455 /*
456 return true if the user selected a file with one of the SF routines,
457 return false otherwise.
458
459 as a bonus, we return the full path for the selected file in the path string.
460
461 2005-10-06 creedon: added filecreator parameter, used for get file dialog
462
463 2005-09-21 creedon: changed from TimsGetFile to getafile
464
465 Tuesday, June 20, 2000 8:50:41 PM Timothy Paustian: I am going to hack the heck out of this routine. See what you think
466
467 4.1b13 dmb: un-commented out the shellwritescrap and shellactive calls.
468 I don't know how they got commented; I must have been experimenting with
469 something.
470
471 2.1b2 dmb: updated interface to be filespec-based. for putfile, the name in the
472 filespec is the default name. for all verbs, a non-empty filespec seeds the dialog
473
474 2.1b1 dmb: set sfdata.sfname to an impossible value to ensure button update
475
476 6/11/93 dmb: recoded to System 7 Standard File
477
478 12/18/92 dmb: call shellwritescrap
479
480 9/15/92 dmb: when picking a folder, grab path from sfstring instead of reply
481 record.
482
483 2/10/92 dmb: added call to new shellactivate; standard file breaks when brought
484 up in the background.
485
486 12/27/91 dmb: if the default fname includes a colon, attempt to set default
487 directory, and remove folder specification from dialog default
488
489 4/16/91 dmb: replaced filetype parameter with pointer to type list. callers
490 can pass nil when irrelevant, or when all types are to be shown.
491
492 11/16/90 dmb: replace flput boolean with sfverb enum. added code for folder
493 and disk selection dialogs
494
495 8/1/90 dmb: if filetype is zero, show all files by passing zero to SFGetFile
496 */
497
498 Str255 bs;
499 tysfdata sfdata;
500 FSSpec *fs = &sfdata.sfreply.sfFile;
501 OSErr anErr = noErr;
502 #if !TARGET_API_MAC_CARBON
503 Point pt = {-1, -1};
504 short cttypes = -1;
505 OSType *types = nil;
506 #endif
507 #ifdef flcomponent
508 long appA5;
509 #endif
510
511 //move the switch statement to below because it's smarter to call it there when using
512 //the new routines for Nav services.
513
514 clearbytes (&sfdata, sizeof (sfdata));
515
516 copystring (bsprompt, sfdata.sfprompt);
517
518 sfdata.sftypes = filetypes;
519
520 setemptystring (bs);
521
522 if (!isemptystring ((*fspec).name)) { /*if path is included, set default dir and strip to file name*/
523
524 *fs = *fspec; /*seed directory & file selection*/
525
526 /*
527 if (pathtofilespec (fname, fs) && ((*fs).vRefNum != 0))
528 copystring ((*fs).name, fname);
529 else
530 filefrompath (fname, fname);
531 */
532 }
533
534 setstringlength (sfdata.sfname, -1); /*make sure it can't match fsspec*/
535
536 shellwritescrap (textscraptype);
537
538 shellactivate ();
539
540 #ifdef flcomponent
541
542 appA5 = SetUpCurA5 (); /*for system*/
543
544 #endif
545
546 switch (sfverb) {
547
548 case sfputfileverb:
549 if(gCanUseNavServ) {
550 anErr = TimsPutFile(bsprompt, (*fs).name, &sfdata.sfreply);
551 }
552 #if TARGET_API_MAC_CARBON != 1
553 //we can get away with this because nav services is always there in OSX.
554 else
555 CustomPutFile (bsprompt, (*fs).name, &sfdata.sfreply, sfputfileid, pt,
556 sfputfilehookUPP, nil, nil, nil, &sfdata);
557 #endif
558
559 break;
560
561 case sfgetfileverb:
562 if(gCanUseNavServ)
563 anErr = getafile (bsprompt, filetypes, &sfdata.sfreply, filecreator);
564 #if !TARGET_API_MAC_CARBON
565 else
566 CustomGetFile (knowntypesfilterUPP, cttypes, types, &sfdata.sfreply, sfgetfileid, pt,
567 sfprompthookUPP, nil, nil, nil, &sfdata);
568 #endif
569 break;
570
571 case sfgetfolderverb:
572 if(gCanUseNavServ)
573 anErr = TimsGetFolderOrVolume(bsprompt, sfgetfolderid, &sfdata.sfreply);
574 #if !TARGET_API_MAC_CARBON
575 else
576 CustomGetFile (onlyfoldersfilterUPP, cttypes, types, &sfdata.sfreply, sfgetfolderid, pt,
577 sffolderhookUPP, nil, nil, nil, &sfdata);
578 #endif
579 break;
580
581 case sfgetdiskverb:
582 if(gCanUseNavServ)
583 anErr = TimsGetFolderOrVolume(bsprompt, sfgetdiskid, &sfdata.sfreply);
584 #if !TARGET_API_MAC_CARBON
585 else
586 CustomGetFile (nil, cttypes, types, &sfdata.sfreply, sfgetdiskid, pt,
587 sfdiskhookUPP, nil, nil, nil, &sfdata);
588 #endif
589
590 break;
591 }
592
593 //code moved to above
594 //if (sfverb == sfputfileverb)
595 //Code change by Timothy Paustian Tuesday, June 20, 2000 8:44:39 PM
596 //I added nav services as the dialog. This works well so I updated it
597 //in the PPC version also.
598 //CustomPutFile (bsprompt, (*fs).name, &sfdata.sfreply, id, pt,
599 // sfhook, nil, nil, nil, &sfdata);
600 //else
601 //Code change by Timothy Paustian Tuesday, June 20, 2000 2:58:33 PM
602 //Use nav services verbs and a switch statment
603
604 //CustomGetFile (sffilefilter, cttypes, types, &sfdata.sfreply, id, pt,
605 // sfhook, nil, nil, nil, &sfdata);
606
607 #ifdef flcomponent
608
609 RestoreA5 (appA5);
610
611 #endif
612 //if the user canceled return false
613 //I know that oserror can handle this, but lets make it
614 //obvious that we are checking.
615 if (userCanceledErr == anErr)
616 return false;
617
618 if(oserror(anErr))
619 return false;
620
621 if (sfdata.sfreply.sfGood) {
622
623 FSMakeFSSpec ((*fs).vRefNum, (*fs).parID, (*fs).name, fspec); /*canonize*/
624
625 /*
626 *fspec = sfdata.sfreply.sfFile;
627 */
628 return (true);
629 }
630
631 return (false);
632 } /*sfdialog*/
633
634 #endif
635
636 #ifdef WIN95VERSION
637 static void buildfilter (char * filter, short * len, bigstring bsname, bigstring bsext) {
638 short namelen, extlen;
639
640 namelen = stringlength (bsname);
641 extlen = stringlength (bsext);
642
643 memmove (filter + *len, stringbaseaddress(bsname), namelen);
644 *len = *len + namelen;
645 memmove (filter + *len, "\0", 1);
646 *len = *len + 1;
647 memmove (filter + *len, stringbaseaddress(bsext), extlen);
648 *len = *len + extlen;
649 memmove (filter + *len, "\0", 1);
650 *len = *len + 1;
651 memmove (filter + *len, "\0", 1); //alway finish the filter but don't count it in the length
652 } /*buildfilter*/
653
654
655 boolean sfdialog (tysfverb sfverb, bigstring bsprompt, ptrsftypelist filetypes, tyfilespec *fspec, OSType filecreator) {
656
657 #pragma unused (filecreator)
658
659 /*
660 2005-10-06 creedon: added filecreator, unused on Windows
661
662 5.0.2b4 dmb: fixed bug in above change that would generate an error for empty paths
663
664 5.0.1 dmb: make sure default file and directory are valid, or we'll fail (silently)
665 */
666
667 TCHAR szFile[MAX_PATH];
668 OPENFILENAME OpenFileName;
669 BROWSEINFO BrowseInfo;
670 LPITEMIDLIST itemList;
671 char title [256];
672 char filter [1024];
673 short filterlen = 0;
674 char defaultdir [256];
675 char defaultfile [256];
676 bigstring extension;
677 byte type [6];
678 bigstring osstring;
679 boolean fl = false;
680 short i;
681 boolean fldatabases = false;
682 boolean flfatpages = false;
683 // Global pointer to the shell's IMalloc interface.
684 static LPMALLOC pMalloc = NULL;
685
686 OpenFileName.lStructSize = sizeof(OPENFILENAME);
687 OpenFileName.hwndOwner = shellframewindow;
688 OpenFileName.hInstance = shellinstance;
689 OpenFileName.lpstrFilter = NULL;
690 OpenFileName.lpstrCustomFilter = NULL;
691 OpenFileName.nMaxCustFilter = 0;
692 OpenFileName.nFilterIndex = 0;
693 OpenFileName.lpstrFile = stringbaseaddress(fsname (fspec));
694 OpenFileName.nMaxFile = sizeof(fsname (fspec)) - 2;
695 OpenFileName.lpstrFileTitle = NULL;
696 OpenFileName.nMaxFileTitle = 0;
697 OpenFileName.lpstrTitle = title;
698 OpenFileName.lpstrInitialDir = NULL;
699 OpenFileName.lpstrTitle = NULL;
700 OpenFileName.nFileOffset = 0;
701 OpenFileName.nFileExtension = 0;
702 OpenFileName.lpstrDefExt = NULL;
703 OpenFileName.lCustData = (LPARAM)NULL;
704 OpenFileName.lpfnHook = NULL;
705 OpenFileName.lpTemplateName = 0;
706
707 strcpy (szFile, "");
708
709 // set the title
710 if (bsprompt != NULL) {
711
712 copyptocstring (bsprompt, title);
713
714 OpenFileName.lpstrTitle = title;
715 }
716
717 // set default dir, file and extension fields
718 if (!isemptystring (fsname (fspec))) {
719
720 tyfilespec fsdir;
721 boolean flfolder;
722
723 folderfrompath (fsname (fspec), defaultdir);
724
725 if (pathtofilespec (defaultdir, &fsdir) &&
726 fileexists (&fsdir, &flfolder) && flfolder) {
727
728 OpenFileName.lpstrInitialDir = defaultdir;
729
730 //if (!isemptystring (defaultdir))
731 // OpenFileName.nFileOffset = stringlength (defaultdir) + 1;
732
733 convertpstring (defaultdir);
734 }
735
736 filefrompath (fsname (fspec), defaultfile);
737
738 lastword (defaultfile, ':', defaultfile); //skip any Mac path
739
740 //OpenFileName.nFileExtension = stringlength (fsname (fspec));
741
742 lastword (defaultfile, '.', extension);
743
744 //if (stringlength (extension) < stringlength (fsname (fspec)))
745 // OpenFileName.nFileExtension -= stringlength (extension);
746
747 copystring (defaultfile, fsname (fspec));
748
749 nullterminate (fsname (fspec));
750 }
751
752 releasethreadglobals ();
753
754 switch (sfverb) {
755
756 case sfputfileverb:
757 OpenFileName.Flags = OFN_SHOWHELP | OFN_EXPLORER | OFN_OVERWRITEPROMPT; //| OFN_NOCHANGEDIR;
758
759 if (filetypes != nil) {
760 setemptystring (filter);
761
762 //RAB: 1/22/98 use string since the windows type can be any case
763 ostypetostring ((*filetypes).types [0], osstring);
764
765 if (equalidentifiers (osstring, "\x04" "fatp"))
766 copystring ("\x016" "Fat Page [*.fatp]\0*.*\0", filter);
767
768 else if (equalidentifiers (osstring, "\x04" "ftop"))
769 copystring ("\x015" "Outline [*.ftop]\0*.*\0", filter);
770
771 else if (equalidentifiers (osstring, "\x04" "ftwp"))
772 copystring ("\x019" "WP Document [*.ftwp]\0*.*\0", filter);
773
774 else if (equalidentifiers (osstring, "\x04" "fttb"))
775 copystring ("\x013" "Table [*.fttb]\0*.*\0", filter);
776
777 else if (equalidentifiers (osstring, "\x04" "ftmb"))
778 copystring ("\x012" "Menu [*.ftmb]\0*.*\0", filter);
779
780 else if (equalidentifiers (osstring, "\x04" "ftsc"))
781 copystring ("\x014" "Script [*.ftsc]\0*.*\0", filter);
782
783 else if (equalidentifiers (osstring, "\x04" "ftds"))
784 copystring ("\x01c" "Desktop Script [*.ftds]\0*.*\0", filter);
785
786 else if (equalidentifiers (osstring, "\x04" "root"))
787 copystring ("\x016" "Database [*.root]\0*.*\0", filter);
788
789 if (! isemptystring (filter)) {
790 convertpstring (filter);
791
792 OpenFileName.lpstrFilter = filter;
793 }
794
795 ostypetostring ((*filetypes).types [0], type);
796
797 popleadingchars (type, '.');
798
799 poptrailingwhitespace (type);
800
801 // convertpstring (type);
802
803 // OpenFileName.lpstrDefExt = type;
804 OpenFileName.lpstrDefExt = NULL;
805 }
806
807 // Call the common dialog function.
808 fl = GetSaveFileName (&OpenFileName);
809
810 if (fl && (filetypes != NULL) && (stringlength(type) > 0)) {
811
812 setstringlength (fsname (fspec), strlen(stringbaseaddress(fsname (fspec))));
813 lastword (fsname (fspec), '.', extension);
814
815 if ((stringlength (fsname (fspec)) == stringlength (extension)) || (stringlength (extension) > 4)) { /* no extension */
816 pushstring ("\x01.", fsname(fspec));
817 pushstring (type, fsname(fspec));
818 nullterminate (fsname (fspec));
819 }
820 }
821
822 break;
823
824 case sfgetfileverb:
825 OpenFileName.Flags = OFN_SHOWHELP | OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; //| OFN_NOCHANGEDIR;
826
827 // create the filter string
828 if (filetypes != nil) { /*showing specific files*/
829
830 //copystring ("\x09Types: [\0", filter);
831 setemptystring (extension);
832
833 for (i = 0; i < (*filetypes).cttypes; ++i) {
834
835 if (i > 0)
836 pushchar (';', extension);
837
838 if ((*filetypes).types [i] == 'root')
839 fldatabases = true;
840
841 if ((*filetypes).types [i] == 'fatp')
842 flfatpages = true;
843
844 if ((*filetypes).types [i] == 'ROOT')
845 fldatabases = true;
846
847 if ((*filetypes).types [i] == 'FATP')
848 flfatpages = true;
849
850 ostypetostring ((*filetypes).types [i], type);
851
852 popleadingchars (type, '.');
853
854 poptrailingwhitespace (type);
855
856 pushstring ("\x02" "*.", extension);
857
858 pushstring (type, extension);
859
860 if (stringlength (type) > 3) {
861
862 setstringlength (type, 3);
863
864 pushstring ("\x03" ";*.", extension);
865
866 pushstring (type, extension);
867 }
868 }
869
870
871 filterlen = 0;
872
873 buildfilter (filter, &filterlen, "\x1c" "Openable Types: [*.clickers]", extension);
874
875 if (fldatabases)
876 buildfilter (filter, &filterlen, "\x12" "Databases [*.root]", "\x0c" "*.root;*.roo");
877
878 // pushstring ("\x20\0Databases [*.root]\0*.roo;*.root", filter);
879
880 if (flfatpages) {
881 buildfilter (filter, &filterlen, "\x12" "Fat Pages [*.fatp]", "\x5a" "*.fatp;*.fat;*.FTsc;*.FTs;*.FTwp;*.FTw;*.FTop;*.FTo;*.FTmb;*.FTm;*.FTtb;*.FTt;*.Ftds;*.FTd");
882 buildfilter (filter, &filterlen, "\x17" "Frontier Menus [*.FTmb]", "\x0c" "*.FTmb;*.FTm");
883 buildfilter (filter, &filterlen, "\x1a" "Frontier Outlines [*.FTop]", "\x0c" "*.FTop;*.FTo");
884 buildfilter (filter, &filterlen, "\x19" "Frontier Scripts [*.FTsc]", "\x0c" "*.FTsc;*.FTs");
885 buildfilter (filter, &filterlen, "\x21" "Frontier Desktop Scripts [*.FTds]", "\x0c" "*.FTds;*.FTd");
886 buildfilter (filter, &filterlen, "\x18" "Frontier Tables [*.FTtb]", "\x0c" "*.FTtb;*.FTt");
887 buildfilter (filter, &filterlen, "\x19" "Frontier WP Text [*.FTwp]", "\x0c" "*.FTwp;*.FTw");
888 }
889
890 // pushstring ("\x20\0Fat Pages [*.fatp]\0*.fat;*.fatp", filter);
891
892 buildfilter (filter, &filterlen, "\x12" "Plain Text [*.txt]", "\x12" "*.Text;*.txt;*.tex");
893 buildfilter (filter, &filterlen, "\x0f" "All Files [*.*]", "\x03" "*.*");
894
895 OpenFileName.lpstrFilter = filter;
896
897 ostypetostring ((*filetypes).types [0], type);
898
899 //RAB: 1/22/98 added next two lines
900 // poptrailingwhitespace is no longer done in ostypetostring.
901 popleadingchars (type, '.');
902
903 poptrailingwhitespace (type);
904
905 convertpstring (type);
906
907 OpenFileName.lpstrDefExt = type;
908 }
909
910 // Call the common dialog function.
911 fl = GetOpenFileName (&OpenFileName);
912
913 break;
914
915 case sfgetfolderverb:
916 case sfgetdiskverb:
917 // Get the shell's allocator.
918 if (pMalloc == NULL && !SUCCEEDED(SHGetMalloc(&pMalloc)))
919 break;
920
921 BrowseInfo.hwndOwner = OpenFileName.hwndOwner;
922 BrowseInfo.pidlRoot = NULL;
923 BrowseInfo.pszDisplayName = szFile;
924 BrowseInfo.lpszTitle = OpenFileName.lpstrTitle;
925 BrowseInfo.ulFlags = BIF_RETURNONLYFSDIRS;
926 if (sfverb == sfgetdiskverb)
927 BrowseInfo.ulFlags |= BIF_RETURNFSANCESTORS;
928 BrowseInfo.lpfn = NULL;
929 BrowseInfo.lParam = 0;
930
931 itemList = SHBrowseForFolder (&BrowseInfo);
932
933 if (itemList != NULL) {
934
935 fl = SHGetPathFromIDList (itemList, szFile);
936
937 copyctopstring (szFile, fsname (fspec));
938
939 if (sfverb == sfgetdiskverb) {
940
941 firstword (fsname (fspec), ':', fsname (fspec));
942
943 pushstring ("\x02:\\", fsname (fspec));
944 }
945 else {
946
947 pushstring ("\x01\\", fsname (fspec));
948 }
949
950 nullterminate (fsname (fspec));
951
952 // deallocate itemList
953 pMalloc->lpVtbl->Free (pMalloc, itemList);
954
955 /*
956 LPSHELLFOLDER ppshf;
957 if (SHGetDesktopFolder (&ppshf) == NOERROR) {
958 ULONG ctchars;
959 WCHAR szWide [300];
960
961 MultiByteToWideChar (CP_ACP, 0, szFile, -1, szWide, 300);
962
963 ppshf->lpVtbl->ParseDisplayName (ppshf, NULL, szWide, &ctchars, &itemList,NULL);
964
965 fl = SHGetPathFromIDList (itemList, szFile);
966
967 pMalloc->lpVtbl->Free (pMalloc, itemList);
968
969 ppshf->lpVtbl->Release (ppshf);
970 }
971 */
972 }
973
974 break;
975
976 }
977
978 grabthreadglobals ();
979
980 if (!fl) {
981
982 oserror (GetLastError ());
983
984 return (false);
985 }
986
987 setstringlength (fsname (fspec), strlen(stringbaseaddress(fsname (fspec))));
988
989 return (true);
990 } /*sfdialog*/
991
992 #endif
993
994
995 #ifdef MACVERSION
996
997 boolean initfiledialog (void) {
998
999 #ifdef flcomponent
1000
1001 #if !TARGET_API_MAC_CARBON
1002 RememberA5 ();
1003 #endif /*for hook*/
1004
1005 #endif
1006
1007 return (true);
1008 } /*initfile*/
1009
1010
1011 //Code change by Timothy Paustian Tuesday, June 20, 2000 2:55:17 PM
1012 //New routine to use Nav services for this instead of CustomPutFile.
1013 OSErr
1014 TimsPutFile(bigstring prompt, Str255 fileName, StandardFileReply * outReply)
1015 {
1016
1017 OSErr anErr = noErr;
1018 NavReplyRecord reply;
1019 NavDialogOptions dialogOptions;
1020 OSType fileTypeToSave = 'TEXT';
1021 NavEventUPP eventProc = NewNavEventUPP(NavEventProc);
1022
1023 anErr = NavGetDefaultDialogOptions(&dialogOptions);
1024 copystring(fileName, dialogOptions.savedFileName);
1025 copystring(prompt, dialogOptions.message);
1026 dialogOptions.dialogOptionFlags |= kNavNoTypePopup; /* 08/25/2000 AR */
1027 if (anErr == noErr)
1028 {
1029 anErr = NavPutFile( nil, &reply, &dialogOptions, eventProc,
1030 fileTypeToSave, 'LAND', nil);
1031
1032 if (anErr == noErr && reply.validRecord)
1033 {
1034 AEKeyword theKeyword;
1035 DescType actualType;
1036 Size actualSize;
1037 FSSpec documentFSSpec;
1038
1039 anErr = AEGetNthPtr(&(reply.selection), 1, typeFSS,
1040 &theKeyword, &actualType,
1041 &documentFSSpec, sizeof(documentFSSpec),
1042 &actualSize );
1043 if (anErr == noErr)
1044 {
1045
1046 outReply->sfReplacing = reply.replacing;
1047 FSMakeFSSpec (documentFSSpec.vRefNum, documentFSSpec.parID, documentFSSpec.name, &(outReply->sfFile));
1048 outReply->sfGood = true;
1049 }
1050 // Always call NavCompleteSave() to complete
1051 #if TARGET_API_MAC_CARBON != 1
1052 anErr = NavCompleteSave(&reply, kNavTranslateInPlace);
1053 #endif
1054
1055 (void) NavDisposeReply(&reply);
1056 }
1057 }
1058 DisposeNavEventUPP(eventProc);
1059 return anErr;
1060 }
1061
1062
1063 OSErr getafile (bigstring prompt, ptrsftypelist filetypes, StandardFileReply * outReply, OSType filecreator) {
1064
1065 /*
1066 2005-10-06 creedon: added filecreator parameter
1067
1068 2005-09-21 creedon: created, cribbed from TimsGetFile
1069 */
1070
1071 NavDialogCreationOptions dialogOptions;
1072 NavDialogRef dialogRef;
1073 NavEventUPP eventProc = NewNavEventUPP (NavEventProc);
1074 NavReplyRecord reply;
1075 NavTypeListHandle typeList = nil;
1076 OSErr anErr = noErr;
1077
1078 anErr = NavGetDefaultDialogCreationOptions (&dialogOptions);
1079
1080 dialogOptions.clientName = CFStringCreateWithCString (NULL, APPNAME_SHORT, kCFStringEncodingMacRoman);
1081 dialogOptions.message = CFStringCreateWithPascalString (NULL, prompt, kCFStringEncodingMacRoman);
1082
1083 if (anErr == noErr) {
1084
1085 if (filetypes == nil)
1086 dialogOptions.optionFlags -= kNavNoTypePopup;
1087 else
1088 dialogOptions.optionFlags += kNavAllFilesInPopup; // add all documents to show pop-up
1089
1090 dialogOptions.optionFlags ^=kNavAllowMultipleFiles; //no multiple files for now
1091
1092 dialogOptions.optionFlags ^= kNavAllowPreviews; // clear preview option
1093
1094 dialogOptions.optionFlags += kNavSupportPackages; // see packages
1095
1096 // dialogOptions.dialogOptionFlags += kNavAllowOpenPackages; // can open packages
1097
1098 if (filetypes != nil) { // translate into a type list NavServices understands
1099
1100 NavTypeListPtr typesP = nil;
1101 SInt32 hSize = (sizeof (NavTypeList) + sizeof (OSType) * (filetypes->cttypes - 1));
1102 newhandle (hSize, (Handle*) &typeList);
1103 typesP = (NavTypeListPtr) *((Handle) typeList);
1104
1105 typesP->componentSignature = filecreator;
1106 typesP->reserved = 0;
1107 typesP->osTypeCount = filetypes->cttypes;
1108
1109 BlockMoveData (&(filetypes->types), typesP->osType, (Size) (sizeof (OSType) * filetypes->cttypes));
1110 }
1111
1112 anErr = NavCreateGetFileDialog (&dialogOptions, typeList, eventProc, NULL, NULL, NULL, &dialogRef);
1113
1114 anErr = NavDialogRun (dialogRef);
1115
1116 anErr = NavDialogGetReply (dialogRef, &reply);
1117
1118 if (anErr == noErr && reply.validRecord) {
1119
1120 AEKeyword theKeyword;
1121 DescType actualType;
1122 Size actualSize;
1123 FSSpec documentFSSpec;
1124
1125 anErr = AEGetNthPtr (&(reply.selection), 1, typeFSS, &theKeyword, &actualType, &documentFSSpec, sizeof (documentFSSpec), &actualSize); // get a pointer to selected file
1126
1127 assert (actualType == typeFSS);
1128
1129 if (anErr == noErr) {
1130 FSMakeFSSpec (documentFSSpec.vRefNum, documentFSSpec.parID, documentFSSpec.name, &(outReply->sfFile));
1131
1132 outReply->sfGood = true;
1133 }
1134
1135 anErr = NavDisposeReply (&reply); // dispose of NavReplyRecord, resources, descriptors
1136 }
1137 }
1138
1139 DisposeNavEventUPP (eventProc);
1140
1141 NavDialogDispose (dialogRef);
1142
1143 return anErr;
1144 } /* getafile */
1145
1146
1147 OSErr
1148 TimsGetFolderOrVolume(bigstring prompt, SInt16 dialogType, StandardFileReply * outReply)
1149 {
1150 NavDialogOptions dialogOptions;
1151 NavEventUPP eventProc = NewNavEventUPP(NavEventProc);
1152 OSErr anErr = noErr;
1153 NavReplyRecord reply;
1154
1155 // Specify default options for dialog box
1156 //we don't really need to modify this, but it is needed for NavChooseFolder
1157 anErr = NavGetDefaultDialogOptions(&dialogOptions);
1158 copystring(prompt, dialogOptions.message);
1159
1160 if(anErr == noErr)
1161 {
1162 //display the dialog
1163 if(sfgetfolderid == dialogType)
1164 anErr = NavChooseFolder(nil, &reply, &dialogOptions, eventProc, nil, nil);
1165 else
1166 {
1167 assert(sfgetdiskid == dialogType);
1168 anErr = NavChooseVolume(nil, &reply, &dialogOptions, eventProc, nil, nil);
1169 }
1170
1171 if (anErr == noErr && reply.validRecord)
1172 {
1173 AEKeyword theKeyword;
1174 DescType actualType;
1175 Size actualSize;
1176 FSSpec documentFSSpec;
1177
1178 // Get a pointer to selected file
1179 anErr = AEGetNthPtr(&(reply.selection), 1,
1180 typeFSS, &theKeyword,
1181 &actualType, &documentFSSpec,
1182 sizeof(documentFSSpec),
1183 &actualSize);
1184 assert(actualType == typeFSS);
1185 if (anErr == noErr)
1186 {
1187 FSMakeFSSpec (documentFSSpec.vRefNum, documentFSSpec.parID, documentFSSpec.name, &(outReply->sfFile));
1188 outReply->sfGood = true;
1189 }
1190 // Dispose of NavReplyRecord
1191 anErr = NavDisposeReply(&reply);
1192 }
1193 }
1194 DisposeNavEventUPP (eventProc);
1195 return anErr;
1196 }
1197
1198
1199
1200
1201
1202
1203 //Code change by Timothy Paustian Tuesday, June 20, 2000 9:07:26 PM
1204 //a very simple event proc so that Nav file service dialogs are movable and resizable.
1205 pascal void NavEventProc(NavEventCallbackMessage callBackSelector,
1206 NavCBRecPtr callBackParms,
1207 NavCallBackUserData callBackUD)
1208 {
1209 #pragma unused(callBackUD)
1210 if (callBackSelector == kNavCBEvent)
1211 {
1212 if(((callBackParms->eventData)
1213 .eventDataParms).event->what == updateEvt)
1214 {
1215 //I was having a crash due to getting the window ptr outside the switch statement.
1216 // This now works.
1217 //10/30/00 Timothy Paustian
1218 WindowPtr window = (WindowPtr)(((callBackParms->eventData).eventDataParms).event)->message;
1219 shellupdatenow(window);
1220 }
1221 }
1222 }
1223
1224 #endif
1225
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.