TweetFollow Us on Twitter

True B, Prototyper
Volume Number:4
Issue Number:8
Column Tag:Basic School

True Basic & Prototyper Reviewed

By Dave Kelly, Editorial Board

True Basic 2.01 Run Time Package

I promised you some more information about the new version of True Basic (2.01). The good news is that you can now create double-clickable applications with the runtime package that is included with the price of True Basic ($99.95 retail).This price includes both a commercial and non-commercial license.There is no longer an extra charge for the license for "unlimited commercial" use. The Bad news is that the Developer's Toolkit is not included with the True Basic interpreter yet. UGH! According to True Basic it will be available soon. The Developer’s Toolkit includes all the ROM routines for creating the Macintosh User features we all know and love. As much as I would like the Toolkit to be included with True Basic, they have come a long way. After all, last time I reviewed this the runtime package was priced way out of sight and even the interpreter was overpriced.

You are probably wondering about the runtime package and just what it is. I just received a copy of the runtime package yesterday, but I can pass on to you some information about it. The runtime includes two new libraries of routines, named Bundle and Launch*. Bundle is a “compiled” True Basic program which sets up the signature id of your application. Launch* consists of some routines for getting your application’s name and getting the names of files to be opened or printed by the application that were selected in the finder when the application was run. Two application files are included in the runtime package too. RTP is an application shell program which is that base of all applications that you will create. RTP contains the ENTIRE True Basic interpreter and is used as the shell which will ‘run’ your program after it is attached. The other application is named Binder and is used to combined compiled True Basic programs with the RTP application so that they can now be considered one application. The RTP application (the interpreter) consists of 73K of True Basic standard packages so you should be aware that your programs will always be at least 73K in size. That may be bad news, but at least the application can be created.

True Basic has one of the most extensive sets of library routines available for any language. Some of these routines are very valuable for scientific/engineering applications. True Basic Inc. says that all the original versions of the libraries work with True Basic 2.01 except for the Developer’s Toolkit and the Communications Support package. Both of these have been updated to work with version 2.01. The Developer’s Toolkit, as I mentioned before, contains all the latest Macintosh ROM routine calls. Some of the libraries available include: Business Graphics Toolkit, Scientific Graphics Toolkit, 3D Graphics, Communications Support, Forms Management, Sorting and Searching, Advanced String Library, and Mathematician’s Toolkit. All of these are list price of $69.95 each. They are probably worth it if you think you need the function they perform.

To give you a little feel for the runtime package I have included the following short program which makes use of the launch* library. The program displays the files which were selected in the finder launch of the application.

! Runtime Demo

LIBRARY “launch*”
CALL AppParms(name$,message,nfiles)
PRINT “Current Application name is:”;name$
SELECT CASE message
CASE 0
     PRINT “Files to be opened:”
CASE 1
     PRINT “Files to be printed:”
END SELECT
FOR i=1 to nfiles
    CALL Appfile(i,filename$,””)
    PRINT filename$
    CALL ClrAppFile(i)
NEXT i
if nfiles=0 then print “NONE”
GET KEY k
END

SAMPLE OUTPUT:

So just what’s so great about True Basic? Actually, the main drawback in the previous version was its inability to be a double-clickable application. As a language, it is excellent, especially in support of scientific applications. On the positive side, True Basic has the strongest version of Basic available on the Mac. The reason I say it is the strongest because the structure and functional capabilities of the language are solid and reliable (I haven’t seen any system bombs!) The library routines are very extensive, more extensive than any for MS Basic. Recursion is supported. The 68881 math coprocessor is supported. Color is supported with ability to modify color palettes (July, 1988 MacTutor). Since the runtime package is now made more freely available, you can use True Basic more effectively in real world applications (instead of the class room world that you have without the runtime package).

No Developer’s Toolkit Yet

On the negative side, there are a few areas that could have been cleaned up a bit. The first negative, and my strongest point is that the Developer’s Toolkit is not included with the interpreter. Since I’ve already mentioned this before I won’t dwell on it, but I feel it is a ‘must have’ if you are doing any serious development. Next there are a few compatibility/ user interface issues some of which you can fix yourself. One problem is the small size of the Standard GetFile/SaveFile Dialog windows. This can be fix with a little ResEdit work. The problem is that the window is only wide enough for short file names (like version 1.0 was when Mac 128K came out). Fortunately this is fixable.

While it is true that True Basic will run with Multifinder, True Basic does not know when to update windows when they have been overwritten by other applications or desk accessories and without the Developer’s Toolkit it would be impossible to know that a window needs to be refreshed. True Basic was designed to run in one window which happens to be the size of the screen (any size screen). All graphics commands are automatically scaled to work with whatever size screen (on whatever computer True Basic runs on). Since the main True Basic window is the size of the screen and is not adjustable, it will overlap ALL windows and icons which are running in the background with Multifinder. Since the menus are disabled during True Basic runtime (runtime package), the only way to switch applications is by clicking on the icon in the upper right corner (in the menu bar). The are a few refinements that could be done here to make it more Multifinder compatible.

True Basic for the Macintosh comes with two manuals, the Reference Manual, and the Macintosh™ User’s Guide. The Reference Manual is much improved over the old version included with version 1.0. The True Basic statements are listed alphabetically in the back half of the book (part III), but since there are sometimes several statements on a page you have to read carefully to find what you are looking for. The Macintosh™ User’s Manual is just what it says it is, a user’s manual. The first half of the book tells what each menu of the True Basic application does, then there are some sections telling about a few Macintosh only routines which are included. Included in this is sections on color support, standard GetFile/PutFile stuff, and a few graphics commands for fonts and basic graphics (about like the original MS Basic Toolbox of Graphics commands). The rest of the graphic support (99% of it) is built into the standard True Basic.

Should you buy it? Well, if you do I recommend that you be sure to get the Developer’s Toolkit too. I haven’t seen the Developer’s Toolkit yet (I hope to be able to review it soon!) so I can’t form an opinion yet, but since I expect it to be similar or better than the original ToolBox routines (from version 1.0) I would say that it should turn out to be a pretty decent package. True Basic costs $99.95, so with the Toolkit it will be about $170 for the whole enchilada. If you are an educator you may be able to get really good prices on everything (about half price). I would say that there is a lot of potential for more support for True Basic in the future.

ProtoTyper Creates Shell Program Code

Thank goodness for software developers. At least that’s what I say when I don’t have the time to write my own software and I need to do something right now. The problem is the length of time it takes to develop software. There are a number of you that, like myself, work full time at a job other than programming and then have family and other responsibilities take you away from that great idea for a software package. Time is valuable, especially when the only time you may have is on weekends and a little time each evening.

