TweetFollow Us on Twitter

MacApp Text Editor
Volume Number:3
Issue Number:2
Column Tag:MacApp Objects

A MacApp Text Editor

By David Goldsmith, MacApp Project Manager, Apple Computer, Inc.

The January 1987 issue of MacTutor contained an article showing how to implement a TextEdit based editor, MyWrite, in LS Pascal, which allows editing of multiple documents at the same time, changing fonts, sizes, and styles, and supports the usual Macintosh™ features of scrolling, resizing and moving windows, and so forth. MyWrite is already a pretty sizeable program, but it is still missing features, such as:

1.Saving documents to and reading documents from disk.

2.Support for printing documents.

3.The ability to undo and redo commands.

4.Asking the user if s/he wants to save changes before closing or quitting.

5.Displaying informative messages if a problem occurs.

6.Making sure the program doesn’t run out of memory (or encounter some other problem) and bomb.

Although MyWrite has most of the basic features of a Macintosh application, there is a big difference between a sample application like this and a commercial application. Producing a good commercial application requires that you attend to many details like those listed above, while also trying to conform to the Macintosh user interface and make your program competitive in the marketplace. In the pressure to bring a program to market, some of these considerations may get short shrift, simply because there isn’t time to deal with them. Yet the applications which supply all these ingredients are the most successful.

As large as it is, the MyWrite program is simpler than most applications because TextEdit does so much. TextEdit provides calls to handle mouse clicks, typing, screen update, scrolling, cut and paste, highlighting of the current selection, and import and export of the clipboard. Most applications, however, do not have a convenient ROM package to do all this work for them. The result is more work for you.

On all computers, you must write the part of your application that does a job for the user. On Macintosh, you must also provide the intuitive user interface, common functions, and friendly operation that Macintosh owners expect. Adding these features to a program that’s already large would certainly make it much too big to present in the pages of MacTutor - unless we do it with MacApp™.

What is MacApp?

MacApp is an object oriented framework for Macintosh applications. It’s object oriented because it uses Apple’s extended dialect of Pascal, called Object Pascal, part of the MPW development system. It’s a framework in that it provides an architecture and a collection of tools which make it much easier to write a Macintosh application.

Wherever it can, MacApp handles details which are the same for all applications, such as dealing with desk accessories or Switcher. Where it can’t do all the work for you, it provides tools and a support structure for you to fit your code into which make it easy to provide such standard features as Undo, scrolling, and printing. MacApp is like a high level Toolbox built on top of the Toolbox in the Macintosh ROMs.

By providing much of the standard behavior of a Macintosh application, MacApp frees you to spend more time making your application do a better job for the user. It also enables you to refine your user interface and make it better than it would have been if you had built it from scratch. The flexibility which lets MacApp provide this standard behavior while allowing you to alter it comes from Object Pascal.

All About Objects

For a good discussion of Object Pascal, see the December 1986 issue of MacTutor, which has several articles on MacApp. For those of you who don’t have that issue handy, here is an overview of Object Pascal.

Object Pascal adds a new data type to Pascal, the object. An object is very similar to a record, but in addition to conventional fields it can also have associated procedures and functions, called methods. Just as you would reference a field of a record or object by writing record.field, you call a method of an object by writing object.Method(arguments).

The ability to associate code with the data which that code operates on is a powerful tool for making your code more modular. However, the real power of object oriented programming lies in another feature called inheritance. When you declare a new object type in Object Pascal, you can give the name of an existing object type which becomes the new type’s ancestor; the name of the ancestor appears in parentheses (see Figure 2). The new, descendant type inherits all of the fields and methods defined by the ancestral type; that is, any fields and methods which the new type defines are in addition to those already defined for the ancestral type.

In addition, the descendant type can override methods defined by its ancestor, by providing a new implementation of the same method, with the same interface. The override method can call the method it is overriding; this allows you to extend the function of a method by calling the original version and then doing a little bit extra, instead of duplicating the original code and then modifying it.

Now for the best part: variables actually hold references to objects rather than the objects themselves, which are relocatable blocks in the Macintosh heap. In fact, a variable of a given object type can hold a reference to an object of that type or any of its descendant types. When you call a method using a given variable, the code which gets executed depends on which particular kind of object that variable refers to. If it refers to an object of type TRectangle with a method Draw, and you say variable.Draw, you’ll call the method TRectangle.Draw. But if the same variable currently refers to an object whose type is a descendant of TRectangle (say TRoundRect), and that descendant type overrides Draw, then the same statement variable.Draw will call the method TRoundRect.Draw instead, which probably does something quite different from what TRectangle.Draw does.

How Does MacApp Work?

Well, objects sound interesting and powerful, but how does MacApp use them? The answer is that MacApp defines a set of object types which act as generic components of an application. These components implement those parts of an application which are common to almost all applications, but not the parts that make any given application unique. The types MacApp defines are:

1.TApplication, which can handle desk accessories, the clipboard, and opening new and old documents.

2.TDocument, which knows how to read and write disk files, handle its windows, and ask if you want to save it when it’s closed.

3.TView, which shows the contents of a document. It knows how to draw itself on the screen, and process mouse clicks and keystrokes.

4.TFrame and TWindow, which know how to show views, and provide scroll bars to look at different parts of those views.

5.TCommand, which represents a unit of action by the user which can be done, undone, or redone.

What’s slightly surprising is that TDocument reads and writes empty documents, TView displays blank documents, and TCommand does nothing when doing, undoing, or redoing. So how does a MacApp program do anything useful? By overriding, of course. You define object types which are descendants of the standard MacApp types, and which supply just that extra knowledge which makes them do what your application needs to do. These types inherit all the standard behavior which you would otherwise have to reinvent for every application. That standard behavior makes for a very, very long list, and few commercial applications implement everything on it.

The Multi-Window Text Editor

How would we go about implementing this program in MacApp? Well, we don’t have to worry about supporting desk accessories, Switcher, scrolling, saving and restoring documents, Undo, handling errors, displaying meaningful error messages, supporting multiple documents open at once, handling interactions with the Finder, printing, displaying the Clipboard, zoom boxes, resizing or moving windows, or memory management, because MacApp already does all of that for us.

We are still responsible for implementing that part of our application which isn’t generic, which in this case means editing text using the Toolbox TextEdit package. Fortunately for us, though, MacApp comes with a building block which puts a MacApp front end on TextEdit by defining a descendant of TView called TTEView. Building blocks are add-ons to MacApp which provide features that not every application uses. Currently, MacApp comes with three building blocks, for printing, TextEdit, and dialogs.

Does this mean we’ve pared the program down to nothing at all? Not quite, because the standard TTEView type defined by MacApp doesn’t support commands for changing the font, size, or style of the text being displayed. We’ll have to do that ourselves. For this article, we’ll do it by calling methods of TTEView and by calling TextEdit routines to do what we want. A cleaner way to do it would be to define a descendant of TTEView called, say, TFontsTEView. TFontsTEView would define additional methods to do what we need, such as TFontsTEView.ChangeTextSpecs. This would make our work reusable in any program which needed a TextEdit view with those additional capabilities.

Our multi-window text editor, named DemoText, is in fact the same as the sample program of the same name which is supplied with MacApp, except for some small differences. It saves text in documents of type TEXT, with the text in the data fork, and the current font information and Page Setup information stored in the resource fork. It doesn’t have the Other font size menu command which the MacTutor editor has, but that would be fairly easy to add. In fact, it could be added without modifying the UDemoText unit at all, by overriding the types TTextDocument and TTextApplication in the main program, MDemoText.p, and adding that one command.

