5#include "Stroika/Foundation/StroikaPreComp.h"
7#include <ControlDefinitions.h>
11#include <PP_Resources.h>
13#include <UExtractFromAEDesc.h>
14#include <UModalDialogs.h>
15#include <UStandardDialogs.h>
17#include "LedItResources.h"
19#include "FilteredFilePicker.h"
24 static int Append_DITL (DialogPtr dialog,
int item_list_ID);
27 inline MenuHandle GetPopUpMenuHandle (ControlHandle thisControl)
30 return ::GetControlPopupMenuHandle (thisControl);
34 Led_RequireNotNil (thisControl);
35 PopupPrivateData** theMenuData = (PopupPrivateData**)(*thisControl)->contrlData;
36 Led_AssertNotNil (theMenuData);
37 Led_EnsureNotNil ((*theMenuData)->mHandle);
38 return ((*theMenuData)->mHandle);
43 inline NavTypeListHandle CreateNavTypeList (UInt16 inNumTypes,
const OSType* inSFTypeList)
45 NavTypeListHandle list = (NavTypeListHandle)::NewHandleClear ((
sizeof (NavTypeList) -
sizeof (OSType)) + (inNumTypes *
sizeof (OSType)));
46 Execution::ThrowIfNull (list);
47 (*list)->componentSignature = kNavGenericSignature;
48 (*list)->osTypeCount = inNumTypes;
49 memcpy ((*list)->osType, inSFTypeList, inNumTypes * sizeof (OSType));
55 FSSpec CombineDirAndFileName (
const FSSpec& dir, ConstStr255Param fileName)
58 memset (&pb, 0,
sizeof (pb));
59 FSSpec tmpFSSpec = dir;
60 pb.dirInfo.ioNamePtr = tmpFSSpec.name;
61 pb.dirInfo.ioVRefNum = tmpFSSpec.vRefNum;
62 pb.dirInfo.ioDrDirID = tmpFSSpec.parID;
63 OSErr err = ::PBGetCatInfoSync (&pb);
67 err = FSMakeFSSpec (pb.dirInfo.ioVRefNum, pb.dirInfo.ioDrDirID, fileName, &result);
77FilteredSFGetDLog::FilteredSFGetDLog (
const TypeSpec* typeNameList,
size_t nTypes)
83 fTypeSpecs (typeNameList)
84 , fTypeSpecCount (nTypes)
85 , fCurPopupIdx (kBadIndex)
86 , fPopupDLGItemNumber (0)
87#if !qUseNavServices && !TARGET_CARBON
93bool FilteredSFGetDLog::PickFile (FSSpec* result,
bool* typeSpecified,
size_t* typeIndex)
95 Led_RequireNotNil (result);
97 bool userPickGood =
false;
99 UDesktop::Deactivate ();
102 NavDialogCreationOptions options;
103 (void)::memset (&options, 0,
sizeof (options));
104 Led_ThrowIfOSStatus (::NavGetDefaultDialogCreationOptions (&options));
106 options.optionFlags |= kNavNoTypePopup;
107 options.optionFlags &= ~kNavAllowMultipleFiles;
108 options.optionFlags &= ~kNavAllowStationery;
109 options.optionFlags &= ~kNavAllowPreviews;
111 options.modality = kWindowModalityAppModal;
113 Led_SmallStackBuffer<OSType> osTypeBuf (fTypeSpecCount);
115 for (
size_t i = 0; i < fTypeSpecCount; ++i) {
116 osTypeBuf[i] = fTypeSpecs[i].fOSType;
120 NavTypeListHandle typeList = NULL;
121 NavObjectFilterUPP filterProc = NULL;
122 NavEventUPP eventProc = NULL;
123 NavReplyRecord replyRec;
124 memset (&replyRec, 0,
sizeof (replyRec));
126 typeList = CreateNavTypeList (fTypeSpecCount, osTypeBuf);
128 eventProc = ::NewNavEventUPP (StaticNavEventProc);
129 Led_AssertNotNil (eventProc);
130 filterProc = ::NewNavObjectFilterUPP (StaticNavObjectFilterProc);
131 Led_AssertNotNil (filterProc);
133 Led_Assert (fCurDialog == NULL);
134 Led_ThrowIfOSStatus (::NavCreateGetFileDialog (&options, typeList, eventProc, NULL, filterProc,
this, &fCurDialog));
136 Led_ThrowIfOSStatus (::NavDialogRun (fCurDialog));
138 Led_ThrowIfOSStatus (::NavDialogGetReply (fCurDialog, &replyRec));
140 userPickGood = replyRec.validRecord;
142 if (typeSpecified != NULL) {
143 *typeSpecified = (fCurPopupIdx != kBadIndex) and (fCurPopupIdx >= 4);
145 if (typeSpecified != NULL and *typeSpecified and typeIndex != NULL) {
146 *typeIndex = fCurPopupIdx - 4 + 0;
148 UExtractFromAEDesc::TheFSSpec (replyRec.selection, *result);
152 userPickGood =
false;
154 if (replyRec.validRecord) {
155 ::NavDisposeReply (&replyRec);
157 if (fCurDialog != NULL) {
158 ::NavDialogDispose (fCurDialog);
161 if (typeList != NULL) {
162 ::DisposeHandle (
reinterpret_cast<Handle
> (typeList));
164 if (eventProc != NULL) {
165 ::DisposeNavEventUPP (eventProc);
167 if (filterProc != NULL) {
168 ::DisposeNavObjectFilterUPP (filterProc);
175 Point where = {-1, -1};
177 static RoutineDescriptor dlgProcHook_ = BUILD_ROUTINE_DESCRIPTOR (uppDlgHookYDProcInfo, SFGetDlgHook);
178 RoutineDescriptor* dlgProcHook = &dlgProcHook_;
179 static RoutineDescriptor fileFilter_ = BUILD_ROUTINE_DESCRIPTOR (uppFileFilterYDProcInfo, SFFilterProc);
180 RoutineDescriptor* fileFilter = &fileFilter_;
182 DlgHookYDProcPtr dlgProcHook = &SFGetDlgHook;
183 FileFilterYDProcPtr fileFilter = &SFFilterProc;
185 StandardFileReply sfResult;
186 ::CustomGetFile (fileFilter, -1, NULL, &sfResult, 0, where, dlgProcHook, NULL, NULL, NULL,
this);
188 if (typeSpecified != NULL) {
189 *typeSpecified = (fCurPopupIdx != kBadIndex) and (fCurPopupIdx >= 4);
191 if (typeSpecified != NULL and *typeSpecified and typeIndex != NULL) {
192 *typeIndex = fCurPopupIdx - 4 + 0;
195 userPickGood = sfResult.sfGood;
197 *result = sfResult.sfFile;
202 UDesktop::Activate ();
207pascal
void FilteredSFGetDLog::StaticNavEventProc (NavEventCallbackMessage inSelector, NavCBRecPtr ioParams, NavCallBackUserData ioUserData)
209 Led_RequireNotNil (ioParams);
210 Led_RequireNotNil (ioUserData);
211 FilteredSFGetDLog* dlog =
reinterpret_cast<FilteredSFGetDLog*
> (ioUserData);
212 dlog->NavEventProc (inSelector, ioParams);
215void FilteredSFGetDLog::NavEventProc (NavEventCallbackMessage inSelector, NavCBRecPtr ioParams)
217 Led_RequireNotNil (ioParams);
219 switch (inSelector) {
220 case kNavCBCustomize: {
224 if (ioParams->customRect.right == 0 and ioParams->customRect.bottom == 0) {
225 ioParams->customRect.right = ioParams->customRect.left + 200;
226 ioParams->customRect.bottom = ioParams->customRect.top + 20;
234 Handle dlogItems = ::GetResource (
'DITL', kOpenDLOGAdditionItems_DialogID);
235 Led_ThrowIfOSErr (::NavCustomControl (fCurDialog, kNavCtlAddControlList, dlogItems));
236 ::ReleaseResource (dlogItems);
241 Led_ThrowIfOSErr (::NavCustomControl (fCurDialog, kNavCtlGetFirstControlID, &numItems));
242 fPopupDLGItemNumber = numItems + 1;
245 DialogRef dialog = ::GetDialogFromWindow (ioParams->window);
250 ::GetDialogItem (dialog, fPopupDLGItemNumber, &i, &h, &r);
251 MenuHandle mm = GetPopUpMenuHandle ((ControlHandle)h);
252 for (
size_t i = 0; i < fTypeSpecCount; ++i) {
254 tmp[0] = strlen (fTypeSpecs[i].fName);
255 memcpy (&tmp[1], fTypeSpecs[i].fName, tmp[0]);
256 AppendMenu (mm,
"\pHiMom");
257 SetMenuItemText (mm, ::CountMenuItems (mm), tmp);
259 ::SetControlMinimum ((ControlHandle)h, 1);
260 ::SetControlMaximum ((ControlHandle)h, i);
261 ::SetControlValue ((ControlHandle)h, 1);
265 if (ioParams->eventData.eventDataParms.event->what == mouseDown) {
266 DialogRef dialog = ::GetDialogFromWindow (ioParams->window);
270 ::GetDialogItem (dialog, fPopupDLGItemNumber, &i, &h, &r);
271 int newValue = ::GetControlValue ((ControlHandle)h);
272 if (newValue != fCurPopupIdx) {
273 fCurPopupIdx = newValue;
275 Led_ThrowIfOSErr (::NavCustomControl (fCurDialog, kNavCtlBrowserRedraw, NULL));
285pascal Boolean FilteredSFGetDLog::StaticNavObjectFilterProc (AEDesc* theItem,
void* info,
void* callBackUD, NavFilterModes filterMode)
287 Led_RequireNotNil (theItem);
288 Led_RequireNotNil (info);
289 Led_RequireNotNil (callBackUD);
290 FilteredSFGetDLog* dlog =
reinterpret_cast<FilteredSFGetDLog*
> (callBackUD);
291 return dlog->NavObjectFilterProc (theItem, info, filterMode);
294bool FilteredSFGetDLog::NavObjectFilterProc (AEDesc* theItem,
void* info, NavFilterModes )
296 Led_RequireNotNil (theItem);
297 Led_RequireNotNil (info);
299 if ((theItem->descriptorType == typeFSS) or (theItem->descriptorType == typeFSRef)) {
300 NavFileOrFolderInfo* fileOrFolderInfo =
reinterpret_cast<NavFileOrFolderInfo*
> (info);
301 if (fileOrFolderInfo->isFolder) {
306 OSType thisFileType = fileOrFolderInfo->fileAndFolder.fileInfo.finderInfo.fdType;
307 switch (fCurPopupIdx) {
310 for (
size_t i = 0; i < fTypeSpecCount; ++i) {
311 if (thisFileType == fTypeSpecs[i].fOSType) {
324 Led_Assert (fCurPopupIdx >= 4);
325 if (thisFileType == fTypeSpecs[fCurPopupIdx - 4].fOSType) {
336#if !qUseNavServices && !TARGET_CARBON
337pascal
short FilteredSFGetDLog::SFGetDlgHook (
short item, DialogPtr dialog,
void* myData)
339 FilteredSFGetDLog* sThis = (FilteredSFGetDLog*)myData;
344 if (item == sfHookFirstCall and sThis->fMainDialog == NULL) {
345 sThis->fMainDialog = dialog;
346 sThis->fPopupDLGItemNumber = Append_DITL (dialog, kOpenDLOGAdditionItems_DialogID);
350 ::GetDialogItem (dialog, sThis->fPopupDLGItemNumber, &i, &h, &r);
351 MenuHandle mm = GetPopUpMenuHandle ((ControlHandle)h);
352 for (
size_t i = 0; i < sThis->fTypeSpecCount; ++i) {
354 tmp[0] = strlen (sThis->fTypeSpecs[i].fName);
355 memcpy (&tmp[1], sThis->fTypeSpecs[i].fName, tmp[0]);
356 AppendMenu (mm,
"\pHiMom");
357 SetMenuItemText (mm, ::CountMenuItems (mm), tmp);
359 ::SetControlMinimum ((ControlHandle)h, 1);
360 ::SetControlMaximum ((ControlHandle)h, i);
361 ::SetControlValue ((ControlHandle)h, 1);
362 sThis->fCurPopupIdx = 1;
364 else if (sThis->fMainDialog == dialog) {
368 ::GetDialogItem (dialog, sThis->fPopupDLGItemNumber, &i, &h, &r);
369 int newValue = ::GetControlValue ((ControlHandle)h);
370 if (newValue != sThis->fCurPopupIdx) {
371 sThis->fCurPopupIdx = newValue;
372 return sfHookRebuildList;
379pascal Boolean FilteredSFGetDLog::SFFilterProc (CInfoPBPtr pb,
void* myData)
381 FilteredSFGetDLog* sThis = (FilteredSFGetDLog*)myData;
383 Led_AssertNotNil (pb);
386 if (pb->dirInfo.ioFlAttrib & ioDirMask) {
390 OSType thisFileType = pb->hFileInfo.ioFlFndrInfo.fdType;
391 bool filtered =
true;
392 switch (sThis->fCurPopupIdx) {
395 for (
size_t i = 0; i < sThis->fTypeSpecCount; ++i) {
396 if (thisFileType == sThis->fTypeSpecs[i].fOSType) {
409 if (thisFileType == sThis->fTypeSpecs[sThis->fCurPopupIdx - 4].fOSType) {
424FilteredSFPutDLog::FilteredSFPutDLog (
const TypeSpec* typeNameList,
size_t nTypes)
430 fTypeSpecs (typeNameList)
431 , fTypeSpecCount (nTypes)
432 , fCurPopupIdx (kBadIndex)
433 , fPopupDLGItemNumber (0)
434#if !qUseNavServices && !TARGET_CARBON
440bool FilteredSFPutDLog::PickFile (ConstStr255Param defaultName, FSSpec* result,
bool* replacing,
size_t* typeIndex)
442 Led_RequireNotNil (result);
443 Led_RequireNotNil (replacing);
445 bool userPickGood =
false;
447 if (typeIndex != NULL) {
448 fCurPopupIdx = *typeIndex - 0 + 1;
451 UDesktop::Deactivate ();
455 NavDialogCreationOptions options;
456 (void)::memset (&options, 0,
sizeof (options));
457 Led_ThrowIfOSStatus (::NavGetDefaultDialogCreationOptions (&options));
459 options.optionFlags |= kNavNoTypePopup;
460 options.optionFlags &= ~kNavAllowMultipleFiles;
461 options.optionFlags &= ~kNavAllowStationery;
462 options.optionFlags &= ~kNavAllowPreviews;
464 options.modality = kWindowModalityAppModal;
466 Led_SmallStackBuffer<OSType> osTypeBuf (fTypeSpecCount);
468 for (
size_t i = 0; i < fTypeSpecCount; ++i) {
469 osTypeBuf[i] = fTypeSpecs[i].fOSType;
473 NavEventUPP eventProc = NULL;
474 NavReplyRecord replyRec;
476 eventProc = ::NewNavEventUPP (StaticNavEventProc);
477 Led_AssertNotNil (eventProc);
479 options.saveFileName = ::CFStringCreateWithPascalString (NULL, defaultName, ::CFStringGetSystemEncoding ());
481 Led_Assert (fCurDialog == NULL);
482 Led_ThrowIfOSStatus (::NavCreatePutFileDialog (&options,
'TEXT', kApplicationSignature, eventProc,
this, &fCurDialog));
484 Led_ThrowIfOSStatus (::NavDialogRun (fCurDialog));
486 Led_ThrowIfOSStatus (::NavDialogGetReply (fCurDialog, &replyRec));
488 userPickGood = replyRec.validRecord;
490 *replacing = replyRec.replacing;
493 UExtractFromAEDesc::TheFSSpec (replyRec.selection, folderSpec);
502 ::CFStringGetPascalString (replyRec.saveFileName, tmpFileName, sizeof (tmpFileName), ::CFStringGetSystemEncoding ());
503 *result = CombineDirAndFileName (folderSpec, tmpFileName);
507 userPickGood =
false;
509 if (replyRec.validRecord) {
510 ::NavDisposeReply (&replyRec);
512 if (fCurDialog != NULL) {
513 ::NavDialogDispose (fCurDialog);
516 if (eventProc != NULL) {
517 ::DisposeNavEventUPP (eventProc);
525 ::GetIndString (saveAsPrompt, STRx_Standards, str_SaveAs);
527 Point where = {-1, -1};
529 static RoutineDescriptor dlgProcHook_ = BUILD_ROUTINE_DESCRIPTOR (uppDlgHookYDProcInfo, SFPutDlgHook);
530 RoutineDescriptor* dlgProcHook = &dlgProcHook_;
532 DlgHookYDProcPtr dlgProcHook = &SFPutDlgHook;
534 StandardFileReply sfResult;
535 ::CustomPutFile (saveAsPrompt, defaultName, &sfResult, 0, where, dlgProcHook, NULL, NULL, NULL,
this);
537 userPickGood = sfResult.sfGood;
539 *result = sfResult.sfFile;
540 *replacing = sfResult.sfReplacing;
545 UDesktop::Activate ();
547 if (typeIndex != NULL) {
548 *typeIndex = fCurPopupIdx - 1;
555pascal
void FilteredSFPutDLog::StaticNavEventProc (NavEventCallbackMessage inSelector, NavCBRecPtr ioParams, NavCallBackUserData ioUserData)
557 Led_RequireNotNil (ioParams);
558 Led_RequireNotNil (ioUserData);
559 FilteredSFPutDLog* dlog =
reinterpret_cast<FilteredSFPutDLog*
> (ioUserData);
560 dlog->NavEventProc (inSelector, ioParams);
563void FilteredSFPutDLog::NavEventProc (NavEventCallbackMessage inSelector, NavCBRecPtr ioParams)
565 Led_RequireNotNil (ioParams);
567 switch (inSelector) {
568 case kNavCBCustomize: {
572 if (ioParams->customRect.right == 0 and ioParams->customRect.bottom == 0) {
573 ioParams->customRect.right = ioParams->customRect.left + 200;
574 ioParams->customRect.bottom = ioParams->customRect.top + 20;
582 Handle dlogItems = ::GetResource (
'DITL', kSaveDLOGAdditionItems_DialogID);
583 Led_ThrowIfOSErr (::NavCustomControl (fCurDialog, kNavCtlAddControlList, dlogItems));
584 ::ReleaseResource (dlogItems);
589 Led_ThrowIfOSErr (::NavCustomControl (fCurDialog, kNavCtlGetFirstControlID, &numItems));
590 fPopupDLGItemNumber = numItems + 1;
593 DialogRef dialog = ::GetDialogFromWindow (ioParams->window);
598 ::GetDialogItem (dialog, fPopupDLGItemNumber, &i, &h, &r);
599 MenuHandle mm = GetPopUpMenuHandle ((ControlHandle)h);
600 for (
size_t i = 0; i < fTypeSpecCount; ++i) {
602 tmp[0] = strlen (fTypeSpecs[i].fName);
603 memcpy (&tmp[1], fTypeSpecs[i].fName, tmp[0]);
604 AppendMenu (mm,
"\pHiMom");
605 SetMenuItemText (mm, ::CountMenuItems (mm), tmp);
607 ::SetControlMinimum ((ControlHandle)h, 1);
608 ::SetControlMaximum ((ControlHandle)h, i);
609 ::SetControlValue ((ControlHandle)h, 1);
610 ::SetControlValue ((ControlHandle)h, (fCurPopupIdx == kBadIndex) ? 1 : fCurPopupIdx);
613 if (ioParams->eventData.eventDataParms.event->what == mouseDown) {
614 DialogRef dialog = ::GetDialogFromWindow (ioParams->window);
618 ::GetDialogItem (dialog, fPopupDLGItemNumber, &i, &h, &r);
619 int newValue = ::GetControlValue ((ControlHandle)h);
620 if (newValue != fCurPopupIdx) {
621 fCurPopupIdx = newValue;
623 Led_ThrowIfOSErr (::NavCustomControl (fCurDialog, kNavCtlBrowserRedraw, NULL));
634#if !qUseNavServices && !TARGET_CARBON
635pascal
short FilteredSFPutDLog::SFPutDlgHook (
short item, DialogPtr dialog,
void* myData)
637 FilteredSFPutDLog* sThis = (FilteredSFPutDLog*)myData;
642 if (item == sfHookFirstCall and sThis->fMainDialog == NULL) {
643 sThis->fMainDialog = dialog;
644 sThis->fPopupDLGItemNumber = Append_DITL (dialog, kSaveDLOGAdditionItems_DialogID);
648 ::GetDialogItem (dialog, sThis->fPopupDLGItemNumber, &i, &h, &r);
649 MenuHandle mm = GetPopUpMenuHandle ((ControlHandle)h);
650 for (
size_t i = 0; i < sThis->fTypeSpecCount; ++i) {
652 tmp[0] = strlen (sThis->fTypeSpecs[i].fName);
653 memcpy (&tmp[1], sThis->fTypeSpecs[i].fName, tmp[0]);
654 ::AppendMenu (mm,
"\pHiMom");
655 ::SetMenuItemText (mm, ::CountMenuItems (mm), tmp);
657 ::SetControlMinimum ((ControlHandle)h, 1);
658 ::SetControlMaximum ((ControlHandle)h, i);
659 ::SetControlValue ((ControlHandle)h, (sThis->fCurPopupIdx == kBadIndex) ? 1 : sThis->fCurPopupIdx);
661 else if (sThis->fMainDialog == dialog) {
665 ::GetDialogItem (dialog, sThis->fPopupDLGItemNumber, &i, &h, &r);
666 sThis->fCurPopupIdx = ::GetControlValue ((ControlHandle)h);
680 static int Append_DITL (DialogPtr dialog,
int item_list_ID)
682#if PRAGMA_ALIGN_SUPPORTED
683#pragma options align = mac68k
701 ItemList** append_item_list;
703 ItemList** dlg_item_list;
705 int new_items, data_size, i;
721 Led_AssertNotNil (dialog);
723 max_rect = ((DialogPeek)dialog)->window.port.portRect;
724 offset.v = max_rect.bottom;
726 max_rect.bottom -= 5;
729 dlg_item_list = (ItemList**)((DialogPeek)dialog)->items;
730 first_item = (**dlg_item_list).max_index + 2;
732 append_item_list = (ItemList**)GetResource (
'DITL', item_list_ID);
733 if (append_item_list == NULL)
736 HLock ((Handle)append_item_list);
737 new_items = (**append_item_list).max_index + 1;
745 item = (**append_item_list).items;
746 for (i = 0; i < new_items; ++i) {
747 OffsetRect (&item->bounds, offset.h, offset.v);
748 UnionRect (&item->bounds, &max_rect, &max_rect);
750 usb.bytes[1] = item->data[0];
752 switch (item->type & 0x7F) {
753 case ctrlItem + btnCtrl:
754 case ctrlItem + chkCtrl:
755 case ctrlItem + radCtrl:
756 item->handle = (Handle)NewControl ((DialogPtr)dialog, &item->bounds, (StringPtr)item->data,
true, 0, 0, 1, item->type & 0x03, 0);
759 case ctrlItem + resCtrl: {
760 item->handle = (Handle)GetNewControl (*(
short*)(item->data + 1), (DialogPtr)dialog);
761 (**(ControlHandle)item->handle).contrlRect = item->bounds;
766 err = PtrToHand (item->data + 1, &item->handle, usb.integer);
770 item->handle = GetIcon (*(
short*)(item->data + 1));
774 item->handle = (Handle)GetPicture (*(
short*)(item->data + 1));
781 data_size = (usb.integer + 1) & 0xFFFE;
782 item = (DialogItem*)((
char*)item + data_size +
sizeof (DialogItem));
785 err = PtrAndHand ((**append_item_list).items, (Handle)dlg_item_list, GetHandleSize ((Handle)append_item_list));
786 (**dlg_item_list).max_index += new_items;
787 HUnlock ((Handle)append_item_list);
788 ReleaseResource ((Handle)append_item_list);
790 max_rect.bottom += 5;
792 SizeWindow ((WindowPtr)dialog, max_rect.right, max_rect.bottom,
true);
795#if PRAGMA_ALIGN_SUPPORTED
796#pragma options align = reset