One solution to my time schedule problem has been to write most of my programs in Basic because it is “quick and dirty”. I can usually see my results during the same weekend or maybe two weekends for a longer program, compared to several weeks working with a full blown Pascal program. That used to be the only solution available to me (except to give it up and not write anything) until recently. It’s been different lately.

PRESENTING PROTOTYPER™

Back at MacWorld Expo in San Francisco I saw Prototyper™ for the first time. Prototyper is one of those truly ingenious ideas whose time has come. If you haven’t yet seen it or read about it yet then keep on reading. If you have heard of Prototyper then I don’t want it said that it wasn’t ever mentioned in MacTutor.

What is Prototyper? Prototyper is a tool which is used to help you to develop the conceptual design of your software and get you started with your software. It is not all things to all people, but it is a unique tool which may be used to save many hours of development time. Prototyper is not a language compiler; it is a code generation program and resource compiler of a sort. Anyone that uses resources such as menus, windows, dialogs, icons, or controls can make use of Prototyper.

Prototyper is not just another substitute for ResEdit. ResEdit is still very useful for what it does, but Prototyper adds another element of user friendliness to the sometimes hostile world of software development. Let’s look at a typical sample Prototyper application. The Prototyper window lists the windows and dialogs that have been defined. Clicking on the menu icon invokes the menu editor. Clicking on the window icon invokes the window/dialog editor. (See fig. 1 previous page)

The Menu editor is similar to other menu editors I have seen before. By clicking in the first column, Menus:, you can select and change the menu to edit. Clicking on an item in the second column lets you edit each item. The current menu is presented in the menu bar so you can see what you actually get. It’s a good thing because the scrolling window is so narrow that longer menu item names can’t be seen. A wider window here or a better way to scroll would be valuable, but is not essential to creating a menu successfully. You may check, disable items, or add command-keys. Icons may be added to menus to add a personal touch. Icons may be read in from any application and modified with the icon editor. The Link button links any item to a defined window or dialog. More on that later. Only one menu can be created. (See fig. 2 below)

The window editor allows you to create almost any kind of window, dialog, or alert and add text, buttons, scroll bars, active or inactive icons, lists, lines, and rectangles. You should decide before hand whether or not you should use a window, dialog or alert as defined in the guidelines in Inside Macintosh. At least once I created a dialog or alert and used it the wrong way and Prototyper bombed! Except for that it was extremely easy to use. (See fig. 3 below)

I created a sample window and sample dialog for this example. The dialog will serve as my About Dialog when the application is created so I have linked the About menu item (in the Menu Editor) to the DIALOG -About Dialog window and set the OK button to close the dialog when pressed. I included some sample buttons and a scroll bar so that you could see how that works. The scroll bars and buttons will move and toggle, but don’t effect anything else. They won’t do anything until they are updated in the Pascal source code. (See fig. 4 below)

There are a few areas that are deficient that SmethersBarnes needs to work on to improve the next version. One deficiency is that you can’t set up hierarchical menus from within Prototyper. That doesn’t mean that you can’t do it yourself. It just means that you won’t have the menu resources for hierarchical menus set up for you. The next version of Prototyper promises hierarchical menus and support for C. The current version supports four different versions of Pascal, LightSpeed™ Turbo™, MPW™, and TML™. I don’t know if that includes the new TML Pascal II which runs under MPW. I’m very pleased with the results of the LightSpeed code. You set up your preferences and dump the code to the appropriate LightSpeed type files. A resource file is also created along with an RMaker source file (except for PICT resources). (See fig. 5)

Prototyper generates a shell for you which incorporates all of the menus and windows which were created in the Menu and Window Editor. It’s too bad that only one menu may be used, but the shell must be able to work with many different application designs. A sample of the LightSpeed Pascal is given on the source code disk for this issue of MacTutor.

I wholeheartedly recommend Prototyper to anyone that would like to write full blown applications, but can’t use Basic for one reason or another and doesn’t want to take a lot of time writing the shell the application. Some of you might not need Prototyper if you already have your own custom application shell, but even then Prototyper is a great way to create the resources. There are things that can and will improve, such as adding hierarchical menus and generation of C source code, but even without some of the enhancements, Prototyper is a major time saver. Improvements will come with time.

unit About_Dialog;

{File name:About_Dialog.Pas }
{Function: Handle a dialog }
{History: 6/13/88 Original by Prototyper. }

interface

  procedure D_About_Dialog;

implementation

  const {item numbers for controls in the Dialog}
    I_OK = 1;
    I_Static_Text = 2;
var 
    ExitDialog : boolean;  {Flag used to exit the Dialog}
  procedure D_About_Dialog;
    var
      GetSelection : DialogPtr;  {Name of dialog}
      {*ExitDialog : Boolean; declared global for filter routine *} {Flag 
to exit dialog}
      tempRect : Rect;          {Temporary tectangle}
      DType : Integer;          {Type of dialog item}
      Index : Integer;          {For looping}
      DItem : Handle;           {Handle to the dialog item}
      CItem, CTempItem : controlhandle;
      sTemp : Str255;     {temp holding}
      itemHit : Integer;        {Get selection}
      temp : Integer;         {temp holding}
      Icon_Handle : Handle;   {Temp handle to read Icon }
      NewMouse : Point;    {Mouse loc,tracking Icon presses}
      InIcon : boolean;       {Flag to say pressed in an Icon}
      ThisEditText : TEHandle;  {Handle to Dialogs TE record}
      TheDialogPtr : DialogPeek;  {Pntr to Dialogs def record}
   
  {This is an update routine for non-controls in the dialog} 
  {This is executed after the dialog is uncovered by an alert} 
  procedure Refresh_Dialog;  {Refresh dialogs non-controls}
    var 
      rTempRect:Rect;    {Temp rectangle used for drawing}
    begin 
  end; 
   
    begin        {Start of dialog handler}
      GetSelection := GetNewDialog(2, nil,  Pointer(-1) );
      ShowWindow(GetSelection);         {Open a dialog box}
      SelectWindow(GetSelection);       {Lets see it}
      SetPort(GetSelection); 
      TheDialogPtr := DialogPeek(GetSelection); 
      ThisEditText := TheDialogPtr^.textH; 
      HLock(Handle(ThisEditText));      {Lock it for safety}
      ThisEditText^^.txSize := 12;      {TE Point size}
      TextSize(12);                     {Window Point size}
      ThisEditText^^.txFont := systemFont; {TE Font ID}
      TextFont(systemFont);             {Window Font ID}
      ThisEditText^^.txFont := 0;       {TE Font ID}
      ThisEditText^^.fontAscent := 12;  {Font ascent}
      ThisEditText^^.lineHeight := 12 + 3 + 1; 
 {Font ascent + descent + leading}
      HUnLock(Handle(ThisEditText));   {UnLock handle}
       
      {Setup initial conditions}      
      ExitDialog:=FALSE;  {Do not exit dialog handle loop yet}      
      repeat          {Start of dialog handle loop}
        ModalDialog(nil, itemHit);  {Wait til item hit}
        GetDItem(GetSelection, itemHit, DType, DItem, tempRect); {Get 
item information}
        CItem := Pointer(DItem);  {Get the control handle}       
        if (ItemHit =I_OK) then  {Handle Button pressed}
          begin
          {?? Code to handle this button goes here}
          ExitDialog:=TRUE;  {Exit dialog when selection made}
          end;               {End for this item selected}
      until ExitDialog;  
       
      {Get results after dialog}
      DisposDialog(GetSelection);   {Flush dialog}
    end;                            {End of procedure}
  end.                             {End of unit}
  