If you compare this program to the one done without MacApp, you will find that it is significantly shorter and does much more. If desired, it could be distributed as a commercial product (begging the question of whether there’s a market for programs which support only one font at a time and no more than 32K of text).

Structure of a MacApp Application

When you use MacApp with MPW (the Macintosh Programmer’s Workshop) and MPW Pascal, you usually need at least five files to specify an application and how to build it:

1.MYourApp.p, the Pascal source for the main program.

2.UYourApp.p, the interface file for the Pascal unit which defines the main application types.

3.UYourApp.inc1.p, the implementation file for the Pascal unit which defines the main application types. This is in a separate file so that changes to the implementation do not cause users of the unit to be recompiled.

4.YourApp.r, the input file to the MPW resource compiler, Rez.

5.YourApp.make, a file which specifies the structure of the application. MPW’s Make tool is very powerful but also very complex. MacApp comes with a set of Make files which declare the necessary rules for building a MacApp program; all you need do is specify the structure of your program.

[Note: In terms of hardware, MacTutor recommends you buy a 40 meg. hard disk. The MPW and MacApp software runs about 8 Meg including source code! Our experience is that a typical 20 Meg drive is barely enough for all the non-development type applications and data files. -Ed.]

It’s possible to have applications with more source files by making the appropriate declarations in the .make file.

In MDemoText.p, DemoText.r, and DemoText.make, we don’t need anything out of the ordinary; these files are similar to the templates provided with MacApp. MDemoText.p calls some initialization routines and makes the application’s one resident segment resident in memory (by calling some MacApp utility routines). It then creates an instance of the application object and tells it to run the application. When this call returns, the user has selected the Quit command.

Note that DemoText.r contains only resources specific to DemoText, such as its window template and the About DemoText alert. Some of the other resources are unusual in that they don’t appear in applications written without MacApp. For example, the seg! and mem! resources control the memory management features of MacApp (which are too involved to discuss here). The cmnu resources are just like MENU resources, except that each menu item has an additional component: a MacApp command number. A special MPW tool (PostRez) strips the command numbers from each menu, creating normal MENU resources while also building a table which maps between MacApp command numbers and menu and item numbers. Notice that there are command numbers defined by both DemoText (these are defined in the source) and MacApp (these are defined in the MacApp interface files).

Getting Down to Business

The parts of the application which actually do the work are in UDemoText.p and UDemoText.inc1.p, where the application’s object types are defined.

As I mentioned above, we won’t override TTEView to implement DemoText. Instead, we’ll define three new descendants of MacApp objects: TDemoTextApplication, a descendant of TApplication, TTextDocument, a descendant of TDocument, and TTextCommand, a descendant of TCommand. Each is responsible for adding features over and above those provided by MacApp.

TDemoTextApplication doesn’t have much to do. We just provide an initialization method (IDemoTextApplication), and override the standard method DoMakeDocument so that the application creates the right kind of object to represent our documents (the generic TDocument.DoMakeDocument does nothing). This one method is called for both new and existing documents.

TTextDocument does the bulk of the work. One object of type TTextDocument is created for each document which is open. The document object is responsible for making one or more views to display the document (method DoMakeViews), making one or more windows to display those views in (method DoMakeWindows), enabling valid menu commands (method DoSetupMenus), and executing those commands when chosen (method DoMenuCommand). Note that for both of these latter methods, commands not specific to the application are passed on via INHERITED so that MacApp can handle them (such as File menu commands, Edit menu commands, and so on).

The document object is also responsible for reading and writing files, so DemoText overrides the methods DoRead and DoWrite to do so. The method DoNeedDiskSpace calculates the disk space needed before the document is saved, and so allows MacApp to warn the user beforehand if there is not enough space.

There are some additional small methods: DoInitialState is called when Reverting to a blank document, and FreeData and ShowReverted are both used for all cases of the Revert command. Again, we’re only specifying behavior which makes our program different from the generic application. TTextDocument also defines one new method, InstallTextSpecs, which does the work of changing the font, size, style, or justification.

The last type, TTextCommand, has very little to do. It encapsulates the actions of the commands which change font attributes in one object, so that the commands can be easily done, undone, and redone. All it has to do is remember the previous state of the document’s font attributes, then swap them back and forth as requested.

There are some items in the sources which I haven’t discussed, but that would require more details of MacApp than I have room for here. None of them are essential to grasping how the program works and how it makes use of MacApp.

We’ve now done everything necessary to make our program do what we wanted. All of the other features we talked about at the beginning of this article are taken care of by MacApp. For example, because we used TTextCommand to handle our font commands, we automatically get Undo and Redo. In addition, MacApp knows that this command changes the document, and so it knows to ask the user whether or not to save changes. The commands for changing how the text is wrapped are not undoable, but could easily be made so by defining another type of command object.

As I mentioned earlier, having the TTEView type available made this program simpler, just as having TextEdit in ROM made MyWrite easier to write. However, MacApp contains tools which make writing any application easier, not just one which edits text. MacApp comes with many sample programs which demonstrate different kinds of applications, including a MacDraw™-like sample.

How to Find Out More

You can find out more about MacApp from:

1.The December 1986 MacTutor, which has three articles on MacApp, including another application.

2.Kurt Schmucker’s book, “Object Oriented Programming for the Macintosh,” Hayden, 1986. This covers MacApp extensively, and is available in most bookstores.

3.The MacApp Developer’s Association, an independent user’s group. Their address is:

MacApp Developer’s Association

PO Box 23

Everett, WA 98206-0023

4.The MacApp 1.0 Source Listing and Cross Reference, available from the Apple Programmer’s and Developer’s Association (APDA). This is not only a good source of information on MacApp, but a good place to learn things for programs written without MacApp. APDA’s address is:

Apple Programmer’s and Developer’s Association

290 SW 43rd St.

Renton, WA 98055

(206) 251-6548

5.The MacApp Reference Manual, part of the MacApp package which is also available from APDA. MacApp currently can only be used with the Macintosh Programmer’s Workshop (MPW) and MPW Pascal, but third party developers are working on supporting MacApp in other environments.

Remember the MacApp team’s motto: “We do the programming, so you don’t have to!”

Macintosh, MacApp, and MacDraw are trademarks of Apple Computer, Inc.


{File UDemoText.p}

{Copyright © 1986 by Apple Computer, Inc.  All Rights Reserved.}

UNIT UDemoText;

{This sample application demonstrates the breadth of alternatives available 
when using the MacApp building-block "UTEView" for text-editing.}

INTERFACE

USES
 {$LOAD MacIntf.LOAD}
 MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf,
 {$LOAD UMacApp.LOAD}
 UObject, UList, UMacApp,
 {$LOAD}
 UPrinting,
 UTEView;

CONST

  {Command numbers}
 cWidthFrame   = 601;{View-width-determination cmds}
 cWidthView =  602;
 cWidthOnePage = 603;
 cHeightFrame  = 604;{View-height-determination cmds}
 cHeightPages  = 605;
 cHeightText   = 606;
 cHeightConst  = 607;
 cJustLeft= 608; {Justification commands}
 cJustCenter   = 609;
 cJustRight =  610;

  {Other constants}
 kSignature =  'SS04';   {application signature}
 kFileType=  'TEXT';  {file-type code for saved disk files -- uses standard 
text files}
 kWindowRsrcID = 1004;   {Resource ID of the WIND resource used to obtain 
the windows used by this app}

TYPE

TextSpecs =   {Text specifications}
 RECORD
 theFontNumber:  INTEGER;
 theFontSize:    INTEGER;
 theStyle:Style;
 theJustification: INTEGER;
 END;
