TweetFollow Us on Twitter

NonStandard File
Volume Number:7
Issue Number:4
Column Tag:Pascal Forum

Related Info: File Manager Standard File

Non-Standard File Dialogs

By Steven Sheets, Herndon, VA

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

Non-Standard File Unit

The SFGetFile and SFPutFile routines are two of the most commonly used calls in the Macintosh. All programmers need methods to select files (old or new ones) from inside their programs. Only old non-Mac programmers and users really appreciate how much Apple improved the user interface by standardizing this file selection process. However, Apple does not have a monopoly on good user interface ideas. Recently, newer programs have improved the Get and Put dialogs. While these new dialogs have the same functionality as the old ones, they have useful enhancements.

The code provided in this article shows how to create enhanced get and put dialogs. The unit NonStandardFile contains four procedures which demonstrate this. The program NonStandardFileTest shows how to use these routines.

NSPutFile()

The Non-Standard File Put procedure is the first routine provided in the Non-Standard File Unit. This procedure, and all other procedures explained in this article, are passed input parameters (passed by value) and return the output parameters (passed as VAR parameter). NSPutFile contains two input parameters (strings thePrompt and theOrigName) and 3 output parameters (boolean theGood, integer theRefNum and string theFileName). ThePrompt is the prompt that appears in the dialog, and theOrigName is the name that initially appears in the editable text field. If the user selects a file name (pressing the Save button or the return key), theGood flag returns TRUE, while the file name and the volume reference number is in theRefNum and theFileName parameters. If the user selects cancel, theGood returns FALSE.

This is the simplest example of using the SFPPutFile ROM call instead of the normal SFPutFile ROM call. I always find that the prompt portion of a normal SFPutFile is much too short to hold any meaningful information. The NSPutFile procedure provides an modified Put dialog, identical to a normal Put dialog, except the prompt text item is physically expanded (longer and 2 lines high). The routine does this by using a Dialog template resource and a Dialog Item List resource that are almost identical the the normal resources (stored at ID number -3999). The only difference in the resources is that the prompt field is larger. The SFPPutFile call that NSPutFile uses is passed the ID number of this modified dialog. Other than having a different layout, the dialog functions identical to the standard form. It is important to note that whenever a dialog item list is modified, all of the standard items are in the identical order (this is important for the SFPPutFile call). New items can be added to the end of the list (following calls are examples of this), but the original items must still exist.

NSSelectPutFile()

The Non-Standard Selection Put File procedure is the first example of a more intelligent Put dialog. This procedure places a Put dialog on the screen that contains, besides the normal features, 2 buttons to indicate if the user wants to save the entire document or only the selected portion of the document. The procedure is passed 3 input parameters (strings thePrompt, theSelectPrompt, theOrigName) and 4 output parameters (boolean theGood, integer theRefNum, string theFileName, Boolean theFlag). As before, theOrigName is the initial name of the file, while theGood flag returns TRUE if the user selects a file (with theRefNum and theFileName containing the volume reference number and file name selected). However, the routine passes 2 prompt strings, thePrompt and theSelectPrompt. How the button is set affects the appearance of the prompt. If the Document button is set, thePrompt string is displayed in the dialog. If the Selection button is set, theSelectPrompt string is displayed. If at any time, the user changes the button settings, the prompt also changes. If the user selects a file with the Selection button set, theFlag parameter returns TRUE. If he selected a file with the Document button set, theFlag returns FALSE. Having the Document button selected is the initial state of the dialog.

The NSSelectPutFile procedure is very useful when working with documents that can be saved as a whole or saved in portions. For example, a drawing program that allows the user to select various graphical objects on the screen could use this procedure. When the user selects Save from the menu, he can save the entire document, or he can save the selected drawing objects.

Similar to NSPutFile, NSSelectPutFile uses SFPPutFile ROM call in order to use a modified Dialog template and Dialog Item List. However, this list has additional items on it, namely the Document and Selection buttons. The SFPPutFile call also passes a dlogHook routine, NSSelectPutDlg. A dlogHook routine is called by the SFPPutFile call immediately after calling ModalDialog. The dlogHook routine is passed the item number returned by ModalDialog, as well as a pointer to the dialog record. All dlogHook routines (as well as File Filter routines and UserItem routines) need to be declared global to the unit.

The NSSelectPutDlg has two purposes. The first time it is called, the correct prompt is placed in the window and the Document and Selection buttons are set appropriately. After that, the routine scans item events to check if the user has selected either button. If he has, the new prompt is placed in the dialog and the buttons checked appropriately. Also, the item number is set to 100, indicating nothing else needs to be done for this event.

NSIconPutFile()

The Non-Standard Icon Put File procedure is one of the best new user interfaces I have seen on the Macintosh. This routine should be used in a program where a document can be saved as more than one file type. When this routine is used, the desktop icons of the file formats to which the document can be saved are shown.

NSIconPutFile allows up to 4 different file formats (icons). The parameters reflect this. NSIconPutFile is passed 14 input parameters (string theOrigName, integer theDefaultNum, handles theIcon1, theIcon2, theIcon3, theIcon4 and strings theName1, theName2, theName3, theName4, thePrompt1, thePrompt2, thePrompt3, and thePrompt4) and passed 4 output parameters (Boolean theGood, integer theRefNum, string theFileName, integer theNum). TheOrigName, theGood, theRefNum and theFileName are all used identically to the previously explained Non-Standard Put File calls. TheIcon parameters should contain up to 4 icon handles. Each handle should contain 256 byte of information of the ‘ICN#” resource format (32 bit by 32 bit image, 128 bytes of image, 128 bytes of mask). Usually, this is the actual ‘ICN#’ resource that is stored in the application (but it does not have to be). Passing NIL in one of the parameter handles indicates that a particular icon position is not used. For example, if only 3 icons need to be displayed, the last handle should be passed as NIL. TheDefaultNum parameter indicates which icon should be initially set. TheName strings are the titles of the icons (which will appear under the icon), while thePrompt strings are the prompt that will appear when that associated icon is selected. Usually the icon titles are the name of that file type (ie. Text, MacPaint, MacWrite), but this does not have to be the case.