unit  HandleTheMenus;

{File name :HandleTheMenus.Pas}
{Function: Handle all menu selections.}
{  This procedure is called when a menu item is selected.}
{  There is one CASE statement for all Lists.  There is}
{  another CASE for all the commands in each List.}
{History: 6/13/88 Original by Prototyper.   }

interface

uses
  About_Dialog, Sample_Window, InitTheMenus;

  procedure Handle_My_Menu(var doneFlag:boolean; theMenu,theItem:integer; 
var theInput:TEHandle);

implementation

  procedure Handle_My_Menu; {menu selections realtime}
    const
      L_Apple = 201;                    {Menu list}
      C_About_this_Sample = 1;
      L_File = 202;                     {Menu list}
      C_Quit = 1;
      L_Edit = 203;                     {Menu list}
      C_Undo = 1;
      C_Cut = 3;
      C_Copy = 4;
      C_Paste = 5;
      C_Clear = 6;
      C_Select_All = 7;
    var
      DNA:integer;                     {For opening DAs}
      BoolHolder:boolean;              {For SystemEdit result}
      DAName:Str255;                   {For getting DA name}
      SavePort:GrafPtr;   {Save current port when opening DAs}  
    begin                   {Start of procedure}     
        case theMenu of     {Do selected menu list}     
        L_Apple:
          begin
            case theItem of {Handle commands in menu list}
              C_About_this_Sample:
                begin
                  D_About_Dialog; {Call dialog for this}
                end;
              otherwise                 {Handle the DAs}
                begin                   {Start of Otherwise}
                  GetPort(SavePort);    {Save current port}
                  GetItem(AppleMenu, theItem, DAName); {DA}
                  DNA := OpenDeskAcc(DAName); {Open DA }
                  SetPort(SavePort);    {Restore saved port}
                end;                    {End of Otherwise}  
            end;                        {End of item case}
          end;                          {End for this list}
      
        L_File:
          begin
            case theItem of 
              C_Quit:
                begin
                  doneFlag := TRUE;
                end;
              otherwise
                begin
                end;
             
            end;                        {End of item case}
          end;                          {End for this list}
      
        L_Edit:
          begin
            BoolHolder := SystemEdit ( theItem - 1 ); 
 {Do DA editing}
            if not (BoolHolder) then    
 {If not a DA then we get it}
              begin    {Handle by using a Case statment}
              case theItem of  {Handle all commands in list}
                C_Undo:
                  begin
                    {?? ADD IN WHAT THIS COMMAND SHOULD DO}
                  end;
                C_Cut:
                  begin
                    {?? ADD IN WHAT THIS COMMAND SHOULD DO}
                  end;
                C_Copy:
                  begin
                    {?? ADD IN WHAT THIS COMMAND SHOULD DO}
                  end;
                C_Paste:
                  begin
                    {?? ADD IN WHAT THIS COMMAND SHOULD DO}
                  end;
                C_Clear:
                  begin
                    {?? ADD IN WHAT THIS COMMAND SHOULD DO}
                  end;
                C_Select_All:
                  begin
                    {?? ADD IN WHAT THIS COMMAND SHOULD DO}
                  end;
                otherwise  {Send to a DA}
                  begin    {Start of the Othersize}
                  end;     {End of Otherwise}
               
              end;          {End of item case}
              end;          {End of not BoolHolder}
          end;              {End for this list}
      
        otherwise
          begin
          end;      
      end;                  {End for lists}     
      HiliteMenu(0);   {Turn menu selection off}
    end;               {End of procedure Handle_My_Menu}  
end.                   {End of unit}

unit  InitTheMenus;
 
{File name:InitTheMenus.Pas}
{Function: Pull in menu lists from a resource file.}
{    This procedure is called once at program start.}
{    AppleMenu is the handle to the Apple menu, it is also}
{    used in the procedure that handles menu events.}
{ History: 6/13/88 Original by Prototyper.   }

interface
 
  procedure Init_My_Menus;  {Initialize the menus}
 
  var
    AppleMenu:MenuHandle;  {Used to handle DAs}      
 
implementation
 
  procedure Init_My_Menus;    {Initialize the menus}
  const
    Menu1 = 201;                {Menu resource ID}
    Menu2 = 202;                {Menu resource ID}
    Menu3 = 203;                {Menu resource ID}
  var
    tempMenu:MenuHandle;  {Throw away all other menu handles}
      
  begin                  {Start of Init_My_Menus}
    ClearMenuBar;         {Clear any old menu bars}
      
    { APPLE menu, used for About & desk accessories.}
    tempMenu := GetMenu(Menu1);   {Get menu from res file}
    AddResMenu(tempMenu,’DRVR’);  {Add in DAs}
    InsertMenu (tempMenu,0);      {Insert menu into menu bar}
    AppleMenu:=tempMenu;          {Save menu handle for later}
    { This menu is  File  }
    tempMenu := GetMenu(Menu2);    
    InsertMenu (tempMenu,0);            
    { This menu is  Edit  }
    tempMenu := GetMenu(Menu3);         
    InsertMenu (tempMenu,0);            
    DrawMenuBar;       {Draw the menu bar}
end;                  {End of procedure Init_My_Menus}
end.


Set  RUN OPTIONS to use the resource file  Prototyper_Sample.RSRC
RMaker file to use is Prototyper_Sample.R 
The Project should have the following files in it: 
     MacPasLib      LSP This is the Pascal library file
     MacTraps       LSP This is for Mac routines to be called}
     ROM85          LSP This is necessary if you use any Lists}
     ROM85Lib       LSP This is necessary if you use any Lists}
     ListManager    LSP This is necessary if you use any Lists}
     About_Dialog        Modal Dialog
     Sample_Window       Window
     InitTheMenus.Pas    This initializes the Menus.
     HandleTheMenus      Handle the menu selections.
     Prototyper_Sample.Pas    Main program