TextSpecsPtr = ^TextSpecs;
TextSpecsHdl = ^TextSpecsPtr;

TDemoTextApplication = OBJECT(TApplication)

PROCEDURE TDemoTextApplication.IDemoTextApplication;
 {Initialize the Application}

FUNCTION  TDemoTextApplication.DoMakeDocument(
 itsCmdNumber: CmdNumber): TDocument; OVERRIDE;
 {Launches a TTextDocument}

{$IFC qDebug}
PROCEDURE TDemoTextApplication.IdentifySoftware; OVERRIDE;
{$ENDC}

END;

TTextDocument = OBJECT(TDocument)

fText:  Handle;  {The text owned by the document}
fTEView:TTEView; {The view which displays the text}
fTextSpecs: TextSpecs;  {Specifies properties of the text}
fSpecsChanged: BOOLEAN; {Specifications have changed since last time 
menus were set up}
fCurrFontMenu: INTEGER; {Currently selected font menu item}

  {Initialization and freeing}

PROCEDURE TTextDocument.ITextDocument;
PROCEDURE TTextDocument.Free; OVERRIDE;
PROCEDURE TTextDocument.DoInitialState; OVERRIDE;
PROCEDURE TTextDocument.FreeData; OVERRIDE;

  {Filing}

PROCEDURE TTextDocument.DoNeedDiskSpace(
 VAR dataForkBytes, rsrcForkBytes: LONGINT); OVERRIDE;
PROCEDURE TTextDocument.DoRead(
 aRefNum: INTEGER; rsrcExists, forPrinting: BOOLEAN); OVERRIDE;
PROCEDURE TTextDocument.DoWrite(
 aRefNum: INTEGER; makingCopy: BOOLEAN); OVERRIDE;

  {Making views and windows}

PROCEDURE TTextDocument.DoMakeViews(forPrinting: BOOLEAN);     OVERRIDE;
PROCEDURE TTextDocument.DoMakeWindows; OVERRIDE;

  {Command processing}

FUNCTION  TTextDocument.DoMenuCommand(
 aCmdNumber: CmdNumber): TCommand; OVERRIDE;
PROCEDURE TTextDocument.DoSetupMenus; OVERRIDE;

  {Auxiliary routine}

PROCEDURE TTextDocument.InstallTextSpecs(
 specs: TextSpecs);
 {Installs the properties implied by values in 'specs' into the TextEdit 
record}

PROCEDURE TTextDocument.ShowReverted; OVERRIDE;
 {When the user reverts a document, this is called after reading the 
old document and before displaying it.  Causes the reverted font specs 
to be installed.}

END;

TTextCommand = OBJECT(TCommand)  {A Command which changes properties 
of text}

fOldTextSpecs: TextSpecs; {Text specifications before command is done 
-- used for UNDO}
fNewTextSpecs: TextSpecs; {Text specifications after command is done 
-- used for DO/REDO}
fTEView:TTEView; {The view to which the command applies}
fTextDocument: TTextDocument; {The corresponding text document}

  {Initialization}

PROCEDURE TTextCommand.ITextCommand(
 itsCmdNumber: CmdNumber;
 itsTextDocument: TTextDocument;
 itsTEView: TTEView;
 itsFontNumber: INTEGER;
 itsFontSize: INTEGER;
 itsStyle: Style;
 itsJustification: INTEGER);

  {Command execution phases}

PROCEDURE TTextCommand.DoIt; OVERRIDE;
PROCEDURE TTextCommand.UndoIt; OVERRIDE;
PROCEDURE TTextCommand.RedoIt; OVERRIDE;

END;

IMPLEMENTATION

{$I UDemoText.inc1.p}

END.

{File UDemoText.inc1.p}

{Copyright © 1986 by Apple Computer, Inc.  All Rights Reserved.}

