TweetFollow Us on Twitter

Window Ports
Volume Number:1
Issue Number:5
Column Tag:PASCAL PROCEDURES

Windows provide a front end to ports

By Chris Derossi

In the last issue of MacTutor, we introduced briefly the concept of graph ports and how they can make both programming and usage easier and more intuitive. However, the way that we used the ports, the programmer had to keep track of everything. It is fairly obvious that there will be several features that you, as a programmer, would want to associate with ports frequently if not all the time. It is for this reason that windows exist.

Windows provide a front end to ports, making them more easy to use and providing you with several options and features. The Window Manager in the Macintosh Toolbox takes care of the tedious tasks for you. For example, in our last program, we had to do everything with the port, including erasing it to white and drawing the border around the port. It is simple things like this, that you need for every port, that the Window Manager handles.

In addition to taking care of the low level drawing, windows also provide you with more complex options. I’m sure that you’ve seen the title bar on document windows, and the scroll bar controls are standard, too. The Window Manager also sets the window’s coordinate system to local coordinates, with the point (0,0) at the upper left corner of the window. Also handled for you is the setting of the various regions. And, unlike ports, windows can handle overlapping and res- toration of the window contents.

Let’s back up a moment and take a look at the various different window kinds. There are four standard windows in the Macintosh, and you may create your own.

The four standard windows are shown in figure #1. Each type has an associated function on the Mac. Window type #0 is for documents, folders, and disks. Window type #1 is the normal dialog and alert box window, with the shadow border.

Type #2 is like type #1, but without a border. Type #16 is usually found as the window for a desk accessory. Types #0 and #16 have titles, while the other two do not.

Fig. 1

For each type of window, the Window Manager handles drawing of the border and title bar. To do this, each window must have associated with it information about the type of window, and the title for that window. In fact, the magic about windows is just that: associating various things with a particular window.

Of course, the heart of the window is a GrafPort. Each window is its own port, and is unrelated to other windows. The rules for windows are the same as those for ports discussed last time. As you might have guessed, some of the other things associated with each window include window type and title string. There are also several status flags that are kept with each window that keep track of things like whether or not the window is visible, and if it is if it’s hilited.

Figure #2 shows a rough outline of a window record. Some of the fields are not shown, and many other are grouped under the heading ‘Window Stuff’. We will worry about these at a later time. The very first thing in the record is the GrafPort. After that comes most of the window flags and status variables. The windowDefProc is a handle to the procedure that draws the window. This is the procedure that handles the title bar and the border. The four standard windows each have a DefProc. You may create your own window definition procedure and have the Window Manager use it to draw the window.

The titleHandle is a handle to a string in memory. This is how the title is related to the window. Since controls are also associated with windows, a handle to a list of controls is also included in the record. More about this at a later time.

The next field is very important. The field nextWindow is a pointer to the next window record in a linked-list type data structure. By using this field, the Window Manager knows which window to hilite and make active if you get rid of the currently active one. Also, by using this sceme, the Window Manager needs to keep track of only one Window Record, and follow the pointer chain till it finds the one it wants.

Finally there is a field called refCon. This field has nothing at all to do with the window itself. Apple put that field there for your own use. You may have data associated with one of your windows, or a value assoctiated with it. You may use this field as a pointer, handle, integer, or long integer. (Some type conversion may be needed, but you have enough bytes for any of those constructs.)

As with ports and other things, there are toolbox procedures and functions that create, destroy, modify, and control windows. The usual parameter passed to these routines is a WindowPtr, a pointer that points directly to the window record. In many cases, the Window Manager is looking for the data type GrafPtr instead of WindowPtr. This works because there is an entire GrafPort at the beginning of the window record.

Inline Trap Calls From Pascal

We’ll come back to windows in a moment; right now let’s discuss the method for getting to toolbox routines that don’t have a MacPascal interface. (Window routines are in this catagory.)

MacPascal has some built in procedures and functions that call the Macintosh ROM, and even more routines in separate libraries. However, these routines fall very short of covering the entire set of toolbox utilities. For example, there is a toolbox function called ‘OpenWindow’, but there is no library available for MacPascal where this function is defined. Normally, there would be no way to interface to this and other similar routines, but realizing that doing so would be a common and important need, MacPascal has a short-cut set of routines known as InLines.