Program  Prototyper_Sample;
{Program name:Prototyper_Sample.Pas   }
{Function:  This is the main module for this program.  }
{History: 6/13/88 Original by Prototyper.   }

uses
  About_Dialog, Sample_Window, InitTheMenus, HandleTheMenus;

  var                          {Main variables}
    myEvent:EventRecord;        {Event record for all events}
    doneFlag:boolean;           {Exit program flag}
    code:integer;               {Determine event type}
    whichWindow:WindowPtr;      {See which window for event}
    tempRect:Rect;              {Rect for dragging}
    mResult:longint;    {Menu list and item selected values}
    theMenu,theItem:integer;     {Menu list and item selected}
    chCode : integer;            {Key code}
    ch : char;                   {Key pressed in Ascii}
    theInput:TEHandle;         {Used in text edit selections}
 
  begin                           {Start of main body}
 
    MoreMasters;     {This reserves space for more handles}
    InitGraf(@thePort);           {Quickdraw Init}
    InitFonts;                    {Font manager init}
    InitWindows;                  {Window manager init}
    InitMenus;                    {Menu manager init}
    TEInit;                       {Text edit init}
    InitDialogs(nil);             {Dialog manager} 
    FlushEvents(everyEvent, 0);   {Clear out all events}
    InitCursor;                   {Make an arrow cursor}
    doneFlag:=FALSE;            {Do not exit program yet}
      
    Init_My_Menus;              {Initialize menu bar} 
    theInput:=nil; {Init to no text edit selection active}
    Init_Sample_Window;  {Initialize the window routines}
    Open_Sample_Window;  {Open wind routines at program start}
 
    repeat                   {Start of main event loop}
      if (theInput <> nil) then {See if a TE is active}
        TEIdle(theInput);  {Blink cursor if everything ok}
      SystemTask;      {support of desk accessories} 
      if GetNextEvent(everyEvent, myEvent) then 
        begin         {Start handling the event}
        code := FindWindow(myEvent.where, whichWindow); 
        case myEvent.what of    {Decide type of event}
          MouseDown :         {Mouse button pressed}
            begin            {Handle the pressed button}
              if (code = inMenuBar) then
                begin  {Get menu selection and handle it}
                     mResult := MenuSelect(myEvent.Where); 
                     theMenu := HiWord(mResult); 
                     theItem := LoWord(mResult); 
                 Handle_My_Menu(doneFlag,theMenu,theItem, theInput); 

                end;             {End of inMenuBar}
 
              if (code = InDrag) then   {window drag area}
                begin      {Do dragging the window}
                tempRect:= screenbits.bounds; {screen l,t,r,b}
                      SetRect(tempRect,tempRect.Left+10, tempRect.Top+25,tempRect.Right-10,tempRect.Bottom-10); 

                DragWindow(whichWindow, myEvent.where, tempRect); 
                end;            {End of InDrag}
 
              if (code = inGrow) then   {In grow area}
                begin         {Handle the growing}
                tempRect:= whichWindow^.portRect;  
 {Get size and position}
                tempRect.Right := tempRect.Right - tempRect.Left + 1; 
{Adjust to local}
                tempRect.left := tempRect.Right - 18; 
 {Do for width of right edge}
                tempRect.Bottom := tempRect.Bottom - tempRect.Top + 1; 
{Get window height}
                tempRect.top := 0;   {for height of window}
                EraseRect(tempRect);    {Erase old right edge}
                tempRect:= whichWindow^.portRect;  
 {Get window size and position}
                tempRect.Right := tempRect.Right - tempRect.Left + 1; 
{Adjust to local}
                tempRect.left := 0;  {Do width of  window}
                tempRect.Bottom := tempRect.Bottom - tempRect.Top + 1; 
{Get window height}
                tempRect.top := tempRect.Bottom - 18; {Do for height 
of the edge}
                EraseRect(tempRect);  {Erase old bottom edge}
                SetRect(tempRect, 20, 20, 1000, 1000);  {Min Horz size, 
Min Vert size, Max Horz size, Max Vert size}
                mResult := GrowWindow(whichWindow, myEvent.where, tempRect); 
{Grow it}
                SizeWindow(whichWindow, LoWord(mResult), HiWord(mResult), 
TRUE); {Resize to result}
                DrawGrowIcon(whichWindow); {Draw grow Icon again}
                end;   {End of doing the growing}
 
              if (code = inGoAway) then {window goaway area}
                begin   {Handle the goaway button}
                If TrackGoAway(whichWindow,myEvent.where) then 
 {See if mouse released in GoAway box}
                  begin     {Handle the GoAway}
                  Close_Sample_Window(whichWindow,theInput);
 {Close this window}
                  end;       {End of TrackGoAway}
                end;         {End of InGoAway}
 
              if (code = inContent) then {See if in a window}
                begin     {Handle the hit inside a window}
                if (whichWindow <> FrontWindow) then 
                  SelectWindow(whichWindow) 
                else    
                  begin  {Handle the button in the content}
                  SetPort(whichWindow); {Get ready to draw}
                  Do_Sample_Window ( myEvent,theInput ); 
                  end;         {End of else}
                end;           {End of inContent}
 
              if (code = inSysWindow) then {DA?}
                SystemClick(myEvent, whichWindow); 
 
            end;              {End of MouseDown}
 
          KeyDown,AutoKey:    {Handle key inputs}
            begin         {Get the key and handle it}
              with myevent do    {menu command keys}
                begin  
                  chCode := BitAnd(message, CharCodeMask); 
 {Get character}
                  ch := CHR(chCode);    {Change to ASCII}
                  if (Odd(modifiers div CmdKey)) then 
 {See if Command key is down}
                     begin        
                     mResult := MenuKey(ch); {menu selection}
                     theMenu := HiWord(mResult); 
                        theItem := LoWord(mResult); 
                     if (theMenu <> 0) then 
 {See if a list was selected}
                     Handle_My_Menu(doneFlag,theMenu, theItem,theInput); 
{Do the menu selection}
                     if ((ch = ‘x’) or (ch = ‘X’)) and (theInput <> nil) 
then
                      TECut(theInput);  {Handle a TE Cut}
                    if ((ch = ‘c’) or (ch = ‘C’)) and (theInput <> nil) 