Again imagine this routine is used by a graphic program, but in this case the program is a paint program. The document might be able to be saved as a MacPaint file, or as a StartUp Screen file or as some proprietary file format. Instead of using buttons, the user selects the format he wants by selecting the actual icon. He is used to seeing this icon on the desktop, and associating it with that type of file.

NSIconPutFile uses a number of hooks to function. First the routine calls SFPPutFile in order to use a Dialog template and Dialog item list that have 6 new UserItems on it. Like NSSelectPutFile, NSIconPutFile has a dlogHook routine, NSIconPutDlg. The first time through, NSIconPutDlg sets the prompt and sets the UserItem routine of the 4 new dialog items to NSIconItem. A UserItem routine is a graphic routine that draws some special user interface in a dialog. In this case, NSIconItem draws the 4 icons, with titles and hiliting. NSIconPutDlg handles the mouse down events on the icon. Selecting a previously unselected icon activates the icon, which consists of unhiliting old icon, hiliting new one and setting new prompt.

NSGetFile()

The Non Standard Get File is an example of a modification of the Get File Dialog. This routine should be used in applications that can open 2 or more different types of documents. NSGetFile displays a Get File dialog that contains, along with the normal features, a Popup menu that indicates what file types the routine is currently viewing. The default setting is all documents; all documents of the types passed to the routine will be shown in the dialog. However, the user can select the Popup menu and change the settings so that only 1 type can be viewed.

NSGetFile is passed 4 input parameters (string thePrompt, integer theNumTypes, pointers theTypeListPtr and theNameListPtr) and passes back 4 output parameters (Boolean theGood, integer theRefNum, string theFileName, OStype theType).

This routine is written slightly differently than the NSPutFile procedures. NSGetFile was written so that there is no upper limit to the number of different file types that can be viewed by the dialog. Instead of passing the individual file types and file type name as parameters to the routine, all the file types and all the file names are stored in an array before NSGetFile is called. Then pointers to these two arrays are passed to NSGetFile as parameters. TheNumTypes parameter is the number of different file types the routine can display in the dialog. ThePrompt is the prompt that is displayed on the dialog.

If the user selects a file, theGood is returned TRUE. In this case, theRefNum contains the volume reference number, theFileName contains the file’s name, and theType returns the file’s OStype. If the user selects cancel, theGood returns FALSE.

Just as SFPPutfile ROM call is an variation of the SFPutfile call, there is a SFPGetFile ROM call that provides expanded functionality in comparison to the normal SFGetFile call. In NSGetFile, the SFPGetFile call is passed the ID number of a Dialog template resource and Dialog item list resource that is almost identical to the standard SFGetFile resources (stored at ID -4000). The modified resources contain a text item (for the prompt) and an UserItem (for the Popup menu). The SFPGetFile call is also passed a Dialog hook routine, NSGetDlg. As in the previous examples, the first thing NSGetDlg does is set the prompt and set the UserItem to the NSPopUpItem procedure. NSPopUpItem displays the graphics for a Popup menu. NSGetDlg also takes care of handling the Popup (using call to PopUpMenuSelect) when a user selects the item. The SFPGetFile call is also passed a File Filter routine, NSGetFileFilter. NSGetFileFilter decides which files are displayed in the dialog. Depending on the setting of the Popup menu, the routine either allows only a single type of file to be viewed, or it allows all the types of files it knows about to be viewed. Notice that if a user selects a new setting on the Popup menu, NSGetDlg sets the event item number to 101. This tells the SFPGetFile ROM call to redraw the dialog from scratch, which it does using the NGSGetFileFilter (possibly displaying a new group of files).

Beyond

Hopefully these routines should be easy to modify for your own use. NSIconPutFile could be rewritten to handle more than 4 file types. NSGetFile could be modified to use a simpler parameter method when you know exactly which file types your program can open. NSGetFile could also be modified to use icons instead of a Popup menu. The application I wrote NSGetFile for could read a variable number of file types (depending on configuration of program) that had no upper limits.

All routines could be rewritten so as not to use so much global parameter data. Instead, the global type of data could be stored in a temporary handle. As the start of the routine, the handle is allocated, and the values plugged in. Then this handle is stored in the reference value of the dialog (remember a dialog is a window). This is a location that all the dlogHook, fileFilter and UserItem routines can access. Just before the main routine is done, the handle can be disposed of.

While this method does use less global space, for simplicity and ease of understanding, I stuck with global variables. If you were to use the routine with something that does not have global variables (FKEYs, Drivers, DAs), you might have to use that method.

If anyone comes up with other interesting user interfaces, I would love to see them. I can be contacted on Applelink (SHEETS1) or America Online (Mage Steve).

Listing:  NonStandardFile.p

{****************************}
{}
{Non-Standard File Unit}
{Created by Steve Sheets}
{}
{Provides 4 different new user interfaces for}
{the Get & Put dialogs.}
{}
{****************************}

unit NonStandardFile;

interface

 type
 SFTypeListPtr = ^SFTypeList;

 StrArray = array[1..1] of Str255;
 StrArrayPtr = ^StrArray;

{Four new Put & Get File Routines}
 procedure NSPutFile (thePrompt, theOrigName: Str255;
 var theGood: BOOLEAN;
 var theRefNum: INTEGER;
 var theFileName: Str255);

 procedure NSSelectPutFile (thePrompt, theSelectPrompt, theOrigName: 
Str255;
 var theGood: BOOLEAN;
 var theRefNum: INTEGER;
 var theFileName: Str255;
 var theFlag: BOOLEAN);

 procedure NSIconPutFile (theOrigName: Str255;
 theDefaultNum: INTEGER;
 theIcon1, theIcon2, theIcon3, theIcon4: Handle;
 theName1, theName2, theName3, theName4: Str255;
 thePrompt1, thePrompt2, 
 thePrompt3, thePrompt4: Str255;
 var theGood: BOOLEAN;
 var theRefNum: INTEGER;
 var theFileName: Str255;
 var theNum: INTEGER);

 procedure NSGetFile (thePrompt: Str255;
 theNumTypes: INTEGER;
 theTypeListPtr: SFTypeListPtr;
 theNameListPtr: StrArrayPtr;
 var theGood: BOOLEAN;
 var theRefNum: INTEGER;
 var theFileName: Str255;
 var theType: OSType);