The InLine procedures and functions allow direct access to the Macintosh internals. Macintosh ROM routines are accessed by a thing called a trap vector. When the 68000 microprocessor comes upon an instruction that begins with a certain series of bits (1010, or $A in hex), it looks up an address in a RAM table and jumps to it without question. The Mac ROM and the System program are resposible for setting up this table. It is through this method that routines in the ROM are accessed.

[NOTE: The trap mechanism has several advantages. First, as a programmer, you don’t have to know the exact location of the routines you want to use. This allows the RAM table to change, and allows bugs to be repaired by replacing the ROM routine with a better one in RAM and updating the table. Also, you don’t need to use the bytes neccessary for a subroutine call. Instead, you need only the two-byte trap value. Lastly, the RAM table can be modified to create several nice effects. For example, you can intercept ALL of the traps to find out what’s happing when debugging. Also, you can replace the ROM routines with your own routines that are better or different. All in all, trap vectors provide for a more verstile computer.]

The use of the InLine procedure call is fairly straightforward. The only mandatory parameter is the trap vector value. Each Mac ROM routine has a different trap vector value. You need to know what the trap vector is for the routine you wish to use. (Some of the window manager and quickdraw vectors are included this month. Look for a complete list in a later issue.)

Do Your Own Type Checking!

Many of the procedures require parameters. You may simply pass these parameters after the trap value. You may place as many parameters as you need in the call, and the parameters may be of ANY type. The InLine calls short cicuit the normal type checking of MacPascal. For this reason, you should know exactly what you are doing when using an InLine call. If you pass a bad set of parameters, your Mac could crash and you could lose all data in memory and on disk!

There are two methods for passing parameters, by value and by reference. Simple data types (i.e. predefined) are passed by value unless they are VAR parameters. The simple data types include Integer, LongInt, Boolean, Char, Pointer, and Handle. All other data types are complex. Complex data types and VAR parameters are passed by reference. When a parameter is passed by value, the actual value of the parameter is placed on the stack. When passing by reference, a POINTER to the data is placed on the stack.

Since the InLine procedures are dumb, you must control what happens. Passed by value parameters can be passed normally, and complex types can be passed normally too as MacPascal knows to place a pointer on the stack. When you have a simple data type that is supposed to be a VAR parameter, you MUST force MacPascal to pass a pointer, not the data itself. To do this, use the @ function, which returns a pointer to the argument. For example, suppose that we have a variable MyNum which is of type integer. To pass the value of MyNum, you would pass MyNum itself. If you needed a VAR parameter, you would have to pass @MyNum.

The InLine call for procedures is InLineP(Trap, parm1, parm2, ...); You may have zero one or more parameters. There are three InLine calls for functions. Since InLine does not know what size value is to be passed back as the return value, a different call is provided for each type. When a value of size one byte is to be returned, use BInLineF(Trap, parms...). For two-byte long results, use WInLineF(Trap, parms...). W is for Word which is two bytes. L is for LongWord which is four bytes, which is the size of longints, pointers, and handles, so use LInLineF(Trap,parms...).

Freedom From Large Libraries

Using InLine calls does not require any MacPascal libraries; InLine calls are built directly in to MacPascal. There is nothing to stop you from using InLine calls to the ROM even when equivalent routines already exist. In fact, there is a reson to do so. When you need any one procedure or function from a library, the entire library is loaded into memory. If you only need one function, most of the RAM being used by the other functions is wasted. By using a single InLine call instead of loading the entire library, you can save a significant amount of memory for your own data.

[NOTE: ANY single reference to the simple QuickDraw functions causes MacPascal to load the library QuickDraw1. In other words, even though you didn’t have to do a ‘uses QuickDraw1’, it still happens, and you might consider replacing the calls with InLines.]

Now that you know how to access the Window Manager routines, let’s look at the sample program. This month, the sample program is just a vehicle for the program’s sole procedure, ‘Message’. This procedure stands by itself, does not require any librarys, and may be ported to your own program. (With the exception of the type MsgArray, which must be declared before the procedure Message is.)