then {}
                      TECopy(theInput); {Handle a TE Copy}
                    if ((ch = ‘v’) or (ch = ‘V’)) and (theInput <> nil) 
then
                      TEPaste(theInput); {Handle a Paste}
                   end                                         
 
 else if (theInput <> nil) then 
                    TEKey(ch,theInput);                 
 end;  {End for with}
            end;      {End for KeyDown,AutoKey}
 
          UpDateEvt :   {Update event for a window}
            begin       {Handle the update}
              whichWindow := WindowPtr(myEvent.message); 
 {Get the window the update is for}
              BeginUpdate(whichWindow); 
 {Set the clipping to the update area}
              Update_Sample_Window ( whichWindow ); 
 {Update this window}
              EndUpdate(whichWindow);   
 {Return to normal clipping area}
            end;         {End of UpDateEvt}
 
          DiskEvt :     {Disk inserted event}
            begin       {Handle a disk event}
            {Ck for disk event}  
 {?? ADD CALL TO HANDLE A DISK INSERTED}
            end;         {End of DiskEvt}
            
          ActivateEvt :   {Window activated event}
            begin         {Handle the activation}
              whichWindow := WindowPtr(myevent.message); 
 {Get the window to be activated}
              if odd(myEvent.modifiers) then 
 {Activate and not DeActivate}
                 SelectWindow(whichWindow); 
 {Activate the window by selecting it}
            end;          {End of ActivateEvt} 
          otherwise       
            begin                                              {?? ADDED 
FOR CATCHING OTHER EVENTS}
            end;             {End of otherwise}
        end;                 {End of case}
        end;                 {end of GetNextEvent}
    until doneFlag;          {End of the event loop}
end.                         {End of the program}

unit  Sample_Window;

{File name: Sample_Window.Pas}
{Function: Handle a Window}
{History: 6/13/88 Original by Prototyper. }

interface

  {Initialize us so all our routines can be activated}
  procedure Init_Sample_Window;

  {Close our window}
  procedure Close_Sample_Window(whichWindow:WindowPtr; var theInput:TEHandle);

  {Open our window and draw everything}
  procedure Open_Sample_Window;

  {Update our window, someone uncovered a part of us}
  procedure Update_Sample_Window(whichWindow:WindowPtr);

  {Handle action to our window, like controls}
  procedure Do_Sample_Window(myEvent:EventRecord; var theInput:TEHandle);

implementation

  const
    I_Buttonx1 = 4;                     {Button ID}
    I_Checkbox1 = 6;                    {Checkbox ID}
    I_Checkbox2 = 17;                   {Checkbox ID}
    I_Radio1 = 7;                       {Radio ID}
    I_Radio2 = 18;                      {Radio ID}
    I_Edit_Text = 3;                    {Edit text ID}
    I_Scroll_bar = 5;                   {Scroll bar ID}
  var
    MyWindow:WindowPtr;                 {Window pointer}
    tempRect : Rect;                    {Temporary rectangle}
    Index : Integer;                    {For looping}
    CtrlHandle : controlhandle;         {Control handle}
    sTemp : Str255;           {Get text entered, temp holding}
    R1Control:array[1..2] of ControlHandle; { Radio button }
    TE_I_Edit_Text: TEHandle; {Text Edit field handle}
 
{=================================}
 
  {Initialize us so all our routines can be activated}
  procedure Init_Sample_Window;
 
  begin    {Start of Window initialize routine}
    MyWindow:=nil; {other routines must know not valid yet}
  end;     {End of procedure}

{=================================}
 
  {Close our window}
  procedure Close_Sample_Window;
 
  begin                {Start of Window close routine}
    if (MyWindow <> nil) and (MyWindow = whichWindow) then     
 {Close if this is us}
      begin
      if (theInput = TE_I_Edit_Text) then 
 {See if this Text Edit field handle}
      theInput:= nil;     {Clear the handle used}
      DisposeWindow(MyWindow);  {Clear window and controls}
      MyWindow:=nil;  {notify routines window open}
      end;        {End for if (MyWindow<>nil)}
  end;            {End of procedure}

{=================================}
 
  {Update our window, someone uncovered a part of us}
  procedure UpDate_Sample_Window;
  var
    SavePort : WindowPtr;  {Place to save the last port}
    Pic_Handle: PicHandle; {Pict handle for pict loaded }
    sTemp:Str255;    {Temporary string}

  begin          {Start of Window update routine}
    if (MyWindow <> nil) and (MyWindow = whichWindow) then     
 {Handle an open when already opened}
      begin
      GetPort(SavePort);    {Save the current port}
      SetPort(MyWindow);    {Set the port to my window}
      Pic_Handle := GetPicture(9 ); {Get Picture into memory}
      SetRect(tempRect, 188,141,247,218); 
      if (Pic_Handle <> nil) then   
        DrawPicture ( Pic_Handle , tempRect ); 
 {Draw this picture}
      
      TextFont(systemFont);  {Set the font to draw in}
      {Draw a string of text, Static Text }
      SetRect(tempRect, 252,146,330,184);
      sTemp :=’Read MacTutor!’;
      TextBox(Pointer(ord(@sTemp) + 1), length(sTemp), tempRect, teJustLeft);
      TextFont(applFont); {Set the default application font}
      
      {Update a TE box, Edit Text }
      SetRect(TempRect,46,27,294,129); {left,top,right,bottom}
      InsetRect(TempRect,-2,-2);        {Surround the TE area}
      FrameRect(TempRect);              {Frame this TE area}
      if (TE_I_Edit_Text <> nil) then   
 {Only update if TE area is valid}
        TEUpdate(TempRect,TE_I_Edit_Text); {Update TE area}
      
      DrawControls(MyWindow); {Draw all the controls}
      DrawGrowIcon(MyWindow);  {Draw the Grow box}
      SetPort(SavePort);                {Restore the old port}
    end;              {End for if (MyWindow<>nil)}
  end;                {End of procedure}