{************************************}
{External references to these procedures.}
{Do not call them outside this unit}

 function NSSelectPutDlg (item: INTEGER;
 theDialog: DialogPtr): INTEGER;

 procedure NSIconItem (theWindow: WindowPtr;
 itemNo: INTEGER);

 function NSIconPutDlg (item: INTEGER;
 theDialog: DialogPtr): INTEGER;

 procedure NSPopUpItem (theWindow: WindowPtr;
 itemNo: INTEGER);

 function NSGetFileFilter (paramBlock: ParmBlkPtr): BOOLEAN;

 function NSGetDlg (item: INTEGER;
 theDialog: DialogPtr): INTEGER;

implementation
 const
 kNSGetID = 500;
 kNSPutID = 501;
 kNSSelectPutID = 502;
 kNSIconPutID = 503;

 kGetPopUpID = 254;
 kGetPopUpItem = 11;
 kGetPopUpPrompt = 12;

 kPutPrompt = 3;
 kPutNoSelectSwitch = 9;
 kPutSelectSwitch = 10;
 kPutIcon1 = 9;

 kMaxIcons = 4;

 type
 IconStrPtrArray = array[1..kMaxIcons] of StringPtr;

 var
 gNSCurNum, gNSMaxNum: INTEGER;
 gNSTypeListPtr: SFTypeListPtr;
 gNSPromptListPtr: IconStrPtrArray;
 gNSNameListPtr: IconStrPtrArray;
 gNSFirst, gNSSelect: BOOLEAN;
 gNSMenuHdl: MenuHandle;
 gNSBoxs: array[1..kMaxIcons] of Rect;
 gNSIcons: array[1..kMaxIcons] of Handle;
 gNSPrompt, gNSAltPrompt: Str255;

{************************************}

{NSPutFile routines}
 procedure NSPutFile (thePrompt, theOrigName: Str255;
 var theGood: BOOLEAN;
 var theRefNum: INTEGER;
 var theFileName: Str255);
 var
 tempPt: Point;
 tempReply: SFReply;
 begin
 tempPt.v := 40;
 tempPt.h := 60;
 theGood := FALSE;

 SFPPutFile(tempPt, thePrompt, theOrigName, nil, tempReply, kNSPutID, 
nil);

 with tempReply do
 if good then
 begin
 theGood := TRUE;
 theRefNum := vRefNum;
 theFileName := fName;
 end;
 end;

{************************************}
{NSSelectPutFile routines}
 function NSSelectPutDlg (item: INTEGER;
 theDialog: DialogPtr): INTEGER;

 procedure SetPrompt;
 var
 tempNum, tempV1, tempV2: INTEGER;
 tempHdl: Handle;
 tempRect: Rect;
 begin
 GetDItem(theDialog, kPutPrompt, tempNum, tempHdl, tempRect);
 if tempHdl <> nil then
 begin
 if gNSSelect then
 SetIText(tempHdl, gNSAltPrompt)
 else
 SetIText(tempHdl, gNSPrompt);
 end;

 if gNSSelect then
 begin
 tempV1 := 0;
 tempV2 := 1;
 end
 else
 begin
 tempV1 := 1;
 tempV2 := 0;
 end;

 GetDItem(theDialog, kPutNoSelectSwitch, tempNum, tempHdl, tempRect);
 if tempHdl <> nil then
 SetCtlValue(ControlHandle(tempHdl), tempV1);
 GetDItem(theDialog, kPutSelectSwitch, tempNum, tempHdl, tempRect);
 if tempHdl <> nil then
 SetCtlValue(ControlHandle(tempHdl), tempV2);
 end;

 begin
 if gNSFirst then
 begin
 SetPrompt;
 gNSFirst := FALSE;
 end;

 if item = kPutSelectSwitch then
 begin
 gNSSelect := TRUE;
 SetPrompt;
 item := 100;
 end
 else if item = kPutNoSelectSwitch then
 begin
 gNSSelect := FALSE;
 SetPrompt;
 item := 100;
 end;

 NSSelectPutDlg := item;
 end;

 procedure NSSelectPutFile (thePrompt, theSelectPrompt, theOrigName: 
Str255;
 var theGood: BOOLEAN;
 var theRefNum: INTEGER;
 var theFileName: Str255;
 var theFlag: BOOLEAN);
 var
 tempPt: Point;
 tempReply: SFReply;
 begin
 theGood := FALSE;

 tempPt.v := 40;
 tempPt.h := 60;

 gNSFirst := TRUE;
 gNSSelect := FALSE;
 gNSPrompt := thePrompt;
 gNSAltPrompt := theSelectPrompt;
 SFPPutFile(tempPt, thePrompt, theOrigName, @NSSelectPutDlg, tempReply, 
kNSSelectPutID, nil);

 with tempReply do
 if good then
 begin
 theGood := TRUE;
 theRefNum := vRefNum;
 theFileName := fName;
 theFlag := gNSSelect;
 end;
 end;

