TweetFollow Us on Twitter

TextBoxer
Volume Number:8
Issue Number:3
Column Tag:Getting Started

Related Info: Quickdraw TextEdit Window Manager

TextBoxer

A vehicle for experimenting with QuickDraw's text and shape-drawing routines

By Dave Mark, MacTutor Regular Contributing Author

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

About the author

Dave Mark is an accomplished Macintosh author and an Apple Partner. He is the author of The Macintosh Programming Primer Series which includes: Macintosh C Programming Primer, Volumes 1 and 2; Macintosh Pascal Programming Primer, Volume 1, and his latest book, Learn C on the Macintosh. These books are available through the MacTutor Mail Order Store located in the back of the magazine. Dave is also the “professor” on the Learn Programming Forum on CompuServe. To get there, type GO MACDEV, then check out section 11.

In last months column, we covered the basics of programming using windows and QuickDraw. The Macintosh Toolbox was introduced, and a function was presented that properly initializes the Toolbox. This month, we’ll dig a little deeper into the relationship between windows and QuickDraw.

TextBoxer: Still Life With Text and QuickDraw

This months application, TextBoxer, gives you a vehicle to experiment with QuickDraw’s text and shape-drawing routines. In its initial incarnation, TextBoxer creates the window shown in Figure 1. Notice that the content region of the window contains two rectangle (one inside the other), as well as a text string.

Figure 1. TextBoxer in action.

Creating the TextBoxer Project

Launch THINK C, creating a new project called TextBoxer.Π (The Π character is created by typing option-p). THINK C will create a project window with the title TextBoxer.Π. Select New from the File menu to create a new source code window. Type the following source code into the window:

/* 1*/

#define kVisible false
#define kMoveToFront (WindowPtr)-1L
#define kNoGoAwayfalse
#define kNilRefCon 0L
#define kPascalString“\pAll applaud the strongly-jawed”
#define kFontSize12
#define kBottomOffset7
#define kLeftOffset7

void    ToolBoxInit( void );
WindowPtr WindowInit( void );

/****************** main ************/
main()
{
 Rect   shapeRect;
 WindowPtrwindow;
 
 ToolBoxInit();
 window = WindowInit();
 
 shapeRect = window->portRect;
 
 InsetRect( &shapeRect, 5, 5 );
 FrameRect( &shapeRect );
 
 InsetRect( &shapeRect, 2, 2 );
 FrameRect( &shapeRect );
 
 TextFont( monaco );
 TextSize( kFontSize );
 MoveTo( shapeRect.left + kLeftOffset,
 shapeRect.bottom - kBottomOffset );
 DrawString( kPascalString );
 
 while ( ! Button() ) ;
}

/****************** ToolBoxInit ***********/
void  ToolBoxInit( void )
{
 InitGraf( &thePort );
 InitFonts();
 InitWindows();
 InitMenus();
 TEInit();
 InitDialogs( nil );
 InitCursor();
}
/****************** WindowInit *************/
WindowPtr WindowInit( void )
{
 WindowPtrwindow;
 Rect   windowRect;
 
 SetRect( &windowRect, 20, 40, 260, 74 );

 window = NewWindow( nil, &windowRect, “\pBox o’ Text”,
 kVisible, documentProc, kMoveToFront,
 kNoGoAway, kNilRefCon );
 
 if ( window == nil )
 {
 SysBeep( 10 );  /*  Couldn’t create a window!!!  */
 ExitToShell();
 }
 
 ShowWindow( window );
 SetPort( window );
 
 return( window );
}

Select Save from the File menu and save the source code under the name TextBoxer.c. Next, select Add (not Add...) from the Source menu to add TextBoxer.c to the project. Finally, select Add... from the Source menu and add the MacTraps library to the project. You’ll find MacTraps inside your Development folder, inside the THINK C Folder, inside the Mac Libraries folder. As mentioned last month, MacTraps contains the interfaces to the routines that make up the Macintosh Toolbox.

Once MacTraps has been added to the project, the project window should look like the one shown in Figure 2.

Figure 2. The TextBoxer project window, before compilation.

Running TextBoxer.Π

Select Run from the Project menu, asking THINK C to compile and run your project. If you run into any compile or link errors, check the code over carefully. Once your project runs, you should see something similar to Figure 3. To exit TextBoxer, just click the mouse button.

Figure 3. Running TextBoxer.

Walking Through the Source Code

TextBoxer.c consists of three routines, main(), ToolBoxInit(), and WindowInit(). As usual, we start off by defining some useful constants. I’ll explain each of these as they occur in context.