{=================================}
 
  {Open our window and draw everything}
  procedure Open_Sample_Window;
  var
    Index : Integer;                    {For looping}
    dataBounds : Rect;                  {For making lists}
    cSize : Point;                      {For making lists}

  begin               {Start of Window open routine}
    if (MyWindow = nil) then      
 {Handle an open when not already opened}
      begin
      MyWindow:= GetNewWindow(1,nil, Pointer(-1)); 
      SelectWindow(MyWindow);   {Bring window to the front}
      SetPort(MyWindow);    {Prepare to write into our window}
      { Make a button, Button }
      CtrlHandle := GetNewControl(I_Buttonx1,MyWindow); 
      { Make a checkbox, Checkbox1 }
      CtrlHandle := GetNewControl(I_Checkbox1,MyWindow); 
      { Make a checkbox, Checkbox2 }
      CtrlHandle := GetNewControl(I_Checkbox2,MyWindow);  
      { Make a radio button, Radio1 }
      R1Control[1] := GetNewControl ( I_Radio1 , MyWindow );
      { Make a radio button, Radio2 }
      R1Control[2] := GetNewControl ( I_Radio2 , MyWindow );
      { Make a scroll bar, Scroll bar }
      CtrlHandle := GetNewControl(I_Scroll_bar,MyWindow); 
      {Open a TE box, Edit Text }
      SetRect(TempRect,46,27,294,129); {left,top,right,bottom}
      InsetRect(TempRect,-2,-2);        {Surround the TE area}
      FrameRect(TempRect);              {Frame this TE area}
      InsetRect(TempRect,2,2);     {Restore the original size}
      TE_I_Edit_Text:= TENew(TempRect,TempRect); 
 {Create the TE area}
      HLock(Handle(TE_I_Edit_Text));    {Lock the handle}
      TE_I_Edit_Text^^.txFont := geneva; {Font}
      TE_I_Edit_Text^^.fontAscent := 12; {Font ascent}
      TE_I_Edit_Text^^.lineHeight := 12 + 3 + 1; 
 {Font ascent + descent + leading}
      HUnLock(Handle(TE_I_Edit_Text));  {UnLock the handle}
      sTemp:= ‘Edit Text’;
      {Default text string}
      TESetText(Pointer(Ord4(@sTemp)+1),length(sTemp), TE_I_Edit_Text); 
{Place default text in the TE area}
      TEActivate(TE_I_Edit_Text); {Make the TE area active}
      TEUpdate(TempRect,TE_I_Edit_Text);
      TextFont(applFont); {Set the default application font}
      UpDate_Sample_Window(MyWindow);   {update draws it}
      end        {End for if (MyWindow<>nil)}
    else
      SelectWindow(MyWindow);   {Already open, so show it}
  end;         {End of procedure}

{=================================}
 
  {Handle action to our window, like controls}
  procedure Do_Sample_Window;
  var
    RefCon:integer; {RefCon for controls}
    code:integer;   {Location of event in window or controls}
    theValue:integer;  {Current value of a control}
    whichWindow:WindowPtr;  {Window pntr where event happened}
    myPt:Point;      {Point where event happened}
    theControl:ControlHandle;  {Handle for a control}

  Procedure Do_A_Button;  {Handle a button being pressed}
  begin
    HiliteControl(theControl, 10);      {Darken the button}
    RefCon := GetCRefCon(theControl);   {get control refcon}
    case RefCon of          {Select correct button}
            I_Buttonx1:       {Button, button}
              begin          {start for this button}
                {??? HANDLE THE BUTTON BEING PRESSED HERE}
              end;            {end for this button}
          
          otherwise     {allow other buttons}
              begin      {start}
              end;        {end of otherwise}
    end;             {end of case}
    HiliteControl(theControl, 0);  {Lighten the button}
  end;   {Handle a button being pressed}

  Procedure Do_A_Checkbox;  {checkbox being pressed}
  var
    Index:integer;    {Index used for radios}

  procedure Clear1RadioGroup;  {clear radios in group 1}
  var
    Index:integer;   {Index used for radios}
  begin              {Start of the clear routine}
    for Index := 1 to 2 do   {Step thru all radios}
      SetCtlValue(R1Control[Index],0);  {Set this to zero}
  end;             {End of the clear routine}

  begin            {Handle a checkbox being pressed}
    RefCon := GetCRefCon(theControl);   {get control refcon}
    theValue := GetCtlValue(theControl); {Get current value}
    theValue := (theValue + 1) mod 2;   {Change value}
    case RefCon of      {Select correct button}
            I_Checkbox1:  {Checkbox1, checkbox}
              begin      {start for this button}
                {??? HANDLE THE CHECKBOX BEING PRESSED HERE}
                SetCtlValue(theControl, theValue); 
 {Set checkbox to new value}
              end;    {end for this checkbox}
          
            I_Checkbox2:     {Checkbox2, checkbox}
              begin         {start for this button}
                {??? HANDLE THE CHECKBOX BEING PRESSED HERE}
                SetCtlValue(theControl, theValue); 
 {Set checkbox to new value}
              end;           {end for this checkbox}
          
            I_Radio1:       {Radio1 , radio button}
               begin       {start for this radio button}
                {??? HANDLE THE RADIO BEING SELECTED HERE}
                Clear1RadioGroup;  {Clear all Radio values}
                SetCtlValue(theControl, 1); {Select Radio}
              end;     {end for this radio button}
          
            I_Radio2:    {Radio2 , radio button}
               begin    {start for this radio button}
                {??? HANDLE THE RADIO BEING SELECTED HERE}
                Clear1RadioGroup;       {Clear all Radio }
                SetCtlValue(theControl, 1); {Select Radio}
              end;       {end for this radio button}
          otherwise {allow other checkboxes and radios}
              begin  {start}
              end;   {end of otherwise}
    end;    {end of case}
  end;      {Handle a checkbox being pressed}

  Procedure Do_A_ScrollBar(code:integer); 
 {Handle a ScrollBar being pressed}

    procedure HandleWScrollBar (code, Start, Stop, Increment, LIncrement 
: integer; theControl : ControlHandle);
    var
      theValue : integer;   {Value of the scrollbar}
      myPt : Point;    {Returned point from track}
  
    begin
      theValue := GetCtlValue(theControl); {Get current state}
      if (code = inUpButton) then   {See if in up/left arrow}
        begin
        theValue := theValue - Increment; 
        if (theValue < Start) then      
          theValue := Start;   {Bump at the start value}
        end;
      
      if (code = inDownButton) then     
 {See if in the down/right arrow}
        begin
        theValue := theValue + Increment; 
        if (theValue > Stop) then       
          theValue := Stop;    {Bump at the stop value}
        end;
      
      if (code = inPageUp) then     
 {See if in the up/left grey area}
        begin
        theValue := theValue - LIncrement; 
 {Subtract the page increment}
        if (theValue < Start) then      
          theValue := Start; {Bump at the Start value}
        end;
      
      if (code = inPageDown) then {down/right grey area}
        begin
        theValue := theValue + LIncrement; {page increment}
        if (theValue > Stop) then  
          theValue := Stop;   {Bump at the Stop value}
        end;
      
      if (code = inThumb) then   {drag box area}
        begin
        code := TrackControl(theControl, myPt, nil); 
 {Let the OS drag it around}
        theValue := GetCtlValue(theControl); 
 {Get current state}
        end;
      SetCtlValue(theControl, theValue); {Set new state}
    end;             {End of handle scroll bar}
  
  begin             {Handle a ScrollBar being pressed}
    RefCon := GetCRefCon(theControl);   {get control refcon}
    case RefCon of   {Select correct scrollbar}
            I_Scroll_bar:   {Scroll bar’, scroll bar}
              begin        {start for this scroll bar}
                HandleWScrollBar(code,1,10,1,10,theControl);   
 {code,Min,Max,Inc,PageInc,handle}
              end;           {end for this scroll bar}
          
          otherwise     
              begin           {start}
              end;             {end of otherwise}
    end;                       {end of case}
  end;      {Handle a ScrollBar being pressed}

  begin                 {Start of Window handler}
    if (MyWindow <> nil) then  
      begin
      code := FindWindow(myEvent.where, whichWindow); 
      if (myEvent.what = MouseDown) and (MyWindow = whichWindow) then 

        begin                  
        myPt := myEvent.where;  {Get mouse position}
        with MyWindow^.portBits.bounds do {Make it relative}
          begin
            myPt.h := myPt.h + left;
            myPt.v := myPt.v + top;
          end;       
        SetRect(tempRect,46,27,294,129); {Position of the TE}
        if PtInRect(myPt,tempRect) then {Check for pressed in the TE 
 Edit Text }
          begin                         
          theInput:= TE_I_Edit_Text;    
          TEClick(myPt, FALSE, TE_I_Edit_Text); 
          end;                          
        
        SetRect(tempRect,188,141,247,218); {Position of Pict}
        if PtInRect(myPt,tempRect) then {mouse in pict?}
          begin
 { do somethng for mouse click in pict}                        
          end;                          
         end;
      if (MyWindow = whichWindow) and (code = inContent) then  
 {for our window}
        begin 
        code := FindControl(myPt, whichWindow, theControl); 
        if (code <> 0) then   {Check type of control}
          code := TrackControl(theControl,myPt, nil); 
        if code = inButton then
          Do_A_Button;                  {Do buttons}
        if code = inCheckBox then
          Do_A_Checkbox;                {Do checkboxes}
        if (code = inUpButton) or (code = inDownButton) or (code = inThumb) 