{************************************}
{NSIconPutFile routines}
 procedure DrawNSIcon (theNum: INTEGER;
 theHiliteFlag: BOOLEAN);
 var
 tempBitMap: BitMap;
 tempPort: GrafPtr;
 tempRect, tempRect2: Rect;
 tempFont, tempSize, tempLen, tempCenter: INTEGER;
 begin
 if (theNum > 0) and (theNum <= kMaxIcons) then
 if gNSIcons[theNum] <> nil then
 begin
 GetPort(tempPort);

 with gNSBoxs[theNum] do
 begin
 tempCenter := ((right + left) div 2);
 tempRect.top := top;
 tempRect.bottom := top + 32;
 tempRect.left := tempCenter - 16;
 tempRect.right := tempRect.left + 32;
 end;

 PlotIcon(tempRect, gNSIcons[theNum]);

 if gNSNameListPtr[theNum]^ <> ‘’ then
 begin
 tempFont := tempPort^.txFont;
 tempSize := tempPort^.txSize;

 TextFont(1);
 TextSize(10);

 tempLen := StringWidth(gNSNameListPtr[theNum]^);
 with gNSBoxs[theNum] do
 begin
 tempRect2.top := bottom - 14;
 tempRect2.bottom := bottom;
 tempRect2.left := tempCenter - (tempLen div 2) - 4;
 tempRect2.right := tempRect2.left + tempLen + 8;
 end;

 TextBox(POINTER(@gNSNameListPtr[theNum]^[1]), Length(gNSNameListPtr[theNum]^), 
tempRect2, teJustCenter);

 TextFont(tempFont);
 TextSize(tempSize);
 end;

 if theHiliteFlag then
 begin
 Hlock(gNSIcons[theNum]);
 tempBitMap.baseaddr := POINTER(ORD4(gNSIcons[theNum]^) + $80);
 tempBitMap.rowbytes := 4;
 SetRect(tempBitMap.bounds, 0, 0, 32, 32);

 BitClr(Ptr($938), 0);
 CopyBits(tempBitMap, tempPort^.portBits, tempBitMap.bounds, tempRect, 
srcXor, nil);

 HUnlock(gNSIcons[theNum]);

 if gNSNameListPtr[theNum]^ <> ‘’ then
 begin
 BitClr(Ptr($938), 0);
 InvertRect(tempRect2);
 end;
 end;
 end;
 end;

 procedure NSIconItem (theWindow: WindowPtr;
 itemNo: INTEGER);
 begin
 itemNo := itemNo - kPutIcon1 + 1;
 if (itemNo >= 1) and (itemNo <= kMaxIcons) then
 DrawNSIcon(itemNo, itemNo = gNSCurNum);
 end;

 function NSIconPutDlg (item: INTEGER;
 theDialog: DialogPtr): INTEGER;
 var
 tempNum, tempCount: INTEGER;
 tempHdl: Handle;
 tempRect: Rect;

 procedure SetPrompt;
 begin
 GetDItem(theDialog, kPutPrompt, tempNum, tempHdl, tempRect);
 if tempHdl <> nil then
 SetIText(tempHdl, gNSPromptListPtr[gNSCurNum]^);
 end;

 begin
 if gNSFirst then
 begin
 SetPrompt;

 for tempCount := 1 to kMaxIcons do
 begin
 GetDItem(theDialog, tempCount - 1 + kPutIcon1, tempNum, tempHdl, gNSBoxs[tempCount]);
 tempHdl := @NSIconItem;
 SetDItem(theDialog, tempCount - 1 + kPutIcon1, tempNum, tempHdl, gNSBoxs[tempCount]);
 end;

 gNSFirst := FALSE;
 end;

 tempNum := item - kPutIcon1 + 1;
 if (tempNum >= 1) and (tempNum <= kMaxIcons) then
 begin
 item := 100;
 if (gNSIcons[tempNum] <> nil) and (tempNum <> gNSCurNum) then
 begin
 DrawNSIcon(gNSCurNum, FALSE);
 DrawNSIcon(tempNum, TRUE);
 gNSCurNum := tempNum;
 SetPrompt;
 end;
 end;

 NSIconPutDlg := item;
 end;

 procedure NSIconPutFile (theOrigName: Str255;
 theDefaultNum: INTEGER;
 theIcon1, theIcon2, theIcon3, theIcon4: Handle;
 theName1, theName2, theName3, theName4: Str255;
 thePrompt1, thePrompt2, thePrompt3, thePrompt4: Str255;
 var theGood: BOOLEAN;
 var theRefNum: INTEGER;
 var theFileName: Str255;
 var theNum: INTEGER);
 var
 tempPt: Point;
 tempReply: SFReply;
 begin
 theGood := FALSE;

 if (theDefaultNum >= 1) and (theDefaultNum <= kMaxIcons) then
 begin
 tempPt.v := 40;
 tempPt.h := 60;

 gNSFirst := TRUE;
 gNSCurNum := theDefaultNum;
 gNSNameListPtr[1] := @theName1;
 gNSNameListPtr[2] := @theName2;
 gNSNameListPtr[3] := @theName3;
 gNSNameListPtr[4] := @theName4;
 gNSPromptListPtr[1] := @thePrompt1;
 gNSPromptListPtr[2] := @thePrompt2;
 gNSPromptListPtr[3] := @thePrompt3;
 gNSPromptListPtr[4] := @thePrompt4;
 gNSIcons[1] := theIcon1;
 gNSIcons[2] := theIcon2;
 gNSIcons[3] := theIcon3;
 gNSIcons[4] := theIcon4;

 SFPPutFile(tempPt, ‘’, theOrigName, @NSIconPutDlg, tempReply, kNSIconPutID, 
nil);

 with tempReply do
 if good then
 begin
 theGood := TRUE;
 theRefNum := vRefNum;
 theFileName := fName;
 theNum := gNSCurNum;
 end;
 end;
 end;