The procedure Message takes four inputs. First and second are the message you wish displayed. The first parameter is the number if lines of the array to use. The second is the array itself. Other methods could have been used, but we’ll talk about that at the end. The next parameter is the window type, and can have values 0, 1, 2, or 16, corresponding to the window types in figure #1. Finally, a delay value is provided if you want to slow the output for effect.

DISPOSE should be Disposed of!

To create a window, it is neccessary to provide the space for the window record. One way to do this would be to declare the entire window record type, but that is quite large. Instead, the size of the record is known to be 156 bytes. By declaring the record as an array of 78 integers, we achieve the same size data structure. Also, instead of using the built in NEW procedure which allocates the memory, we create the variable ourselves. The reason for this is that the DISPOSE procedure that deallocates the memory doesn’t work, and the memory never becomes free. Instead, we declare the variable, and its memory is freed when the procedure terminates.

AVOID A QUICKDRAW1 LOAD

The InLine call to SetRect creates the window’s rectangle. Notice that an InLine call is used to avoid loading QuickDraw1. Also, Rect is defined separately as well. (ANY reference to the data types in QuickDraw1 causes QuickDraw1 to be loaded.) Then, the InLine call for OpenWindow is executed. The Window Manager takes care of setting up the grafport, drawing the window, erasing it to white, and drawing the title bar if it has one. When this call is complete, the window will be on the screen.

Normally, this would cause the window to become the current grafport, but because MacPascal handles graphics and text in different windows, and therefore keeps changing the current port, it is a good idea to do a SetPort call. Once the window is set to be the current port, a simple loop calls DrawChar to place each character in the window.

When the loop terminates, the procedure waits for a mouse press and release. The call to the ROM routine Button is built into MacPascal, and no libraries need to be read. The procedure then closes the window and terminates. The Window Manager erases the window.

As an exercise, you may wish to modify the Message procedure directly. There is nothing to stop you from doing more elaborate drawing in the window. You might want to create your own alert procedures that draw bombs or other icons in the window. Additionally, you may want to pass the windows title and rectangle to Message. You could also delete the delay if you don’t want it.

That covers the basic introduction to windows. In the next issue, we’ll talk about how to handle multiple windows, even overlapping ones. Also, we’ll discuss the use of controls in general, and controls in windows. Up till now, we’ve limited ouselves to Button and GetMouse. The use of controls will greatly enhance our ability to receive input from the user. As you can see, windows with all their associated features provide you with a very powerul set of tool. Ciao.


program Window_Example;

{ This is the sample program for the} 
{ April issue of MacTutor Magazine.}
{ The main part of this program is only a}
{ front end for the procedure}
{ called ‘Message’. You can take the}
{ message procedure into your own}
{ programs as it stands.}
{ by -- Chris Derossi}

 const
  MaxLines = 5;

 type
  MsgArray = 
     array[1..MaxLines] of Str255;

 var
  MyMsg : MsgArray;

 procedure Message 
   (Lines : INTEGER;
    Msg : MsgArray;
    WindKind, Delay : INTEGER);

{ This procedure is the heart of this}
{ month’s sample program. It will}
{ open a window on the desktop, display}
{ your message using the delay,}
{ and then wait for a press of the mouse}
{ button before it closes the}
{ window and returns.}

  const

{Window Manager Traps}
   NewWindow = $A913;
   CloseWindow = $A92D;
{QuickDraw Traps}
   SetRect = $A8A7;
   SetPort = $A873;
   MoveTo = $A893;
   DrawChar = $A883;

  type
   Rect : array[1..4] of INTEGER;
   WindowRecord = array[1..78] of Integer;
   WindowPtr = ^WindowRecord;

  var
   Count, X, Index : INTEGER;
   Dummy : LongInt;
   TheWindow : WindowPtr;
   WindowStorage : WindowRecord;
   BoundsRect : Rect;

 begin

{ Initialize memory, and open a new}
{ window. }

  TheWindow := @WindowStorage;
  InLineP(SetRect, @BoundsRect,
              40, 50, 390, 140);
  Dummy := LInLineF(NewWindow, 
                                TheWindow,
                                BoundsRect,
                                ‘Message Window ‘,
                                TRUE,
                                WindKind,
                                Pointer(-1),
                                FALSE,
                                0 + 0);
  InLineP(SetPort, TheWindow);