or  (code = inPageDown) or (code = inPageUp) then
          Do_A_ScrollBar(code);         {Do scrollbars}      
        end;      {End for if (MyWindow=whichWindow)}
      end;        {End for if (MyWindow<>nil)}
  end;            {End of procedure}

{=================================} 
end.   {End of unit}

***************************************
*
* RMaker resource file sources.
* File: Prototyper_Sample.R
* History: 6/13/88 Original by Prototyper.   
* This file contains the sources for all 
* the resources except for Pictures. 
*
***************************************
*

Prototyper_Sample.RSRC
APPL????

*
* This is the definition for the DIALOG.
*
Type DLOG
*
     ,2                                 ;;Resource ID
About Dialog                            ;;Dialog title
50  120  189  427                       ;;Top Left Bottom Right
Visible NoGoAway                        ;;Visible GoAway 
1                                       ;;ProcID, dialog def ID
2                                       ;;Refcon, reference value
2                                       ;;ID of item list

*
* This is the DIALOG or ALERT item list.
*
Type DITL
*
     ,2          ;;Resource ID
2                ;;Number of controls in list

Button  Enabled  ;;Push button
100  102  129  178    ;;Top Left Bottom Right
OK                  ;;message

StaticText          ;;Static text
9  10  93  295       ;;Top Left Bottom Right
Sorry, this program really does nothing.\0D©1988 MacTutor\0D©1986 THINK 
Technologies, Inc. Certain portions of this software are copyrighted 
by THINK Technologies, Inc. ;;message

*
* This is the definition for the WINDOW.
*
Type WIND
*
     ,1               ;;Resource ID
Sample Window         ;;Window title
41  3  305  350       ;;Top Left Bottom Right
Visible  GoAway       ;;Visible GoAway 
0                     ;;ProcID, Window def ID
1                     ;;Refcon, reference value

*
* This is the CONTROL item list.
*
Type CNTL
*
   ,4                   ;;Resource ID
Button                  ;;Title for a Button
142  46  168  129       ;;Top Left Bottom Right
Visible                 ;;Initially visible 
0                       ;;ProcID (Control definition ID)
4                       ;;RefCon (reference value)
0 1 0                   ;;Min Max Value

   ,6                  ;;Resource ID
Checkbox1              ;;Title for a Checkbox
171  47  193  137      ;;Top Left Bottom Right
Visible                ;;Initially visible 
1                      ;;ProcID (Control definition ID)
6                      ;;RefCon (reference value)
0 1 1                  ;;Min Max Value

   ,17                 ;;Resource ID
Checkbox2              ;;Title for a Checkbox
190  47  212  137      ;;Top Left Bottom Right
Visible                ;;Initially visible 
1                      ;;ProcID (Control definition ID)
17                     ;;RefCon (reference value)
0 1 0                  ;;Min Max Value

   ,7                   ;;Resource ID
Radio1                  ;;Title for a RadioButton
217  47  242  139       ;;Top Left Bottom Right
Visible                 ;;Initially visible 
2                       ;;ProcID (Control definition ID)
7                       ;;RefCon (reference value)
0 1 0                  ;;Min Max Value

   ,18                 ;;Resource ID
Radio2                 ;;Title for a RadioButton
216  145  241  237     ;;Top Left Bottom Right
Visible                ;;Initially visible 
2                      ;;ProcID (Control definition ID)
18                     ;;RefCon (reference value)
0 1 1                  ;;Min Max Value

   ,5                  ;;Resource ID
Scroll bar             ;;Title for a Scrollbar
27  293  129  309      ;;Top Left Bottom Right
Visible                ;;Initially visible 
16                     ;;ProcID (Control definition ID)
5                      ;;RefCon (reference value)
1  10  1               ;;Min Max Value

*
* This is the PICTs for the Window list above.
* Move the pictures from the resource data file 
* after this is compiled.
* Type PICT
*

* This Picture is Picture
*  9                       ;;PICT Resource ID

*
* This is the definition for the MENU.
*
Type MENU
*

     ,201                   ;;Resource ID