{************************************}
{NSGetFile routines}
 procedure DrawNSPopup;
 var
 tempStr: Str255;
 begin
 FrameRect(gNSBoxs[1]);
 MoveTo(gNSBoxs[1].left, gNSBoxs[1].bottom);
 LineTo(gNSBoxs[1].right, gNSBoxs[1].bottom);
 LineTo(gNSBoxs[1].right, gNSBoxs[1].top);

 MoveTo(gNSBoxs[1].left + 4, gNSBoxs[1].bottom - 6);
 if gNSCurNum = 0 then
 DrawString(‘All Files’)
 else
 begin
 GetItem(gNSMenuHdl, gNSCurNum + 2, tempStr);
 DrawString(tempStr);
 end;
 end;

 procedure NSPopUpItem (theWindow: WindowPtr;
 itemNo: INTEGER);
 begin
 if itemNo = kGetPopUpItem then
 DrawNSPopup;
 end;

 function NSGetFileFilter (paramBlock: ParmBlkPtr): BOOLEAN;
 var
 tempFlag: BOOLEAN;
 tempType: OSType;
 tempCount: INTEGER;
 begin
 tempFlag := TRUE;

 tempType := paramBlock^.ioFlFndrInfo.fdType;
 if gNSCurNum = 0 then
 begin
 for tempCount := 0 to gNSMaxNum - 1 do
 if tempFlag then
 if gNSTypeListPtr^[tempCount] = tempType then
 tempFlag := FALSE;
 end
 else
 begin
 if gNSTypeListPtr^[gNSCurNum - 1] = tempType then
 tempFlag := FALSE;
 end;

 NSGetFileFilter := tempFlag;
 end;

 function NSGetDlg (item: INTEGER;
 theDialog: DialogPtr): INTEGER;
 var
 tempType: INTEGER;
 tempHdl: Handle;
 tempNum, tempNewNum: INTEGER;
 tempLong: LongInt;
 tempRect: Rect;
 tempPt: Point;

 begin
 if gNSFirst then
 begin
 GetDItem(theDialog, kGetPopUpPrompt, tempNum, tempHdl, tempRect);
 if tempHdl <> nil then
 SetIText(tempHdl, gNSPrompt);

 GetDItem(theDialog, kGetPopUpItem, tempType, tempHdl, gNSBoxs[1]);
 tempHdl := @NSPopUpItem;
 SetDItem(theDialog, kGetPopUpItem, tempType, tempHdl, gNSBoxs[1]);
 with gNSBoxs[1] do
 begin
 bottom := bottom - 1;
 right := right - 1;
 end;
 gNSFirst := FALSE;
 end;

 if item = kGetPopUpItem then
 begin
 if gNSCurNum = 0 then
 tempNum := 1
 else
 tempNum := gNSCurNum + 2;

 CheckItem(gNSMenuHdl, tempNum, TRUE);
 InsertMenu(gNSMenuHdl, -1);
 tempPt := gNSBoxs[1].topleft;
 LocalToGlobal(tempPt);
 BitClr(Ptr($938), 0);
 InvertRect(gNSBoxs[1]);
 tempLong := PopUpMenuSelect(gNSMenuHdl, tempPt.v, tempPt.h, tempNum);
 BitClr(Ptr($938), 0);
 InvertRect(gNSBoxs[1]);
 DeleteMenu(kGetPopUpID);
 CheckItem(gNSMenuHdl, tempNum, FALSE);

 if tempLong <> 0 then
 begin
 tempNewNum := LoWord(tempLong);
 if tempNewNum <> tempNum then
 begin
 if tempNewNum = 1 then
 gNSCurNum := 0
 else
 gNSCurNum := tempNewNum - 2;

 item := 101;
 EraseRect(gNSBoxs[1]);
 DrawNSPopup;
 end;
 end;
 end;

 NSGetDlg := item;
 end;

 procedure NSGetFile (thePrompt: Str255;
 theNumTypes: INTEGER;
 theTypeListPtr: SFTypeListPtr;
 theNameListPtr: StrArrayPtr;
 var theGood: BOOLEAN;
 var theRefNum: INTEGER;
 var theFileName: Str255;
 var theType: OSType);
 var
 tempPt: Point;
 tempReply: SFReply;
 tempCount: INTEGER;
 begin
 theGood := FALSE;
 theRefNum := -1;
 theFileName := ‘’;
 theType := ‘    ‘;

 if (theNumTypes > 0) and (theTypeListPtr <> nil) then
 begin
 gNSCurNum := 0;
 gNSMaxNum := theNumTypes;
 gNSTypeListPtr := theTypeListPtr;
 gNSPrompt := thePrompt;
 gNSFirst := TRUE;
 gNSMenuHdl := NewMenu(kGetPopUpID, ‘NS’);
 AppendMenu(gNSMenuHdl, ‘All Files;(-’);
 for tempCount := 1 to theNumTypes do
 AppendMenu(gNSMenuHdl, theNameListPtr^[tempCount]);

 tempPt.v := 40;
 tempPt.h := 60;
 SFPGetFile(tempPt, ‘’, @NSGetFileFilter, theNumTypes, theTypeListPtr^, 
@NSGetDlg, tempReply, kNSGetID, nil);

 DisposeMenu(gNSMenuHdl);

 with tempReply do
 if good then
 begin
 theGood := TRUE;
 theRefNum := vRefNum;
 theFileName := fName;
 theType := fType;
 end
 end;
 end;
end.
Listing NonStandardFileTest.p

{****************************}
{}
{Non-Standard File Test}
{Created by Steve Sheets}
{}
{Examples of using NonStandardFile unit.}
{}
{****************************}

program NonStandardFileTest;
 uses
 NonStandardFile;
 var
 gGood: BOOLEAN;
 gRefNum: INTEGER;
 gFileName: Str255;
 gType: OSType;
 gTypeList: SFTypeList;
 gNameList: array[0..1] of Str255;
 gFlag: BOOLEAN;
 gNum: INTEGER;
 gIcon1, gIcon2, gIcon3: Handle;
begin
 NSPutFile(‘Please enter the name of the file you wish to save:’, ‘File 
Name’, gGood, gRefNum, gFileName);

 NSSelectPutFile(‘Save copy of Document to disk:’, ‘Save copy of Selection 
to disk:’, ‘File Name’, gGood, gRefNum, gFileName, gFlag);

 gTypeList[0] := ‘TEXT’;
 gNameList[0] := ‘Text files’;
 gTypeList[1] := ‘PNTG’;
 gNameList[1] := ‘MacPaint files’;
 NSGetFile(‘Please select a file:’, 2, @gTypeList, @gNameList, gGood, 
gRefNum, gFileName, gType);

 gIcon1 := GetResource(‘ICN#’, 1000);
 gIcon2 := GetResource(‘ICN#’, 1001);
 gIcon3 := GetResource(‘ICN#’, 1002);
 NSIconPutFile(‘Name’, 1, gIcon1, gIcon2, gIcon3, nil, ‘MacPaint’, ‘Text’, 
‘PICT’, ‘’, ‘Save copy file to MacPaint document:’, ‘Save file as Text 
document:’, ‘Save copy file to PICT document:’, ‘’, gGood, gRefNum, gFileName, 
gNum);
 ReleaseResource(gIcon1);
 ReleaseResource(gIcon2);
 ReleaseResource(gIcon3);
end.
Listing:  NonStandardFile.r

/*--------------------------------------------------------
#
#Non-Standard File Resources
#Created by Steve Sheets
#
#Provides 4 different new user interfaces for
#the Get & Put dialogs.
#
#This resource file contains resource needed
#for the Unit as well as the resources needed
#for the test program, Non-Standard File Test.
#
#Compile this file into resource file with command:
#
#Rez ‘NonStandard File.r’ -o ‘NonStandard File Resources’
#
----------------------------------------------------------*/

#include “Types.r”

/* Dialog Template & Dialog item list resources */
/* required for the Unit. */

resource ‘DLOG’ (500, purgeable) {
 {0, 0, 256, 348},
 dBoxProc,
 invisible,
 noGoAway,
 0x0,
 500,
 “”
};

resource ‘DLOG’ (501, purgeable) {
 {0, 0, 200, 304},
 dBoxProc,
 invisible,
 noGoAway,
 0x0,
 501,
 “”
};

resource ‘DLOG’ (502, purgeable) {
 {0, 0, 220, 304},
 dBoxProc,
 invisible,
 noGoAway,
 0x0,
 502,
 “”
};

resource ‘DLOG’ (503, purgeable) {
 {0, 0, 268, 304},
 dBoxProc,
 invisible,
 noGoAway,
 0x0,
 503,
 “”
};

resource ‘DITL’ (500, purgeable) {
 { /* array DITLarray: 13 elements */
 /* [1] */
 {138, 256, 156, 336},
 Button {
 enabled,
 “Open”
 },
 /* [2] */
 {0, 699, 80, 717},
 Button {
 enabled,
 “Hidden”
 },
 /* [3] */
 {163, 256, 181, 336},
 Button {
 enabled,
 “Cancel”
 },
 /* [4] */
 {39, 232, 59, 347},
 UserItem {
 disabled
 },
 /* [5] */
 {68, 256, 86, 336},
 Button {
 enabled,
 “Eject”
 },
 /* [6] */
 {93, 256, 111, 336},
 Button {
 enabled,
 “Drive”
 },
 /* [7] */
 {39, 12, 185, 230},
 UserItem {
 enabled
 },
 /* [8] */
 {39, 229, 185, 246},
 UserItem {
 enabled
 },
 /* [9] */
 {124, 252, 125, 340},
 UserItem {
 disabled
 },
 /* [10] */
 {0, 660, 101, 756},
 StaticText {
 disabled,
 “”
 },
 /* [11] */
 {227, 62, 247, 246},
 UserItem {
 enabled
 },
 /* [12] */
 {200, 12, 218, 336},
 StaticText {
 disabled,
 “”
 },
 /* [13] */
 {227, 12, 247, 61},
 StaticText {
 disabled,
 “Show:”
 }
 }
};

resource ‘DITL’ (501, purgeable) {
 { /* array DITLarray: 8 elements */
 /* [1] */
 {132, 218, 150, 288},
 Button {
 enabled,
 “Save”
 },
 /* [2] */
 {158, 218, 176, 288},
 Button {
 enabled,
 “Cancel”
 },
 /* [3] */
 {136, 14, 168, 197},
 StaticText {
 disabled,
 “Save as:”
 },
 /* [4] */
 {29, 198, 49, 302},
 UserItem {
 disabled
 },
 /* [5] */
 {56, 218, 74, 288},
 Button {
 enabled,
 “Eject”
 },
 /* [6] */
 {82, 218, 100, 288},
 Button {
 enabled,
 “Drive”
 },
 /* [7] */
 {173, 17, 189, 194},
 EditText {
 enabled,
 “”
 },
 /* [8] */
 {29, 14, 127, 197},
 UserItem {
 disabled
 }
 }
};

resource ‘DITL’ (502, purgeable) {
 { /* array DITLarray: 10 elements */
 /* [1] */
 {132, 218, 150, 288},
 Button {
 enabled,
 “Save”
 },
 /* [2] */
 {158, 218, 176, 288},
 Button {
 enabled,
 “Cancel”
 },
 /* [3] */
 {136, 14, 168, 197},
 StaticText {
 disabled,
 “Save as:”
 },
 /* [4] */
 {29, 198, 49, 302},
 UserItem {
 disabled
 },
 /* [5] */
 {56, 218, 74, 288},
 Button {
 enabled,
 “Eject”
 },
 /* [6] */
 {82, 218, 100, 288},
 Button {
 enabled,
 “Drive”
 },
 /* [7] */
 {173, 17, 189, 194},
 EditText {
 enabled,
 “”
 },
 /* [8] */
 {29, 14, 127, 197},
 UserItem {
 disabled
 },
 /* [9] */
 {199, 17, 217, 103},
 RadioButton {
 enabled,
 “Document”
 },
 /* [10] */
 {199, 113, 217, 194},
 RadioButton {
 enabled,
 “Selection”
 }
 }
};

resource ‘DITL’ (503, purgeable) {
 { /* array DITLarray: 12 elements */
 /* [1] */
 {132, 218, 150, 288},
 Button {
 enabled,
 “Save”
 },
 /* [2] */
 {158, 218, 176, 288},
 Button {
 enabled,
 “Cancel”
 },
 /* [3] */
 {136, 14, 168, 197},
 StaticText {
 disabled,
 “Save as:”
 },
 /* [4] */
 {29, 198, 49, 302},
 UserItem {
 disabled
 },
 /* [5] */
 {56, 218, 74, 288},
 Button {
 enabled,
 “Eject”
 },
 /* [6] */
 {82, 218, 100, 288},
 Button {
 enabled,
 “Drive”
 },
 /* [7] */
 {173, 17, 189, 194},
 EditText {
 enabled,
 “”
 },
 /* [8] */
 {29, 14, 127, 197},
 UserItem {
 disabled
 },
 /* [9] */
 {209, 10, 258, 81},
 UserItem {
 enabled
 },
 /* [10] */
 {209, 81, 258, 152},
 UserItem {
 enabled
 },
 /* [11] */
 {209, 152, 258, 223},
 UserItem {
 enabled
 },
 /* [12] */
 {209, 223, 258, 294},
 UserItem {
 enabled
 }
 }
};

/* Icon resources (MacPaint, Text & PICT) used in */
/* the Test program with the NSGetFile call. */

resource ‘ICN#’ (1002) {
 { /* array: 2 elements */
 /* [1] */
 $”0F FF FE 00 08 00 03 00 08 00 02 80 08 00 02 40"
 $”08 00 02 20 08 00 02 10 08 7F C3 F8 08 40 40 08"
 $”08 40 40 08 08 40 40 08 08 40 40 08 08 40 78 08"
 $”08 41 04 08 08 42 02 08 08 7C 01 08 08 04 01 08"
 $”08 04 01 08 08 04 01 08 08 02 02 08 08 01 04 08"
 $”08 00 F8 08 08 00 00 08 08 04 00 08 08 0A 00 08"
 $”08 11 00 08 08 20 80 08 08 40 40 08 08 80 20 08"
 $”09 FF F0 08 08 00 00 08 08 00 00 08 0F FF FF F8",
 /* [2] */
 $”0F FF FE 00 0F FF FF 00 0F FF FF 80 0F FF FF C0"
 $”0F FF FF E0 0F FF FF F0 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 }
};

resource ‘ICN#’ (1001) {
 { /* array: 2 elements */
 /* [1] */
 $”0F FF FC 00 08 00 06 00 08 00 05 00 08 00 04 80"
 $”08 F8 04 40 08 00 04 20 08 1F E7 F0 08 00 00 10"
 $”08 1F E0 10 08 00 00 10 08 03 FC 10 08 00 00 10"
 $”08 1F 00 10 08 00 00 10 08 1F FE 10 08 00 00 10"
 $”08 FF E0 10 08 00 00 10 08 3C 00 10 08 00 00 10"
 $”08 0F C0 10 08 00 00 10 08 0F F8 10 08 00 00 10"
 $”08 FC 00 10 08 00 00 10 08 3F E0 10 08 00 00 10"
 $”08 07 FE 10 08 00 00 10 08 00 00 10 0F FF FF F0",
 /* [2] */
 $”0F FF FC 00 0F FF FE 00 0F FF FF 00 0F FF FF 80"
 $”0F FF FF C0 0F FF FF E0 0F FF FF F0 0F FF FF F0"
 $”0F FF FF F0 0F FF FF F0 0F FF FF F0 0F FF FF F0"
 $”0F FF FF F0 0F FF FF F0 0F FF FF F0 0F FF FF F0"
 $”0F FF FF F0 0F FF FF F0 0F FF FF F0 0F FF FF F0"
 $”0F FF FF F0 0F FF FF F0 0F FF FF F0 0F FF FF F0"
 $”0F FF FF F0 0F FF FF F0 0F FF FF F0 0F FF FF F0"
 $”0F FF FF F0 0F FF FF F0 0F FF FF F0 0F FF FF F0"
 }
};

resource ‘ICN#’ (1000) {
 { /* array: 2 elements */
 /* [1] */
 $”0F FF FE 00 08 00 03 00 09 D0 02 80 09 D0 02 40"
 $”09 D0 02 20 09 D0 02 10 09 D0 03 F8 09 D0 00 08"
 $”09 D0 00 08 09 D0 00 08 09 D0 00 08 09 D0 00 08"
 $”09 F0 00 08 09 10 00 08 09 10 00 08 09 10 00 08"
 $”09 10 00 08 09 10 00 08 08 E0 00 08 09 F0 00 08"
 $”09 F0 00 08 09 F8 00 08 09 F8 00 08 09 E8 5F E8"
 $”09 F8 0B E8 08 D0 3F E8 08 F0 FF E8 08 70 3F E8"
 $”08 19 FF E8 08 00 00 08 08 00 00 08 0F FF FF F8",
 /* [2] */
 $”0F FF FE 00 0F FF FF 00 0F FF FF 80 0F FF FF C0"
 $”0F FF FF E0 0F FF FF F0 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 $”0F FF FF F8 0F FF FF F8 0F FF FF F8 0F FF FF F8"
 }
};

 
AAPL
$105.22
Apple Inc.
+0.39
MSFT
$46.13
Microsoft Corpora
+1.11
GOOG
$539.78
Google Inc.
-4.20

MacTech Search:
Community Search:

Software Updates via MacUpdate

OS X Server 4.0 - For OS X 10.10 Yosemit...
Designed for OS X and iOS devices, OS X Server makes it easy to share files, schedule meetings, synchronize contacts, develop software, host your own website, publish wikis, configure Mac, iPhone,... Read more
TotalFinder 1.6.12 - Adds tabs, hotkeys,...
TotalFinder is a universally acclaimed navigational companion for your Mac. Enhance your Mac's Finder with features so smart and convenient, you won't believe you ever lived without them. Tab-based... Read more
BusyCal 2.6.3 - Powerful calendar app wi...
BusyCal is an award-winning desktop calendar that combines personal productivity features for individuals with powerful calendar sharing capabilities for families and workgroups. BusyCal's unique... Read more
calibre 2.7 - Complete e-library managem...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital... Read more
Skitch 2.7.3 - Take screenshots, annotat...
With Skitch, taking, annotating, and sharing screenshots or images is as fun as it is simple.Communicate and collaborate with images using Skitch and its intuitive, engaging drawing and annotating... Read more
Delicious Library 3.3.2 - Import, browse...
Delicious Library allows you to import, browse, and share all your books, movies, music, and video games with Delicious Library. Run your very own library from your home or office using our... Read more
Art Text 2.4.8 - Create high quality hea...
Art Text is an OS X application for creating high quality textual graphics, headings, logos, icons, Web site elements, and buttons. Thanks to multi-layer support, creating complex graphics is no... Read more
Live Interior 3D Pro 2.9.6 - Powerful an...
Live Interior 3D Pro is a powerful yet very intuitive interior designing application. View Video Tutorials It has every feature of Live Interior 3D Standard, plus some exclusive ones: Create multi... Read more
The Hit List 1.1.7 - Advanced reminder a...
The Hit List manages the daily chaos of your modern life. It's easy to learn - it's as easy as making lists. And it's powerful enough to let you plan, then forget, then act when the time is right.... Read more
jAlbum Pro 12.2.4 - Organize your digita...
jAlbum Pro has all the features you love in jAlbum, but comes with a commercial license. With jAlbum, you can create gorgeous custom photo galleries for the Web without writing a line of code!... Read more

Latest Forum Discussions

See All

Rami Ismail Opens Up distribute​() for D...
Rami Ismail Opens Up distribute​() for Developers Posted by Jessica Fisher on October 24th, 2014 [ permalink ] Rami Ismail, Chief Executive of Business and Development at indie game studio | Read more »
Great Hitman GO Goes on Sale and Gets Ne...
Great Hitman GO Goes on Sale and Gets New Update – Say That Three Times Fast Posted by Jessica Fisher on October 24th, 2014 [ permalink ] | Read more »
Rival Stars Basketball Review
Rival Stars Basketball Review By Jennifer Allen on October 24th, 2014 Our Rating: :: RESTRICTIVE BUT FUNUniversal App - Designed for iPhone and iPad Rival Stars Basketball is a fun mixture of basketball and card collecting but its... | Read more »
Rubicon Development Makes Over a Dozen o...
Rubicon Development Makes Over a Dozen of Their Games Free For This Weekend Only Posted by Jessica Fisher on October 24th, 2014 [ permalink ] | Read more »
I Am Dolphin Review
I Am Dolphin Review By Jennifer Allen on October 24th, 2014 Our Rating: :: NEARLY FIN-TASTICUniversal App - Designed for iPhone and iPad Swim around and eat nearly everything that moves in I Am Dolphin, a fun Ecco-ish kind of game... | Read more »
nPlayer looks to be the ultimate choice...
Developed by Newin Inc, nPlayer may seem like your standard video player – but is aiming to be the best in its field by providing high quality video play performance and support for a huge number of video formats and codecs. User reviews include... | Read more »
Fighting Fantasy: Caverns of the Snow Wi...
Fighting Fantasy: Caverns of the Snow Witch Review By Jennifer Allen on October 24th, 2014 Our Rating: :: CLASSY STORYTELLINGUniversal App - Designed for iPhone and iPad Fighting Fantasy: Caverns of the Snow Witch is a sterling... | Read more »
A Few Days Left (Games)
A Few Days Left 1.01 Device: iOS Universal Category: Games Price: $3.99, Version: 1.01 (iTunes) Description: Screenshots are in compliance to App Store's 4+ age rating! Please see App Preview for real game play! **Important: Make... | Read more »
Toca Boo (Education)
Toca Boo 1.0.2 Device: iOS Universal Category: Education Price: $2.99, Version: 1.0.2 (iTunes) Description: BOO! Did I scare you!? My name is Bonnie and my family loves to spook! Do you want to scare them back? Follow me and I'll... | Read more »
Intuon (Games)
Intuon 1.1 Device: iOS Universal Category: Games Price: $.99, Version: 1.1 (iTunes) Description: Join the battle with your intuition in a new hardcore game Intuon! How well do you trust your intuition? Can you find a needle in a... | Read more »

Price Scanner via MacPrices.net

Weekend sale: 13-inch 128GB MacBook Air for $...
Best Buy has the 2014 13-inch 1.4GHz 128GB MacBook Air on sale for $849.99, or $150 off MSRP, on their online store. Choose free home shipping or free local store pickup (if available). Price valid... Read more
Nimbus Note Cross=Platform Notes Utility
Nimbus Note will make sure you never forget or lose your valuable data again. Create and edit notes, save web pages, screenshots and any other type of data – and share it all with your friends and... Read more
NewerTech’s Snuglet Makes MagSafe 2 Power Con...
NewerTech has introduced the Snuglet, a precision-manufactured ring designed to sit inside your MagSafe 2 connector port, providing a more snug fit to prevent your power cable from unintentional... Read more
Apple Planning To Sacrifice Gross Margins To...
Digitimes Research’s Jim Hsiao says its analysts believe Apple is planning to sacrifice its gross margins to save its tablet business, which has recently fallen into decline. They project that Apple’... Read more
Who’s On Now? – First Instant-Connect Search...
It’s nighttime and your car has broken down on the side of the highway. You need a tow truck right away, so you open an app on your iPhone, search for the closest tow truck and send an instant... Read more
13-inch 2.5GHz MacBook Pro on sale for $949,...
Best Buy has the 13″ 2.5GHz MacBook Pro available for $949.99 on their online store. Choose free shipping or free instant local store pickup (if available). Their price is $150 off MSRP. Price is... Read more
Save up to $125 on Retina MacBook Pros
B&H Photo has the new 2014 13″ and 15″ Retina MacBook Pros on sale for up to $125 off MSRP. Shipping is free, and B&H charges NY sales tax only. They’ll also include free copies of Parallels... Read more
Apple refurbished Time Capsules available sta...
The Apple Store has certified refurbished Time Capsules available for up to $60 off MSRP. Apple’s one-year warranty is included with each Time Capsule, and shipping is free: - 2TB Time Capsule: $255... Read more
Textilus New Word, Notes and PDF Processor fo...
Textilus is new word-crunching, notes, and PDF processor designed exclusively for the iPad. I haven’t had time to thoroughly check it out yet, but it looks great and early reviews are positive.... Read more
WD My Passport Pro Bus-Powered Thunderbolt RA...
WD’s My Passport Pro RAID solution is powered by an integrated Thunderbolt cable for true portability and speeds as high as 233 MB/s. HighlightsOverviewSpecifications Transfer, Back Up And Edit In... Read more

Jobs Board

*Apple* Solutions Consultant - Apple Inc. (U...
…important role that the ASC serves is that of providing an excellent Apple Customer Experience. Responsibilities include: * Promoting Apple products and solutions Read more
Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Project Manager / Business Analyst, WW *Appl...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.