/* 2 */

#define kVisible false
#define kMoveToFront (WindowPtr)-1L
#define kNoGoAwayfalse
#define kNilRefCon 0L

#define kPascalString“\pAll applaud the strongly-jawed”
#define kFontSize12
#define kBottomOffset7
#define kLeftOffset7

Next come the function prototypes. Be sure to prototype all your functions. This practice will go a long way towards catching compile errors.

/* 3 */

void    ToolBoxInit( void );
WindowPtr WindowInit( void );

main() starts off with a couple of local variable declarations. shapeRect is declared to be of type Rect. Rect is a widely used Toolbox type and is defined in Inside Macintosh. A Rect has four fields: left, top, right, and bottom. Typically, you’ll fill a Rect’s fields so they define the position and size of a rectangle.

You can set the fields of a Rect individually, like this:

/* 4 */

Rect  myRect;

myRect.left = 20;
myRect.top = 30;
myRect.right = 40;
myRect.bottom = 50;

or you can use a Toolbox routine like SetRect(). SetRect() is defined in IM(I:174):

/* 5 */

SetRect( Rect *myRect, int left, int top, int right, int bottom );

The second local variable in main() is window, used to store a pointer to the TextBoxer window.

/* 6 */

/****************** main ************/

main()
{
 Rect   shapeRect;
 WindowPtrwindow;

Next, main() calls ToolBoxInit() to initialize the Macintosh Toolbox. As mentioned last month, with few exceptions, every Mac program you write will start off this way. Once the Toolbox is initialized, you can call the Toolbox as much as you like.

/* 7 */

 ToolBoxInit();

Once the Toolbox is initialized, we’ll call WindowInit() to create our window. WindowInit() returns a WindowPtr, an extremely important Toolbox data type. A WindowPtr is a pointer to a GrafPort, QuickDraw’s basic data structure:

/* 8 */

struct GrafPort {
    short device;
    BitMap portBits;
    Rect portRect;
    RgnHandle visRgn;
    RgnHandle clipRgn;
    Pattern bkPat;
    Pattern fillPat;
    Point pnLoc;
    Point pnSize;
    short pnMode;
    Pattern pnPat;
    short pnVis;
    short txFont;
    Style txFace;
    char filler;
    short txMode;
    short txSize;
    Fixed spExtra;
    long fgColor;
    long bkColor;
    short colrBit;
    short patStretch;
    Handle picSave;
    Handle rgnSave;
    Handle polySave;
    QDProcsPtr grafProcs;
};
typedef GrafPort *GrafPtr;
typedef GrafPtr WindowPtr;

Typically, you’ll create a GrafPort, customize it, draw in it, and eventually dispose of it. When you create a new window, a GrafPort is automatically created for you. For example, the Toolbox function NewWindow() creates a WindowRecord:

/* 9 */

struct WindowRecord {
    GrafPort port;
    short windowKind;
    Boolean visible;
    Boolean hilited;
    Boolean goAwayFlag;
    Boolean spareFlag;
    RgnHandle strucRgn;
    RgnHandle contRgn;
    RgnHandle updateRgn;
    Handle windowDefProc;
    Handle dataHandle;
    StringHandle titleHandle;
    short titleWidth;
    ControlHandle controlList;
    struct WindowRecord *nextWindow;
    PicHandle windowPic;
    long refCon;
};

typedef struct WindowRecord WindowRecord;
typedef WindowRecord *WindowPeek;

Notice that the first field in the WindowRecord is a GrafPort. The WindowPtr returned by NewWindow() is actually a pointer to this GrafPort. You can cast the WindowPtr to the type WindowPeek when you want to access the rest of the fields in the WindowRecord.

Though this may seem confusing, it’s actually quite easy, once you get used to it. As we go over more and more examples, you’ll learn how to create and manage your own windows and GrafPorts. Let’s get back to the TextBoxer code.

As we said earlier, WindowInit() creates a new WindowRecord (and, therefore, a GrafPort as well). The WindowPtr returned by WindowInit() is a pointer to the GrafPort embedded in the WindowRecord.

/* 10 */

 window = WindowInit();

The window’s portRect field is a Rect that defines the boundary of the window in screen pixels. On a typical Macintosh, the upper left corner of the screen corresponds to the (x,y) coordinate 0, 0. As you move to the right, the x coordinate increases. As you move down the screen, the y coordinate increases. The coordinates of the main screen serve as a reference point to all the GrafPorts on the screen and are known as global coordinates. Each GrafPort you create has its own coordinate system, known as local coordinates.

Figure 4 shows the point (0,0) in global coordinates. It also shows the point (0,0) in a window’s local coordinate system. Typically, a window’s local coordinates start in the upper left corner of the window’s content region. The content region starts just below the window’s title bar, if it has one.

The window’s portRect field is copied into a local variable, shapeRect. We’ll inset the Rect (make it uniformally smaller) by 5 pixels in each direction, then call the drawing routine FrameRect() to draw a one pixel rectangle using this inset Rect as a guide. This rectangle will appear 5 pixels inside the border of the window’s content region.

/* 11 */

 shapeRect = window->portRect;
 
 InsetRect( &shapeRect, 5, 5 );
 FrameRect( &shapeRect );

Figure 4. The point (0,0) in both global and local coordinates.

Next, we’ll inset the Rect 2 more pixels and frame another rectangle inside the first. InsetRect() is described in IM(I:175). FrameRect() is described in IM(I:176). Later in the column, we’ll discuss some of the other functions that relate to drawing.

/* 12 */

 InsetRect( &shapeRect, 2, 2 );
 FrameRect( &shapeRect );

Once the rectangles are drawn, we’re ready to tackle the text. First, we’ll set the current font to monaco, then we’ll set the font size to kFontSize. It’s important to note that we’ve only made this change to the current port. If we had two windows set up, we could set one window to use 18 point Geneva, and the other to 24 point Times. You’ll see how to set the current port when we discuss WindowInit()

/* 13 */

 TextFont( monaco );
 TextSize( kFontSize );

Every GrafPort has a pen associated with it. The location of the pen determines where the next drawing operation will take place. Several of the QuickDraw drawing routines produce results based strictly on the location of this pen. One of these routines is DrawString(), a routine that draws a pascal string in the current port, at the current pen location. The function MoveTo() sets the pen location using the local coordinates of the current GrafPort.

/* 14 */

 MoveTo( shapeRect.left + kLeftOffset, shapeRect.bottom - kBottomOffset 
);

DrawString() draws the text using the current pen location as the left side of the baseline of the first character in the specified string. Remember, pascal strings start with a length byte, followed by that number of characters (up to 255). In THINK C, you can specify a pascal string by starting your string with the characters \p (look at the #define for kPascalString above).

/* 15 */

 DrawString( kPascalString );

Finally, leave the window up there till the mouse button is clicked.

/* 16 */

 while ( ! Button() ) ;
}

ToolBoxInit() is the same as it was in last month’s column.

/* 17 */


/****************** ToolBoxInit ***********/

void  ToolBoxInit( void )
{
 InitGraf( &thePort );
 InitFonts();
 InitWindows();
 InitMenus();
 TEInit();
 InitDialogs( nil );
 InitCursor();
}

WindowInit() will create a new window and return a pointer to it.

/* 18 */

/****************** WindowInit *************/

WindowPtr WindowInit( void )
{
 WindowPtrwindow;
 Rect   windowRect;

For starters, SetRect() is used to set windowRect to the global coordinates we’d like our window to appear at.

/* 19 */

 SetRect( &windowRect, 20, 40, 260, 74 );

Next, NewWindow() is called to create the new window. Check out last months column for more info on NewWindow() and its parameters.

/* 20 */

 window = NewWindow( nil, &windowRect, "\pBox o’ Text",
 kVisible, documentProc, kMoveToFront,
 kNoGoAway, kNilRefCon );

If the window could not be created, NewWindow() will return nil. In that case, we beep once and exit.

/* 21 */

 if ( window == nil )
 {
 SysBeep( 10 );  /*  Couldn't create a window!!!  */
 ExitToShell();
 }

Since the constant kVisible (passed as a parameter to NewWindow()) was set to false, the window is not visible upon creation. That’s ShowWindow()’s job! ShowWindow() makes the specified window visible and HideWindow() makes the window invisible.

Try commenting out the call to ShowWindow() to find out what an invisible window looks like.

/* 22 */

 ShowWindow( window );

SetPort() makes the specified window the current port. Use SetPort() to switch between multiple GrafPorts.

/* 23 */

 SetPort( window );

Finally, we return the pointer to our newly created window.

/* 24 */

 return( window );
}

More Routines to Play With

QuickDraw allows you to do a lot more than frame rectangles. On one hand, you can use routines such as FrameOval(), FrameRoundRect(), and FrameArc() to frame each of the different QuickDraw shapes. On the other hand, for each shape you can perform paint, erase, invert, and fill operations in addition to the framing already discussed. For example, check out the QuickDraw routines PaintRect(), EraseRect(), InvertRect(), and FillRect().

These routines are completely described in Inside Macintosh, Volume I, Chapter 6. Be sure to check the parameters for each routine. Different shapes require different parameters.

I would strongly recommend that you read the aforementioned QuickDraw chapter from cover to cover. Play around with TextBoxer. Try different fonts and font sizes. Take a look at the file Quickdraw.h found in the THINK C Folder, in the Mac #includes folder, inside the Apple #includes folder. You’ll find constants for the basic Mac fonts and a list of the different QuickDraw Toolbox routines.

Next Month...

In next month’s column, we’ll poke around some of QuickDraw’s nooks and crannies. We’ll also learn about resources, the Mac’s mechanism for separating data from code. For those of you on baby-watch, there are only eight more weeks to go!!! Got any suggestions for the best type of car seat, crib, swing, diapers, bottles, etc. to buy? Let me know. I could sure use the help!

As always, you can reach me on CompuServe in MACDEV, Section 11 (Learn Programming).

 
AAPL
$118.72
Apple Inc.
+1.12
MSFT
$47.50
Microsoft Corpora
+0.03
GOOG
$539.23
Google Inc.
-1.85

MacTech Search:
Community Search:

Software Updates via MacUpdate

RapidWeaver 6.0.3 - Create template-base...
RapidWeaver is a next-generation Web design application to help you easily create professional-looking Web sites in minutes. No knowledge of complex code is required, RapidWeaver will take care of... Read more
iPhoto Library Manager 4.1.10 - Manage m...
iPhoto Library Manager lets you organize your photos into multiple iPhoto libraries. Separate your high school and college photos from your latest summer vacation pictures. Or keep some photo... Read more
iExplorer 3.5.1.9 - View and transfer al...
iExplorer is an iPhone browser for Mac lets you view the files on your iOS device. By using a drag and drop interface, you can quickly copy files and folders between your Mac and your iPhone or... Read more
MacUpdate Desktop 6.0.3 - Discover and i...
MacUpdate Desktop 6 brings seamless 1-click installs and version updates to your Mac. With a free MacUpdate account and MacUpdate Desktop 6, Mac users can now install almost any Mac app on macupdate.... Read more
SteerMouse 4.2.2 - Powerful third-party...
SteerMouse is an advanced driver for USB and Bluetooth mice. It also supports Apple Mighty Mouse very well. SteerMouse can assign various functions to buttons that Apple's software does not allow,... Read more
iMazing 1.1 - Complete iOS device manage...
iMazing (was DiskAid) is the ultimate iOS device manager with capabilities far beyond what iTunes offers. With iMazing and your iOS device (iPhone, iPad, or iPod), you can: Copy music to and from... Read more
PopChar X 7.0 - Floating window shows av...
PopChar X helps you get the most out of your font collection. With its crystal-clear interface, PopChar X provides a frustration-free way to access any font's special characters. Expanded... Read more
Carbon Copy Cloner 4.0.3 - Easy-to-use b...
Carbon Copy Cloner backups are better than ordinary backups. Suppose the unthinkable happens while you're under deadline to finish a project: your Mac is unresponsive and all you hear is an ominous,... Read more
ForeverSave 2.1.3 - Universal auto-save...
ForeverSave auto-saves all documents you're working on while simultaneously doing backup versioning in the background. Lost data can be quickly restored at any time. Losing data, caused by... Read more
Voila 3.8.1 - Capture, annotate, organiz...
Voila is a screen-capture, recording, and annotation tool that is a full-featured replacement for Mac's screen-capture and screen-recording capabilities. It has a large and robust set of editing,... Read more

Latest Forum Discussions

See All

Tales from the Borderland​s Will be Comi...
Tales from the Borderland​s Will be Coming to iOS by the End of the Year Posted by Jessica Fisher on November 26th, 2014 [ permalink ] Telltale Games has announced | Read more »
Sunburn! Review
Sunburn! Review By Campbell Bird on November 26th, 2014 Our Rating: :: DON'T DIE ALONEUniversal App - Designed for iPhone and iPad Platform through the depths of space to make sure your entire crew dies together in this satisfying... | Read more »
Black Friday has Started Early – Lots an...
It’s almost turkey time! Which means lots and lots of food but also lots and lots of sales. Some sales have even started a few days early, which is why we’ve put together a list of iOS games that are currently discounted (sometimes by a lot).... | Read more »
Loose Leaf Review
Loose Leaf Review By Jennifer Allen on November 26th, 2014 Our Rating: :: SIMPLE SKETCHINGiPad Only App - Designed for the iPad Sketch out ideas with simple drawing tools, courtesy of Loose Leaf.   | Read more »
Screeny (Utilities)
Screeny 1.0 Device: iOS iPhone Category: Utilities Price: $.99, Version: 1.0 (iTunes) Description: Screeny is an utility app that helps you save space consumed by screenshots. It screens your camera roll and helps you to filter and... | Read more »
Tilt to Live Bundle Set to Arrive This T...
Tilt to Live Bundle Set to Arrive This Thanksgiving Posted by Ellis Spice on November 25th, 2014 [ permalink ] One Man Left has unveiled an upcoming Tilt to Live bundle, allowing players to get the series for a di | Read more »
BattleLore: Command (Entertainment)
BattleLore: Command 1.0 Device: iOS Universal Category: Entertainment Price: $9.99, Version: 1.0 (iTunes) Description: ***NOTE: Compatible with iPad 2/iPad mini, iPod touch 5 and up and iPhone 4S and up – WILL NOT RUN ON EARLIER... | Read more »
Weather Or Not Review
Weather Or Not Review By Jennifer Allen on November 25th, 2014 Our Rating: :: STYLISH WEATHER REPORTINGiPhone App - Designed for the iPhone, compatible with the iPad Check the weather quickly and conveniently with Weather or Not... | Read more »
The All-New Football Manager Handheld 20...
The All-New Football Manager Handheld 2015 is Available Now Posted by Jessica Fisher on November 25th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Six iOS Games to Get You Ready for Thank...
Image Source: Friends Wiki At this point in the month, you or at least a few people you know are probably getting ready to scramble around (or are already scrambling around) for Thanksgiving Dinner. It’s a hectic day of precise oven utilization, but... | Read more »

Price Scanner via MacPrices.net

Why iPhone 6 Tablet/Laptop Cannibalization Is...
247wallst.com blogger Douglas A. McIntyre noted last week that according to research posted on the Applovin blog site the iPhone 6 is outselling the iPhone 6 Plus by a wide margin . Hardly a surprise... Read more
Worldwide Tablet Growth Expected to Slow to 7...
The global tablet market is expected to record massive deceleration in 2014 with year-over-year growth slowing to 7.2%, down from 52.5% in 2013, according to a new forecast from International Data... Read more
Touchscreen Glove Company Announces New Produ...
Surrey, United Kingdom based TouchAbility specializes in design and manufacture of a wide variety of products compatible with touchscreen devices including smartphones, tablets and computers. Their... Read more
OtterBox Alpha Glass Screen Protectors for iP...
To complement the bigger, sharper displays on the latest Apple devices, OtterBox has introduced Alpha Glass screen protectors to the iPhone 6 and iPhone 6 Plus. The fortified glass screen protectors... Read more
Early Black Friday Mac Pro sale, 6-Core 3.5GH...
 B&H Photo has the 6-Core 3.5GHz Mac Pro on sale today for $3499 including free shipping plus NY sales tax. Their price is $500 off MSRP, and it’s the lowest price available for this model from... Read more
Early Black Friday sale price: 15-inch 2.2GHz...
 B&H Photo has the 2014 15″ 2.2GHz Retina MacBook Pro on sale today for $1699.99. Shipping is free, and B&H charges NY sales tax only. Their price is $300 off MSRP, equalling Best Buy’s price... Read more
13-inch 2.5GHz MacBook Pro (refurbished) avai...
The Apple Store has Apple Certified Refurbished 13″ 2.5GHz MacBook Pros available for $170 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz... Read more
Early Black Friday iPad mini 3 sale: $75 off...
 Best Buy has iPad mini 3s on sale for $75 off MSRP on their online store for a limited time. Choose free shipping or free local store pickup (if available). Sale prices available for online orders... Read more
Early Black Friday MacBook Pro sale: 15-inch...
 Best Buy has posted early Black Friday prices on 15″ Retina MacBook Pros, with models on sale for $300 off MSRP on their online store for a limited time. Choose free local store pickup (if available... Read more
A9 Chips Already?
It’s barely more than a couple of months since Apple got the first A8 systems-on-chip into consumer hands, but rumor and news focus is already turning to the next-generation A9 SoC. Apple Daily... Read more

Jobs Board

*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
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* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the 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
*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
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.