\14                         ;;APPLE menu title
About this Sample...        ;;item title
(-                          ;;

     ,202                               ;;Resource ID
File                                    ;;menu title
Quit/Q                                  ;;item title

     ,203                               ;;Resource ID
Edit                                    ;;menu title
Undo/Z                                  ;;item title
(-                                      ;;
Cut/X                                   ;;item title
Copy/C                                  ;;item title
Paste/V                                 ;;item title
Clear                                   ;;item title
Select All                              ;;item title

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Summon your guild and prepare for war in...
Netmarble is making some pretty big moves with their latest update for Seven Knights Idle Adventure, with a bunch of interesting additions. Two new heroes enter the battle, there are events and bosses abound, and perhaps most interesting, a huge... | Read more »
Make the passage of time your plaything...
While some of us are still waiting for a chance to get our hands on Ash Prime - yes, don’t remind me I could currently buy him this month I’m barely hanging on - Digital Extremes has announced its next anticipated Prime Form for Warframe. Starting... | Read more »
If you can find it and fit through the d...
The holy trinity of amazing company names have come together, to release their equally amazing and adorable mobile game, Hamster Inn. Published by HyperBeard Games, and co-developed by Mum Not Proud and Little Sasquatch Studios, it's time to... | Read more »
Amikin Survival opens for pre-orders on...
Join me on the wonderful trip down the inspiration rabbit hole; much as Palworld seemingly “borrowed” many aspects from the hit Pokemon franchise, it is time for the heavily armed animal survival to also spawn some illegitimate children as Helio... | Read more »
PUBG Mobile teams up with global phenome...
Since launching in 2019, SpyxFamily has exploded to damn near catastrophic popularity, so it was only a matter of time before a mobile game snapped up a collaboration. Enter PUBG Mobile. Until May 12th, players will be able to collect a host of... | Read more »
Embark into the frozen tundra of certain...
Chucklefish, developers of hit action-adventure sandbox game Starbound and owner of one of the cutest logos in gaming, has released their roguelike deck-builder Wildfrost. Created alongside developers Gaziter and Deadpan Games, Wildfrost will... | Read more »
MoreFun Studios has announced Season 4,...
Tension has escalated in the ever-volatile world of Arena Breakout, as your old pal Randall Fisher and bosses Fred and Perrero continue to lob insults and explosives at each other, bringing us to a new phase of warfare. Season 4, Into The Fog of... | Read more »
Top Mobile Game Discounts
Every day, we pick out a curated list of the best mobile discounts on the App Store and post them here. This list won't be comprehensive, but it every game on it is recommended. Feel free to check out the coverage we did on them in the links below... | Read more »
Marvel Future Fight celebrates nine year...
Announced alongside an advertising image I can only assume was aimed squarely at myself with the prominent Deadpool and Odin featured on it, Netmarble has revealed their celebrations for the 9th anniversary of Marvel Future Fight. The Countdown... | Read more »
HoYoFair 2024 prepares to showcase over...
To say Genshin Impact took the world by storm when it was released would be an understatement. However, I think the most surprising part of the launch was just how much further it went than gaming. There have been concerts, art shows, massive... | Read more »

Price Scanner via MacPrices.net

Apple Watch Ultra 2 now available at Apple fo...
Apple has, for the first time, begun offering Certified Refurbished Apple Watch Ultra 2 models in their online store for $679, or $120 off MSRP. Each Watch includes Apple’s standard one-year warranty... Read more
AT&T has the iPhone 14 on sale for only $...
AT&T has the 128GB Apple iPhone 14 available for only $5.99 per month for new and existing customers when you activate unlimited service and use AT&T’s 36 month installment plan. The fine... Read more
Amazon is offering a $100 discount on every M...
Amazon is offering a $100 instant discount on each configuration of Apple’s new 13″ M3 MacBook Air, in Midnight, this weekend. These are the lowest prices currently available for new 13″ M3 MacBook... Read more
You can save $300-$480 on a 14-inch M3 Pro/Ma...
Apple has 14″ M3 Pro and M3 Max MacBook Pros in stock today and available, Certified Refurbished, starting at $1699 and ranging up to $480 off MSRP. Each model features a new outer case, shipping is... Read more
24-inch M1 iMacs available at Apple starting...
Apple has clearance M1 iMacs available in their Certified Refurbished store starting at $1049 and ranging up to $300 off original MSRP. Each iMac is in like-new condition and comes with Apple’s... Read more
Walmart continues to offer $699 13-inch M1 Ma...
Walmart continues to offer new Apple 13″ M1 MacBook Airs (8GB RAM, 256GB SSD) online for $699, $300 off original MSRP, in Space Gray, Silver, and Gold colors. These are new MacBook for sale by... Read more
B&H has 13-inch M2 MacBook Airs with 16GB...
B&H Photo has 13″ MacBook Airs with M2 CPUs, 16GB of memory, and 256GB of storage in stock and on sale for $1099, $100 off Apple’s MSRP for this configuration. Free 1-2 day delivery is available... Read more
14-inch M3 MacBook Pro with 16GB of RAM avail...
Apple has the 14″ M3 MacBook Pro with 16GB of RAM and 1TB of storage, Certified Refurbished, available for $300 off MSRP. Each MacBook Pro features a new outer case, shipping is free, and an Apple 1-... Read more
Apple M2 Mac minis on sale for up to $150 off...
Amazon has Apple’s M2-powered Mac minis in stock and on sale for $100-$150 off MSRP, each including free delivery: – Mac mini M2/256GB SSD: $499, save $100 – Mac mini M2/512GB SSD: $699, save $100 –... Read more
Amazon is offering a $200 discount on 14-inch...
Amazon has 14-inch M3 MacBook Pros in stock and on sale for $200 off MSRP. Shipping is free. Note that Amazon’s stock tends to come and go: – 14″ M3 MacBook Pro (8GB RAM/512GB SSD): $1399.99, $200... Read more

Jobs Board

*Apple* Systems Administrator - JAMF - Syste...
Title: Apple Systems Administrator - JAMF ALTA is supporting a direct hire opportunity. This position is 100% Onsite for initial 3-6 months and then remote 1-2 Read more
Relationship Banker - *Apple* Valley Financ...
Relationship Banker - Apple Valley Financial Center APPLE VALLEY, Minnesota **Job Description:** At Bank of America, we are guided by a common purpose to help Read more
IN6728 Optometrist- *Apple* Valley, CA- Tar...
Date: Apr 9, 2024 Brand: Target Optical Location: Apple Valley, CA, US, 92308 **Requisition ID:** 824398 At Target Optical, we help people see and look great - and Read more
Medical Assistant - Orthopedics *Apple* Hil...
Medical Assistant - Orthopedics Apple Hill York Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Now Read more
*Apple* Systems Administrator - JAMF - Activ...
…**Public Trust/Other Required:** None **Job Family:** Systems Administration **Skills:** Apple Platforms,Computer Servers,Jamf Pro **Experience:** 3 + years of Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.