{ Output the message, character by}
{ character. }

  for Index := 1 to Lines do
   begin
    X := Index * 15;
    InLineP(MoveTo, 5, X);
    if LENGTH(Msg[Index]) > 0 then
    for Count := 1 to LENGTH(Msg[Index]) do
    begin
    for X := 1 to Delay do
    ; {Nothing, just loop for a pause}
    InLineP(DrawChar, Msg[Index][Count]);
    end;
   end;

{ Wait for a button press and release.}

  repeat
  until Button;
  repeat
  until not Button;

{ Get rid of the window.}

  InLineP(CloseWindow, TheWindow);
 end;


begin {Window_Example}
 HideAll;
 MyMsg[1] := ‘ ‘;
 MyMsg[2] := ‘Your example program that  demonstrates windows’;
 MyMsg[3] := ‘has now begun.’;
 Message(3, MyMsg, 16, 0);

 MyMsg[1] := ‘You can produce your own   error messages and alert’;
 MyMsg[2] := ‘boxes in your MacPascal programs.’;
 Message(2, MyMsg, 1, 75);

 MyMsg[1] := ‘Pause and prompt for a press of the mouse button.’;
 Message(1, MyMsg, 2, 75);

 MyMsg[1] := ‘You can also post brief  instructions for your’;
 MyMsg[2] := ‘users at any time while the   program is running.’;
 Message(2, MyMsg, 0, 100);

 MyMsg[1] := ‘ ‘;
 MyMsg[2] := ‘ ‘;
 MyMsg[3] := ‘ ‘;
 MyMsg[4] := ‘This demonstration program is now over.’;
 Message(4, MyMsg, 16, 0);
end.
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Challenge those pesky wyverns to a dance...
After recently having you do battle against your foes by wildly flailing Hello Kitty and friends at them, GungHo Online has whipped out another surprising collaboration for Puzzle & Dragons. It is now time to beat your opponents by cha-cha... | Read more »
Pack a magnifying glass and practice you...
Somehow it has already been a year since Torchlight: Infinite launched, and XD Games is celebrating by blending in what sounds like a truly fantastic new update. Fans of Cthulhu rejoice, as Whispering Mist brings some horror elements, and tests... | Read more »
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 »

Price Scanner via MacPrices.net

Free iPhone 15 plus Unlimited service for $60...
Boost Infinite, part of MVNO Boost Mobile using AT&T and T-Mobile’s networks, is offering a free 128GB iPhone 15 for $60 per month including their Unlimited service plan (30GB of premium data).... Read more
$300 off any new iPhone with service at Red P...
Red Pocket Mobile has new Apple iPhones on sale for $300 off MSRP when you switch and open up a new line of service. Red Pocket Mobile is a nationwide MVNO using all the major wireless carrier... Read more
Clearance 13-inch M1 MacBook Airs available a...
Apple has clearance 13″ M1 MacBook Airs, Certified Refurbished, available for $759 for 8-Core CPU/7-Core GPU/256GB models and $929 for 8-Core CPU/8-Core GPU/512GB models. Apple’s one-year warranty is... Read more
Updated Apple MacBook Price Trackers
Our Apple award-winning MacBook Price Trackers are continually updated with the latest information on prices, bundles, and availability for 16″ and 14″ MacBook Pros along with 13″ and 15″ MacBook... Read more
Every model of Apple’s 13-inch M3 MacBook Air...
Best Buy has Apple 13″ MacBook Airs with M3 CPUs in stock and on sale today for $100 off MSRP. Prices start at $999. Their prices are the lowest currently available for new 13″ M3 MacBook Airs among... Read more
Sunday Sale: Apple iPad Magic Keyboards for 1...
Walmart has Apple Magic Keyboards for 12.9″ iPad Pros, in Black, on sale for $150 off MSRP on their online store. Sale price for online orders only, in-store price may vary. Order online and choose... Read more
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

Jobs Board

Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Operations Associate - *Apple* Blossom Mall...
Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
IT Systems Engineer ( *Apple* Platforms) - S...
IT Systems Engineer ( Apple Platforms) at SpaceX Hawthorne, CA SpaceX was founded under the belief that a future where humanity is out exploring the stars is 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.