CONST

  {Menu id's}
 mFont  = 6;
 mStyle = 7;

  {Command numbers for font-size commands}
   cSizeChange = 1100;
 cSizeBase= 1100;
 cSizeMin = 1109;
 cSizeMax = 1124;
 {1101-1199 reserved for font sizes 1-99 pts.}

  {Command numbers for typestyle attributes}
   cStyleChange   =1200;
 cPlainText =  1201;
 cBold  = 1202;
 cItalic  = 1203;
 cUnderline =  1204;
 cOutline = 1205;
 cShadow  = 1206;
 cCondense= 1207;
 cExtend  = 1208;

{Command numbers to cover other stylistic changes}
 cJustChange=  1300;
 cFontChange   = 1301;

{Constant for staggering windows}
 kStaggerAmount  = 16;

{Constants for the text specs resource}
 kTextSpecsRsrcType  =  'SPEC';
 kTextSpecsRsrcID  = 1;
 
{Constants for the print info resource}
 kPrintInfoRsrcType  =  'PRNT';
 kPrintInfoRsrcID  = 1;
 
{The 'File is too large' alert}
 kFileTooBig     = 1000;

VAR

gFontNum: INTEGER; {Font number - default for new documents}
gFontSize: INTEGER; {Font Size in points - default for new     
 documents}
gStaggerCount: INTEGER;

PROCEDURE OutlineFontSizes(fontNum: INTEGER); FORWARD;
 {Makes the right Menu Manager calls so that the 'Font' menu has fontsizes 
representing 'natural fonts' shown in 'outline', and sizes which can 
only be achieved by scaling another font size shown in normal face}

{$S AInit}
PROCEDURE  TDemoTextApplication.IDemoTextApplication;
 VAR err: OSErr;
 fntName: Str255;
BEGIN
 IApplication(kFileType);

 {Find out what applFont maps to, so that we set gFontNum to a real font 
number.}
 GetFontName(applFont, fntName);
 GetFNum(fntName, gFontNum);
 gFontSize := 10;

 IF NOT gFinderPrinting THEN
 BEGIN
 AddResMenu(GetMHandle(mFont), 'FONT');

 OutlineFontSizes(gFontNum);
 gStaggerCount := 0;

 {Set style-items to corresponding typeface}
 SetStyle(cBold, [bold]);
 SetStyle(cUnderline, [underline]);
 SetStyle(cItalic, [italic]);
 SetStyle(cOutline, [outline]);
 SetStyle(cShadow, [shadow]);
 SetStyle(cCondense, [condense]);
 SetStyle(cExtend, [extend]);
 END;
END;

{$S AOpen}
FUNCTION TDemoTextApplication.DoMakeDocument(
itsCmdNumber: CmdNumber): TDocument; OVERRIDE;
 VAR aTextDocument:TTextDocument;
BEGIN
 New(aTextDocument);
 FailNIL(aTextDocument);
 aTextDocument.ITextDocument;
 DoMakeDocument := aTextDocument;
END;

{$IFC qDebug}
{$S ADebug}
PROCEDURE TDemoTextApplication.IdentifySoftware;
BEGIN
 WriteLn('DemoText Source date: 23 April 86; Compiled: ',
 COMPDATE, ' @ ', COMPTIME);
 INHERITED IdentifySoftware;
END;
{$ENDC}

{$S AOpen}
PROCEDURE TTextDocument.ITextDocument;
BEGIN
 fText := NIL;
 IDocument(kFileType, kSignature, kUsesDataFork,
 kUsesRsrcFork, NOT kDataOpen,
 NOT kRsrcOpen);
 fTEView := NIL;
 fText := NewPermHandle(0);
 FailNIL(fText);
END;

{$S AClose}
PROCEDURE TTextDocument.Free; OVERRIDE;
BEGIN
 IF fText <> NIL THEN
 DisposHandle(fText);
 INHERITED Free;
END;

{$S AOpen}
PROCEDURE TTextDocument.DoInitialState; OVERRIDE;
BEGIN
 WITH fTextSpecs DO
 BEGIN
 theFontNumber := gFontNum;
 theFontSize := gFontSize;
 theStyle := [];
 theJustification := teJustLeft;
 END;
 fSpecsChanged := TRUE;
END;

{$S AOpen}
PROCEDURE TTextDocument.DoMakeViews(
 forPrinting: BOOLEAN); OVERRIDE;
VAR aTEView:TTEView;
 itsExtent: Rect;
 aHandler:TStdPrintHandler;

BEGIN
 New(aTEView);
 FailNIL(aTEView);
 aTEView.ITEView(
 NIL,   {parent}
 SELF,  {its document}
 fText, {its Text}
 Point(0),{location of its top-left-most point}
 cTyping, {its key-command number}
 10,    {10 pixels of margin on each side}
 8,{8 pixels margin at top}
 1000,  {1000 pixels initial view width -- will be adjusted to be width 
of page later}
 100,   {100 pixels initial height -- will be  adjusted to height-of-content 
later}
 fTextSpecs.theFontNumber, {font family to use}
 fTextSpecs.theFontSize, {font size to use}
 fTextSpecs.theStyle, {style to use}
 sizePage,{view width determined (initially) by page-width less desired 
margins}
 sizeVariable, {height determined (initially) by amount of text}
 kUnlimited);  {no limit to number of characters accepted}

 aTEView.fHTE^^.just := fTextSpecs.theJustification;

 New(aHandler);
 FailNIL(aHandler);
 aHandler.IStdPrintHandler(aTEView, FALSE);
 aHandler.fMinimalMargins := FALSE;

{$IFC qDebug}
 aTEView.fShowBorders := TRUE;
 aTEView.fShowExtraFeedback := TRUE;
{$ENDC}
 fTEView := aTEView;
END;

{$S AOpen}
PROCEDURE TTextDocument.DoMakeWindows; OVERRIDE;
VAR
 aWindow: TWindow;
BEGIN
 aWindow := NewSimpleWindow(kWindowRsrcID,
 NOT kDialogWindow, kWantHScrollBar,
 kWantVScrollBar, fTEView);
 AdaptToScreen(aWindow);
 SimpleStagger(aWindow, kStaggerAmount,
 kStaggerAmount, gStaggerCount);
END;

{$S ASelCommand}
FUNCTION  TTextDocument.DoMenuCommand(
 aCmdNumber: CmdNumber): TCommand;
 VAR sd:  SizeDeterminer;
 aName: Str255;
 menu:  INTEGER;
 item:  INTEGER;
 newSpecs:TextSpecs;
 aStyleItem:   StyleItem;
 PROCEDURE InstallChangedDeterminer(vhs: VHSelect);
 BEGIN
 IF sd <> fTEView.fSizeDeterminer[vhs] THEN
 BEGIN
 fTEView.fSizeDeterminer[vhs] := sd;
 {If we changed the horizontal size determiner, we must ask the TTEView 
to recompute the TE rectangles.}
 IF vhs = h THEN
 BEGIN
 IF sd = sizeFrame THEN
 fTEView.FrameChangedSize
 ELSE IF sd = sizePage THEN
 fTEView.DoPagination;
 END;
 fTEView.AdjustExtent;
 fTEView.fFrame.ForceRedraw;
 END;
 END;

 PROCEDURE LaunchTextCommand(
 aCmdNumber: CmdNumber);
 VAR aTextCommand: TTextCommand;
 BEGIN
 New(aTextCommand);
 FailNIL(aTextCommand);
 WITH newSpecs DO
 aTextCommand.ITextCommand(aCmdNumber,
 SELF, fTEView, theFontNumber,
 theFontSize, theStyle, theJustification);
 DoMenuCommand := aTextCommand;
 END;
BEGIN
 DoMenuCommand := gNoChanges;
 newSpecs := fTextSpecs;

 CmdToMenuItem(aCmdNumber, menu, item);
 IF (cSizeMin <= aCmdNumber) AND (aCmdNumber <=
 cSizeMax) THEN
 BEGIN
 newSpecs.theFontSize := aCmdNumber -
 cSizeBase;
 LaunchTextCommand(cSizeChange);
 END
 ELSE IF menu = mFont THEN
 BEGIN
 GetItem(GetMHandle(menu), item, aName);
 GetFNum(aName, newSpecs.theFontNumber);
 LaunchTextCommand(cFontChange);
 END
 ELSE IF (aCmdNumber >= cJustLeft) AND
 (aCmdNumber <= cJustRight) THEN
 BEGIN
 WITH newSpecs DO
 IF aCmdNumber = cJustLeft THEN
 theJustification := teJustLeft
 ELSE
 IF aCmdNumber = cJustCenter THEN
 theJustification := teJustCenter
 ELSE
 theJustification := teJustRight;
 LaunchTextCommand(cJustChange);
 END
 ELSE IF (aCmdNumber = cPlainText) THEN
 BEGIN
 newSpecs.theStyle := [];
 LaunchTextCommand(cStyleChange);
 END
 ELSE IF (aCmdNumber > cPlainText) AND
 (aCmdNumber <= cExtend) THEN
 BEGIN
 CASE aCmdNumber OF
 cBold: aStyleItem := bold;
 cItalic: aStyleItem := italic;
 cUnderline:   aStyleItem := underline;
 cOutline:aStyleItem := outline;
 cShadow: aStyleItem := shadow;
 cCondense: aStyleItem := condense;
 cExtend: aStyleItem := extend;
 END; {case}
 WITH newSpecs DO
 IF aStyleItem IN theStyle THEN
 theStyle := theStyle - [aStyleItem]
 ELSE
 theStyle := theStyle + [aStyleItem];
 LaunchTextCommand(cStyleChange);
 END
 ELSE
 IF (aCmdNumber <= cWidthOnePage) AND
 (aCmdNumber >= cWidthFrame) THEN
 BEGIN
 IF aCmdNumber = cWidthFrame THEN
 sd := sizeFrame
 ELSE
 IF aCmdNumber = cWidthOnePage THEN
 sd := sizePage
 ELSE
 sd := sizeFixed;
 {NB: The following is not undoable in the current 
 version}
 InstallChangedDeterminer(h);
 END
 ELSE
 IF (aCmdNumber >= cHeightFrame) AND
 (aCmdNumber <= cHeightConst) THEN
 BEGIN
 IF aCmdNumber = cHeightFrame THEN
 sd := sizeFrame
 ELSE
 IF aCmdNumber = cHeightPages THEN
 sd := sizeFillPages
 ELSE
 IF aCmdNumber = cHeightText THEN
 sd := sizeVariable
 ELSE
 IF aCmdNumber = cHeightConst THEN
 sd := sizeFixed;

 {NB: The following is not undoable in the current 
 version}
 InstallChangedDeterminer(v);
 END
 ELSE
 DoMenuCommand :=
 INHERITED DoMenuCommand(aCmdNumber);
END;

{$S AWriteFile}
PROCEDURE TTextDocument.DoNeedDiskSpace(
 VAR dataForkBytes, rsrcForkBytes: LONGINT);
BEGIN
 dataForkBytes := dataForkBytes +
 GetHandleSize(fText);
 rsrcForkBytes := rsrcForkBytes + SIZEOF(TextSpecs) +          kRsrcTypeOverhead 
+ kRsrcOverhead +
 kPrintInfoSize + kRsrcTypeOverhead + kRsrcOverhead;
 INHERITED DoNeedDiskSpace(dataForkBytes,
 rsrcForkBytes);
END;

{$S AReadFile}
PROCEDURE TTextDocument.DoRead(aRefNum: INTEGER;
 rsrcExists, forPrinting: BOOLEAN);
 VAR numChars:   LONGINT;
 hTextSpecs:TextSpecsHdl;
 hPrintInfo:Handle;
BEGIN
 {Read the text}
 FailOSErr(GetEOF(aRefNum, numChars));

 {The file may have been created by someone else--make sure we don't 
read more than we can handle}
 IF numChars > kUnlimited THEN
 BEGIN
 gApplication.ShowError(0, msgAlert + kFileTooBig);
 numChars := kUnlimited;
 END;
 SetHandleSize(fText, numChars);
 FailMemError;
 FailOSErr(FSRead(aRefNum, numChars, fText^));
 
 {Read the text specs resource}
 hTextSpecs :=
 TextSpecsHdl(GetResource(kTextSpecsRsrcType,
 kTextSpecsRsrcID));
 IF hTextSpecs <> NIL THEN
 fTextSpecs := hTextSpecs^^
 ELSE
 WITH fTextSpecs DO
 BEGIN
 theFontNumber := gFontNum;
 theFontSize := gFontSize;
 theStyle := [];
 theJustification := teJustLeft;
 END;
 fSpecsChanged := TRUE;
 
 {Read the print info resource}
 hPrintInfo := GetResource(kPrintInfoRsrcType,
 kPrintInfoRsrcID);
 IF hPrintInfo <> NIL THEN {no print info resources was
 saved}
 BEGIN
 IF fPrintInfo = NIL THEN
 BEGIN
 fPrintInfo := NewPermHandle(kPrintInfoSize);
 FailNIL(fPrintInfo);
 END;
 BlockMove(hPrintInfo^, fPrintInfo^, kPrintInfoSize);
 END;
END;

{$S ARes}
PROCEDURE TTextDocument.DoSetupMenus;
 VAR sd:  SizeDeterminer;
 just:  INTEGER;
 item:  INTEGER;
 fnt:   INTEGER;
 c:INTEGER;
 aName: Str255;
 aMenuHandle:  MenuHandle;
 aStyle:  Style;
BEGIN
 INHERITED DoSetupMenus;

 aMenuHandle := GetMHandle(mFont);
 FOR item := 1 TO CountMItems(aMenuHandle) DO
 BEGIN
 {There can be more than 31 menu entries with scrolling menus, but trying 
to enable an item with number > 31 is bad news.  If the menu itself is 
enabled (which it will be in MacApp if any of the first 31 items is enabled), 
then the extras will always be enabled.}
 IF item <= 31 THEN
 EnableItem(aMenuHandle, item);
 IF fSpecsChanged THEN
 BEGIN
 GetItem(aMenuHandle, item, aName);
 GetFNum(aName, fnt);
 IF fnt = fTextSpecs.theFontNumber THEN
 fCurrFontMenu := item;
 END;
 END;
 CheckItem(aMenuHandle, fCurrFontMenu, TRUE);

 FOR c := cSizeMin TO cSizeMax DO
 EnableCheck(c, TRUE, (c - cSizeBase) =
 fTextSpecs.theFontSize);

 aStyle := fTextSpecs.theStyle;
 EnableCheck(cPlainText, TRUE, aStyle = []);
 EnableCheck(cBold, TRUE, bold IN aStyle);
 EnableCheck(cItalic, TRUE, italic IN aStyle);
 EnableCheck(cUnderline, TRUE, underline IN aStyle);
 EnableCheck(cOutline, TRUE, outline IN aStyle);
 EnableCheck(cExtend, TRUE, extend IN aStyle);
 EnableCheck(cCondense, TRUE, condense IN aStyle);
 EnableCheck(cShadow, TRUE, shadow IN aStyle);

 sd := fTEView.fSizeDeterminer[h];
 EnableCheck(cWidthFrame, TRUE, (sd = sizeFrame));
 EnableCheck(cWidthOnePage, TRUE, (sd = sizePage));
 EnableCheck(cWidthView,  TRUE, (sd = sizeFixed));

 sd := fTEView.fSizeDeterminer[v];
 EnableCheck(cHeightFrame,  TRUE, (sd = sizeFrame));
 EnableCheck(cHeightPages,  TRUE, (sd =
 sizeFillPages));
 EnableCheck(cHeightText,  TRUE, (sd = sizeVariable));
 EnableCheck(cHeightConst,  TRUE, (sd = sizeFixed));

 just := fTextSpecs.theJustification;
 EnableCheck(cJustLeft, TRUE, (just = teJustLeft));
 EnableCheck(cJustCenter, TRUE, (just = teJustCenter));
 EnableCheck(cJustRight, TRUE, (just = teJustRight));

 IF fSpecsChanged THEN
 OutlineFontSizes(fTextSpecs.theFontNumber);

 fSpecsChanged := FALSE;
END;

{$S AWriteFile}
PROCEDURE TTextDocument.DoWrite(aRefNum: INTEGER; makingCopy: BOOLEAN);
 VAR numChars:   LONGINT;
 hTextSpecs:TextSpecsHdl;
 tempHandle:Handle;
BEGIN
 {Write out the text}
 numChars := GetHandleSize(fText);
 FailOSErr(FSWrite(aRefNum, numChars, fText^));

 {Write the text specification resource, after converting it to a handle}
 hTextSpecs :=
 TextSpecsHdl(NewHandle(SIZEOF(TextSpecs)));
 FailNIL(hTextSpecs);
 hTextSpecs^^ := fTextSpecs;
 AddResource(Handle(hTextSpecs),
 kTextSpecsRsrcType, kTextSpecsRsrcID, '');
 FailResError;

 {Write the print info resource.  Note we can't use MacApp for this because 
MacApp will write the print info into the data fork.  Note also--we must 
copy the print info resource to another handle because the Resource Manager 
will dispose of the resource handles when a resource fork is closed.}
 tempHandle := fPrintInfo;
 FailOSErr(HandTohand(tempHandle));
 AddResource(tempHandle, kPrintInfoRsrcType,
 kPrintInfoRsrcID, '');
 FailResError;
END;

{$S AClose}
PROCEDURE TTextDocument.FreeData; OVERRIDE;
BEGIN
 SetHandleSize(fText, 0);
END;

{$S ARes}
PROCEDURE TTextDocument.InstallTextSpecs(
 specs: TextSpecs);
VAR
 savedPort: GrafPtr;
 tempPort:GrafPort;
 newInfo: FontInfo;
BEGIN
 {Make sure the font info record is correct.  We may need to do this 
when the window isn't around, so roll our own GrafPort.}
 GetPort(savedPort);
 OpenPort(@tempPort);
 WITH specs DO
 BEGIN
 TextFont(theFontNumber);
 TextSize(theFontSize);
 TextFace(theStyle);
 END;
 GetFontInfo(newInfo);
 ClosePort(@tempPort);
 SetPort(savedPort);

 fTextSpecs := specs;
 fSpecsChanged := TRUE;
 
 WITH fTEView, specs DO
 BEGIN
 fFont := theFontNumber;
 fSize := theFontSize;
 fFontInfo := newInfo;
 WITH fHTE^^ DO
 BEGIN
 WITH newInfo DO
 BEGIN
 fontAscent := ascent;
 lineHeight := ascent+descent+leading;
 END;
 txSize := theFontSize;
 txFont := theFontNumber;
 txFace := theStyle;
 just := theJustification;
 fFrame.fScrollUnit.v := lineHeight;
 END;
 END;
 fTEView.RecalcText;
 fTEView.DoPagination;
END;

{$S AReadFile}
PROCEDURE TTextDocument.ShowReverted;
BEGIN
 InstallTextSpecs(fTextSpecs);
 TESetSelect(0, 0, fTEView.fHTE);
 INHERITED ShowReverted;
END;

{$S ARes}
PROCEDURE OutlineFontSizes(fontNum: INTEGER);
 VAR c: CmdNumber;
BEGIN
 FOR c := cSizeMin TO cSizeMax DO
 BEGIN
 IF RealFont(fontNum, c - cSizeBase) THEN
 SetStyle(c, [outline])
 ELSE
 SetStyle(c, []);
 END;
END;

{$S ASelCommand}
PROCEDURE TTextCommand.ITextCommand(
 itsCmdNumber: CmdNumber;
 itsTextDocument: TTextDocument;
 itsTEView: TTEView;
 itsFontNumber: INTEGER;
 itsFontSize: INTEGER;
 itsStyle: Style;
 itsJustification: INTEGER);
BEGIN
 ICommand(itsCmdNumber);
 fTEView := itsTEView;
 fTextDocument := itsTextDocument;
 WITH fOldTextSpecs, itsTEView.fHTE^^ DO
 BEGIN
 theFontNumber := txFont;
 theFontSize := txSize;
 theStyle := txFace;
 theJustification := just;
 END;

 WITH fNewTextSpecs DO
 BEGIN
 theFontNumber := itsFontNumber;
 theFontSize := itsFontSize;
 theStyle := itsStyle;
 theJustification := itsJustification;
 END;
 END;

{$S ADoCommand}
PROCEDURE TTextCommand.DoIt; OVERRIDE;
BEGIN
 fTextDocument.InstallTextSpecs(fNewTextSpecs);
END;

{$S ADoCommand}
PROCEDURE TTextCommand.UndoIt; OVERRIDE;
BEGIN
 fTextDocument.InstallTextSpecs(fOldTextSpecs);
END;

{$S ADoCommand}
PROCEDURE TTextCommand.RedoIt; OVERRIDE;
BEGIN
 fTextDocument.InstallTextSpecs(fNewTextSpecs);
END;

{File MDemoText.p}

{Copyright © 1986 by Apple Computer, Inc.  All Rights Reserved.}

PROGRAM DemoText;

USES
 {$LOAD MacIntf.LOAD}
 MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf,
 {$LOAD UMacApp.LOAD}
 UObject, UList, UMacApp,
 {$LOAD}
 UPrinting,
 UTEView,
 UDemoText;

VAR
 gDemoTextApplication:  TDemoTextApplication;

{$S ARes}
PROCEDURE InAResSegment;
BEGIN
END;

{$S Main}
BEGIN
 InitToolbox(8); {Initialize the ToolBox, 8 calls to
 MoreMasters}
 InitPrinting; {Initialize the Printing unit}
 SetResidentSegment(GetSegNumber(
 @InAResSegment), TRUE);
 New(gDemoTextApplication);
 gDemoTextApplication.IDemoTextApplication;
 gDemoTextApplication.Run;
END.

/* DemoText.r - Resource compiler input file */
/* Copyright © 1986 Apple Computer, Inc.  */

#ifdef Debugging
include MacAppRFiles"Debug.rsrc";
#endif
include MacAppRFiles"MacApp.rsrc";
include MacAppRFiles"Printing.rsrc";
include "DemoText" 'CODE';

resource 'WIND' (1004, purgeable) {
 {50, 40, 250, 450},
 zoomDocProc,
 invisible,
 goAway,
 0x0,
 "<<<>>>"
};

resource 'SIZE' (-1) {
 saveScreen,
 acceptSuspendResumeEvents,
#ifdef Debugging
 (307-32) * 1024,
 (247-32) * 1024
#else
 (212-32) * 1024,
 (152-32) * 1024
#endif
};

/* Printing to the LaserWriter is the time when the most temporary memory 
is in use.  We need the segments in use at that time, plus 40K for the 
driver's needs. */

resource 'seg!' (256, purgeable) {
 {
 "GSelCommand";
 "GPrint";
 "PrintNonRes";
 "ARes"
 }
};

resource 'mem!' (256, purgeable) {
 40 * 1024, /* Add to temporary reserve */
 0,/* Add to permanent reserve */
 0 /* Add to stack space */
};

resource 'DITL' (201, purgeable) {
  {/* array DITLarray: 3 elements */
 /* [1] */
 {130, 182, 150, 262},
 Button {
 enabled,
 "OK"
 };
 /* [2] */
 {10, 80, 110, 270},
 StaticText {
 disabled,
 "This sample program demonstrates"
 " how to use various features of "
 "the “TEView” building block of M"
 "acApp."
 };
 /* [3] */
 {10, 20, 42, 52},
 Icon {
 disabled,
 1
 }
 }
};

resource 'ALRT' (201, purgeable) {
 {90, 100, 250, 412},
 201,
 {
 OK, visible, silent;
 OK, visible, silent;
 OK, visible, silent;
 OK, visible, silent
 }
};

/* Used when the user attempts to read a file larger than we can handle 
*/

resource 'DITL' (1000, purgeable) {
 { /* array DITLarray: 3 elements */
 /* [1] */
 {82, 198, 100, 272},
 Button {
 enabled,
 "OK"
 };
 /* [2] */
 {10, 70, 77, 272},
 StaticText {
 disabled,
 "DemoText can’t read the entire file because it is too long."
 };
 /* [3] */
 {10, 20, 42, 52},
 Icon {
 disabled,
 0
 }
 }
};

resource 'ALRT' (1000, purgeable) {
 {100, 110, 210, 402},
 1000,
 { /* array: 4 elements */
 /* [1] */
 OK, visible, silent;
 /* [2] */
 OK, visible, silent;
 /* [3] */
 OK, visible, silent;
 /* [4] */
 OK, visible, silent
 }
};

resource 'cmnu' (1) {
 1,
 textMenuProc,
 0x7FFFFFFD,
 enabled,
 apple,
  {/* array: 2 elements */
 /* [1] */
 "About DemoText ", noIcon, noKey, noMark, plain, 1;
 /* [2] */
 "-", noIcon, noKey, noMark, plain, nocommand
 }
};

resource 'cmnu' (2) {
 2,
 textMenuProc,
 0x7FFFEEFB,
 enabled,
 "File",
  {/* array: 14 elements */
 /* [1] */
 "New", noIcon, "N", noMark, plain, 10;
 /* [2] */
 "Open ", noIcon, noKey, noMark, plain, 20;
 /* [3] */
 "-", noIcon, noKey, noMark, plain, nocommand;
 /* [4] */
 "Close", noIcon, noKey, noMark, plain, 31;
 /* [5] */
 "Save", noIcon, noKey, noMark, plain, 30;
 /* [6] */
 "Save As ", noIcon, noKey, noMark, plain, 32;
 /* [7] */
 "Save a Copy In ", noIcon, noKey, noMark, plain, 33;
 /* [8] */
 "Revert", noIcon, noKey, noMark, plain, 34;
 /* [9] */
 "-", noIcon, noKey, noMark, plain, nocommand;
 /* [10] */
 "Page Setup ", noIcon, noKey, noMark, plain, 176;
 /* [11] */
 "Print One", noIcon, noKey, noMark, plain, 177;
 /* [12] */
 "Print ", noIcon, noKey, noMark, plain, 178;
 /* [13] */
 "-", noIcon, noKey, noMark, plain, nocommand;
 /* [14] */
 "Quit", noIcon, "Q", noMark, plain, 36
 }
};

resource 'cmnu' (3) {
 3,
 textMenuProc,
 0x7FFFFEBD,
 enabled,
 "Edit",
  {/* array: 10 elements */
 /* [1] */
 "Undo", noIcon, "Z", noMark, plain, 101;
 /* [2] */
 "-", noIcon, noKey, noMark, plain, nocommand;
 /* [3] */
 "Cut", noIcon, "X", noMark, plain, 103;
 /* [4] */
 "Copy", noIcon, "C", noMark, plain, 104;
 /* [5] */
 "Paste", noIcon, "V", noMark, plain, 105;
 /* [6] */
 "Clear", noIcon, noKey, noMark, plain, 106;
 /* [7] */
 "-", noIcon, noKey, noMark, plain, nocommand;
 /* [8] */
 "Select All", noIcon, "A", noMark, plain, 110;
 /* [9] */
 "-", noIcon, noKey, noMark, plain, nocommand;
 /* [10] */
 "Show Clipboard", noIcon, noKey, noMark, plain, 35
 }
};

resource 'cmnu' (4) {
 4,
 textMenuProc,
 0x7FFFFF37,
 enabled,
 "Page",
  {/* array: 6 elements */
 /* [1] */
 "Show Page Breaks", noIcon, noKey, noMark, plain, 201;
 /* [2] */
 "Show Page Numbers", noIcon, noKey, noMark, plain, 211;
 /* [3] */
 "Number Pages Top to Bottom", noIcon, noKey, noMark, plain, 206;
 /* [4] */
 "-", noIcon, noKey, noMark, plain, nocommand;
 /* [5] */
 "Draw Frame when Printing", noIcon, noKey, noMark, plain, 202;
 /* [6] */
 "Print Page Numbers when Printing", noIcon, noKey, noMark, plain, 207
 }
};

resource 'cmnu' (5) {
 5,
 textMenuProc,
 0x7FFFFEF7,
 enabled,
 "Text",
  {/* array: 12 elements */
 /* [1] */
 "View as wide as frame", noIcon, noKey, noMark, plain, 601;
 /* [2] */
 "View width frozen", noIcon, noKey, noMark, plain, 602;
 /* [3] */
 "View as wide as one page", noIcon, noKey, noMark, plain, 603;
 /* [4] */
 "-", noIcon, noKey, noMark, plain, nocommand;
 /* [5] */
 "View as high as the frame", noIcon, noKey, noMark, plain, 604;
 /* [6] */
 "View height an exact number of p"
 "ages", noIcon, noKey, noMark, plain, 605;
 /* [7] */
 "View as high as its content", noIcon, noKey, noMark, plain, 606;
 /* [8] */
 "View height frozen", noIcon, noKey, noMark, plain, 607;
 /* [9] */
 "-", noIcon, noKey, noMark, plain, nocommand;
 /* [10] */
 "Left justified", noIcon, noKey, noMark, plain, 608;
 /* [11] */
 "Center justified", noIcon, noKey, noMark, plain, 609;
 /* [12] */
 "Right justified", noIcon, noKey, noMark, plain, 610
 }
};

resource 'MENU' (6) {
 6,
 textMenuProc,
 allEnabled,
 enabled,
 "Font",
  {/* array: 0 elements */

 }
};

resource 'cmnu' (7) {
 7,
 textMenuProc,
 0x7FFFFFBF,
 enabled,
 "Style",
  {/* array: 13 elements */
 /* [1] */
 " 9 Point", noIcon, noKey, noMark, plain, 1109;
 /* [2] */
 "10 Point", noIcon, noKey, noMark, plain, 1110;
 /* [3] */
 "12 Point", noIcon, noKey, noMark, plain, 1112;
 /* [4] */
 "14 Point", noIcon, noKey, noMark, plain, 1114;
 /* [5] */
 "18 Point", noIcon, noKey, noMark, plain, 1118;
 /* [6] */
 "24 Point", noIcon, noKey, noMark, plain, 1124;
 /* [7] */
 "-", noIcon, noKey, noMark, plain, nocommand;
 /* [8] */
 "Plain Text", noIcon, "P", noMark, plain, 1201;
 /* [9] */
 "Bold", noIcon, "B", noMark, plain, 1202;
 /* [10] */
 "Italic", noIcon, "I", noMark, plain, 1203;
 /* [11] */
 "Underline", noIcon, "U", noMark, plain, 1204;
 /* [12] */
 "Outline", noIcon, "O", noMark, plain, 1205;
 /* [13] */
 "Shadow", noIcon, "S", noMark, plain, 1206
 }
};

resource 'cmnu' (128) {
 128,
 textMenuProc,
 allEnabled,
 enabled,
 "Buzzwords",
 { /* array: 6 elements */
 "Typing", noIcon, noKey, noMark, plain, 120;
 "Size Change", noIcon, noKey, noMark, plain, 1100;
 "Style Change", noIcon, noKey, noMark, plain, 1200;
 "Justification Change", noIcon, noKey, noMark, plain, 1300;
 "Font Change", noIcon, noKey, noMark, plain, 1301;
 "Page Setup Change", noIcon, noKey, noMark, plain, 192
 }
};

resource 'MBAR' (128) {
 {1; 2; 3; 4; 5; 6; 7}
};

# DemoText.make - describes structure of program to MacApp
# Copyright © 1986 Apple Computer, Inc.  All Rights Reserved.

AppName = DemoText

Creator = 'SS04'

# List the system libraries that your application needs to
# link with.  If you are not sure, list everything and the
# linker will tell you which ones it did not need

NeededSysLibs = 
 "{Libraries}RunTime.o" 
 "{Libraries}Interface.o" 
 "{PLibraries}PasLib.o"

#List here the MacApp building blocks that your application uses

BuildingBlockIntf =  
 "{SrcMacApp}UPrinting.p" 
 "{SrcMacApp}UTEView.p"

#List the same MacApp building blocks as object files (for linking)

BuildingBlockObjs = 
 "{ObjMacApp}UPrinting.p.o" 
 "{ObjMacApp}UTEView.p.o"

#List any additional pascal interface files which your application uses

OtherInterfaces = 

# By default MacApp.make links the above libraries, all of
# MacApp, and the files UAppName.p.o and MAppName.p.o
# List any additional files that your program links with:

OtherLinkFiles = 

#Specify any -sn (segment alias) linker options that you want included.

OtherSegMappings = 

#List the dependencies of the additional files 
#(and special build rules, if any)


#List Rez files other than AppName.r that need to Rez'ed with the application

OtherRezFiles = 

#List resource files that the Rez file includes

OtherRsrcFiles = 
 "{RezMacApp}Printing.rsrc"

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Macs Fan Control 1.5.14 - Monitor and co...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
VueScan 9.7.96 - Scanner software with a...
VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
FileMaker Pro 19.6.1 - Quickly build cus...
FileMaker Pro is the tool you use to create a custom app. You also use FileMaker Pro to access your app on a computer. Start by importing data from a spreadsheet or using a built-in Starter app to... Read more
Duet 3.1.0.0 - Use your iPad as an exter...
Duet is the first app that allows you to use your iDevice as an extra display for your Mac using the Lightning or 30-pin cable. Note: This app requires a iOS companion app. Release notes were... Read more
Firefox 107.0.1 - Fast, safe Web browser...
Firefox offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals and casual... Read more
War Thunder 2.21.1.91 - Multiplayer war...
In War Thunder, aircraft, attack helicopters, ground forces and naval ships collaborate in realistic competitive battles. You can choose from over 1,500 vehicles and an extensive variety of combat... Read more
Numbers 12.2.1 - Apple's spreadshee...
With Apple Numbers, sophisticated spreadsheets are just the start. The whole sheet is your canvas. Just add dramatic interactive charts, tables, and images that paint a revealing picture of your data... Read more
DEVONthink Pro 3.8.7 - Knowledge base, i...
DEVONthink is DEVONtechnologies' document and information management solution. It supports a large variety of file formats and stores them in a database enhanced by artificial intelligence (AI). Many... Read more
Drive Genius 6.2.3 - $79.00
Drive Genius features a comprehensive Malware Scan. Automate your malware protection. Protect your investment from any threat. The Malware Scan is part of the automated DrivePulse utility. DrivePulse... Read more
VLC Media Player 3.0.18 - Popular multim...
VLC Media Player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, MP3, OGG, ...) as well as DVDs, VCDs, and various streaming protocols. It... Read more

Latest Forum Discussions

See All

TouchArcade Game of the Week: ‘Sling Min...
The world of PC games has always blown my mind because there’s just SO MUCH stuff out there that it’s not uncommon at all for there to be a game that’s well-liked and well-reviewed, and seemingly quite popular with a solid fanbase, and have it be... | Read more »
SwitchArcade Round-Up: Reviews Featuring...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for December 2nd, 2022. So, today turned out a little quieter than the usual Friday. It was so quiet, in fact, that I decided to pen a few reviews. The Knight Witch, Railbound, and Donut... | Read more »
Blue Archive reveals its latest event st...
Nexon has announced the new update for Blue Archive, under the name of An Unconcealed Heart. Featuring a battle between two academies, the story will follow a group struggling to gain recognition, and will bring three new students to recruit. [... | Read more »
Dead Cells+ Is Out Now on Apple Arcade a...
Following the major update for Dead Cells on iOS and Android a few days ago, Playdigious has brought Dead Cells+ () to Apple Arcade. As an App Store Great, Dead Cells+ includes all prior paid DLC and content updates. It also has exclusive mobile... | Read more »
SwitchArcade Round-Up: ‘Romancing SaGa’,...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for December 1st, 2022. Wow, December. We’re already at the last month of the year? Phew. I have a lot of work to finish in the next few weeks. As for today, we’ve got a little news, a... | Read more »
‘Railbound’ Update Now Available Adding...
One of our favorite puzzlers released this year is Railbound from Afterburn Games, which hit in early September and earned our Game of the Week recognition for being an absolutely ace logic puzzler. The goal is to place rail pieces down in order to... | Read more »
The Seven Deadly Sins: Grand Cross celeb...
Netmarble Corporation has pulled out all the stops to celebrate the 3 and a half year anniversary of The Seven Deadly Sins: Grand Cross. The Grand Cross 3.5th Year Anniversary the Ultimate One, a rather wordy title, brings with it a brand new... | Read more »
‘Skullgirls Mobile’ Major Update 5.2 Out...
Developer Hidden Variable pushed out a major update for Skullgirls Mobile (Free) a few hours ago. The version 5.2 update brings in Black Dahlia (before the console and PC game), Retakes, XP Treats, free gifts, and more. Since launch, Skullgirls... | Read more »
Out Now: ‘Disgaea 4’, ‘Romancing SaGa: M...
Each and every day new mobile games are hitting the App Store, and so each week we put together a big old list of all the best new releases of the past seven days. Back in the day the App Store would showcase the same games for a week, and then... | Read more »
SwitchArcade Round-Up: ‘Elevator Action...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for November 30th, 2022. We’re finishing up the month on a quiet note, friends. There are five new releases to look at today, with a few notables amongst them. We’ve got summaries for... | Read more »

Price Scanner via MacPrices.net

New Holiday Sale: Apple retailers are offerin...
Several Apple retailers lowered prices on 10.9″ iPad Airs overnight to lows of $100 off MSRP starting at $499. Their prices are the lowest available for iPad Airs anywhere this Holiday season right... Read more
New Holiday sale at Amazon: Take $50 off Appl...
Amazon has Apple’s new 10th-generation iPads in stock and on sale, for the first time, for $50 off MSRP starting at only $399. Their discount applies to all models and all colors. With the discount,... Read more
Holiday Sale: Get an 8.3″ Apple iPad mini for...
Sams Club has 10.9″ 64GB iPad minis on Holiday sale for $80-$100 off MSRP through December 7, 2022. With their discount, prices start at $399 — the cheapest price for a new iPad mini from any of the... Read more
Sams Club Holiday December Event sale: Apple...
Apple AirPods Max headphones are on sale at Sams Club for $110 off MSRP ($439) as part of their December Event sale, ending on December 7, 2022, valid for all colors. Sale price for online orders... Read more
Apple’s 10.2″ 64GB 9th-generation iPads are o...
Sams Club has 9th-generation 64GB iPads on Holiday sale for $60 off MSRP through December 7, 2022. With their discount, prices start at $259 — the cheapest price for a new iPad from any of the Apple... Read more
11″ 128GB WiFi M2 iPad Pro on sale for $749,...
B&H Photo has the new 11″ 128GB WiFi M2-powered iPad Pro (in Space Gray or Silver) on Holiday sale for $749 including free 1-2 day shipping to most US addresses. Their price is $50 off MSRP and... Read more
Find the best Holiday sale price on an iPad u...
We’ve updated our iPad Price Trackers with the latest information on the new 10th-generation iPads, M2-powered iPad Pros, M1 iPad Airs, iPad minis, and 9th generation iPads from Apple’s authorized... Read more
Apple retailers are offering $100-$150 Holida...
Apple retailers have posted their most-recent Holiday sale prices on 13″ MacBook Airs. Take up to $150 off MSRP on M2-powered Airs with these sales with prices starting at only $1099. Free shipping... Read more
Holiday Sale: Apple’s 14″ MacBook Pros with M...
B&H Photo is offering $200-$300 discounts on Apple’s 14″ MacBook Pros with M1 Pro CPUs as part of their Holiday 2022 sale, with prices starting at $1799. Free 1-2 day shipping is available to... Read more
Deal Alert! 50% off Apple MagSafe Chargers
AT&T has Apple MagSafe Chargers on sale for 50% off MSRP as part of their Holiday sale. Service is not required to take advantage of these savings. With the discounts, their sale prices are the... Read more

Jobs Board

Support Technician II - *Apple* Support - O...
…problems and acting as a liaison between customers and resolving groups. As an Apple Technical Specialist, you will be supporting many of our popular Apple Read more
*Apple* Electronic Repair Technician - PlanI...
…a highly motivated individual to join our Production Department as an Apple Electronic Repair Technician. The computer repair technician will diagnose, assemble, Read more
Lead Developer - *Apple* tvOS - Rumble (Uni...
…earnings, and positive sentiment About the role: We are looking for a Lead Apple tvOS Developer to join our application engineering team to expand our video centric Read more
Tier 1 Endpoint Engineer - *Apple* - Red Ri...
…Desk on site, at our Client's location, with a focus on support to Apple products. This position will handle technical support requests directly from customers and Read more
Product Manager II - *Apple* - DISH (United...
…you will be doing We seek an ambitious, data-driven thinker to assist the Apple Product Development team as our new Retail Wireless division continues to grow and Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.