Apple Dylan Extensions and Framework Reference
Apple Dylan Extensions and Framework Reference
Preliminary
Developer Press
Apple Computer, Inc.
Apple Computer, Inc. manual is accurate. Apple is not If you discover physical defects in the
© 1993–1995 Apple Computer, Inc. responsible for printing or clerical manual or in the media on which a
All rights reserved. errors. software product is distributed, APDA
will replace the media or manual at no
No part of this publication or the Apple Computer, Inc.
charge to you provided you return the
software described in it may be 1 Infinite Loop
item to be replaced with proof of
reproduced, stored in a retrieval Cupertino, CA 95014
purchase to APDA.
system, or transmitted, in any form 408-996-1010
or by any means, mechanical, ALL IMPLIED WARRANTIES ON THIS
Apple, the Apple logo, APDA,
electronic, photocopying, recording, MANUAL, INCLUDING IMPLIED
HyperCard, LaserWriter, MacApp,
or otherwise, without prior written WARRANTIES OF
Macintosh, and MPW are
permission of Apple Computer, Inc., MERCHANTABILITY AND FITNESS
trademarks of Apple Computer, Inc.,
except in the normal use of the FOR A PARTICULAR PURPOSE, ARE
registered in the United States and
software or to make a backup copy LIMITED IN DURATION TO NINETY
other countries.
of the software. The same (90) DAYS FROM THE DATE OF THE
proprietary and copyright notices Geneva and Monaco are trademarks ORIGINAL RETAIL PURCHASE OF
must be affixed to any permitted of Apple Computer, Inc. THIS PRODUCT.
copies as were affixed to the America Online is a registered
Even though Apple has reviewed this
original. This exception does not service mark of America Online, Inc.
manual, APPLE MAKES NO
allow copies to be made for others, Adobe Illustrator, Adobe WARRANTY OR REPRESENTATION,
whether or not sold, but all of the Photoshop, and PostScript are EITHER EXPRESS OR IMPLIED, WITH
material purchased (with all backup trademarks of Adobe Systems RESPECT TO THIS MANUAL, ITS
copies) may be sold, given, or Incorporated, which may be QUALITY, ACCURACY,
loaned to another person. Under the registered in certain jurisdictions. MERCHANTABILITY, OR FITNESS
law, copying includes translating CompuServe is a registered service FOR A PARTICULAR PURPOSE. AS A
into another language or format. mark of CompuServe, Inc. RESULT, THIS MANUAL IS SOLD “AS
You may use the software on any
Docutek is a trademark of Xerox IS,” AND YOU, THE PURCHASER,
computer owned by you, but extra
Corporation. ARE ASSUMING THE ENTIRE RISK
copies cannot be made for this
FrameMaker is a registered AS TO ITS QUALITY AND
purpose.
trademark of Frame Technology ACCURACY.
Printed in the United States of
Corporation. IN NO EVENT WILL APPLE BE
America.
Helvetica and Palatino are LIABLE FOR DIRECT, INDIRECT,
The Apple logo is a trademark of
registered trademarks of Linotype SPECIAL, INCIDENTAL, OR
Apple Computer, Inc. Use of the
Company. CONSEQUENTIAL DAMAGES
“keyboard” Apple logo
Internet is a registered trademark of RESULTING FROM ANY DEFECT OR
(Option-Shift-K) for commercial
Digital Equipment Corporation. INACCURACY IN THIS MANUAL,
purposes without the prior written even if advised of the possibility of such
consent of Apple may constitute ITC Zapf Dingbats is a registered damages.
trademark infringement and unfair trademark of International Typeface
competition in violation of federal Corporation. THE WARRANTY AND REMEDIES
and state laws. PowerPC is a trademark of SET FORTH ABOVE ARE EXCLUSIVE
No licenses, express or implied, are International Business Machines AND IN LIEU OF ALL OTHERS, ORAL
granted with respect to any of the Corporation, used under license OR WRITTEN, EXPRESS OR IMPLIED.
technology described in this book. therefrom. No Apple dealer, agent, or employee is
Apple retains all intellectual authorized to make any modification,
Mercutio MDEF from Digital
property rights associated with the extension, or addition to this warranty.
Alchemy
technology described in this book. Copyright ©Ramon M. Felciano Some states do not allow the exclusion
This book is intended to assist 1992–1995, All Rights Reserved or limitation of implied warranties or
application developers to develop liability for incidental or consequential
applications only for Apple Simultaneously published in the damages, so the above limitation or
Macintosh computers. United States and Canada. exclusion may not apply to you. This
Every effort has been made to LIMITED WARRANTY ON MEDIA warranty gives you specific legal rights,
ensure that the information in this AND REPLACEMENT and you may also have other rights
which vary from state to state.
Contents
Chapter 1 Introduction 3
Apple Dylan and C-Compatible Libraries 5
Interface Importation 6
Cross-Language Calls 7
iii
iv
Chapter 4 Cross-Language Calls 69
About Cross-Language Calls 71
Types of Cross-Language Calls 71
Overview of a Cross-Language Call 72
Using Cross-Language Calls 74
Calling Imported Functions 75
Calling C Library Functions Using Function Pointers 77
Calling Apple Dylan Functions From C Libraries 79
v
Chapter 6 Access Paths 119
About Access Paths 121
Using Access Paths 122
Using File Options to Specify Information About Access Paths 122
Using the Inline Machine Code Access Path 124
Using The Code Fragment Manager Path 126
Creating a CFM Shared Library 126
Using CFM Shared Libraries 128
Using The Apple Shared Library Manager Access Path 129
Creating an ASLM Shared Library 131
Using ASLM Shared Libraries 132
Using The External Module Access Path 133
Creating a Custom Application Nub 134
Using Statically Linked External Modules 135
Using The Direct Pointer Access Path 135
Preparing a Code Resource 136
Loading and Unloading a Code Resource 138
Calling Functions Imported from a Code Resource 140
vi
Preemption Facilities Reference 178
Preemption Constants 178
Preemption Functions 178
Preemption Macros 181
Event-Checking Facilities Reference 183
Break-Request Variables and Functions 183
Event-Checking Functions 185
Microsecond Functions 187
vii
Termination Reference 211
Variables 211
Functions 211
viii
The <event> Class 267
Toolbox Event Classes 268
The <disk-event> Class 270
Key Event Classes 270
System Event Classes 271
Window Event Classes 271
Mouse Event Classes 273
The <become-target-event> Class 274
The <resign-target-event> Class 275
Functions for Event Handling 276
ix
About Frames 310
Frame Coordinate Systems 313
About Regions 314
About Text Styles 315
About Color 316
Using Graphics Objects 317
Changing an Object’s Location and Extent 317
Manipulating Regions and Rectangles 317
Defining Text Styles 318
Defining Colors 318
Graphics Objects Reference 319
The <frame> Class 319
Graphics Ports Classes 320
Text Style Classes 322
The QuickDraw Region Class 324
RGB Color Class 324
Graphics-Related Functions 325
x
View Objects Reference 354
The <view> Class 355
Adorner Classes 360
View Determiner Classes 362
View-Related Functions 364
Functions for Graphics Support 367
Functions for Adorners 368
Functions for View Determiners 369
xi
The <text-grid-view> Class 394
The <list-view> Class 394
The <text-list-view> Class 395
The <grid-select-behavior> Class 396
The <grid-arrow-key-behavior> Class 396
Grid and List View Related Functions 397
xii
Adding a Tabbing Behavior 432
Opening the Modal Dialog Box 432
Dialog and Control Objects Reference 433
The <dialog-behavior> Class 433
The <tabber> Class 435
The <edit-text-dialog-filter> Class 436
The <cluster> Class 437
The <simple-icon> Class 438
The <static-text> Class 439
The <control> Class 440
Subclasses of the <control> Class 442
The <button> Class 443
The <check-box> Class 443
The <radio> Class 443
The <scroll-bar> Class 444
The <popup> Class 445
Control Manager Control Classes 446
The <ctl-mgr-control> Class 446
The <ctl-mgr-button> Class 448
The <ctl-mgr-check-box> Class 449
The <ctl-mgr-radio> Class 450
The <ctl-mgr-scroll-bar> Class 451
The <ctl-mgr-popup> Class 452
Control Event Classes 454
The <default-button-adorner> Class 455
Functions for Dialogs and Controls 456
xiii
Scrolling and Tracking Objects Reference 471
The <scroller> Class 471
The <tracker> Class 473
The <tracker-adorner> Class 474
Functions for Scrolling and Tracking 475
xiv
Chapter 22 Streams 503
About Streams 505
About Class and Slot Specifications 507
Using Class and Slot Specifications 507
Setting up the Class and Slot Specifications 508
Using Slot Specification Getters and Setters 509
Cloning Objects 511
Using Shared and Default Objects 512
Using Streams 513
Using Handle Streams 513
Using Object Streams 514
Reading and Writing Objects 515
Reading and Writing Primitive Data Types 516
Stream Objects Reference 517
The <stream> Class 517
The <file-stream> Class 518
The <handle-stream> Class 519
Object Stream Classes 521
The <class-spec> Class 522
The <slot-spec> Class 523
Functions for Streams 525
xv
The <typing-command> Class 542
The <text-style-command> Class 544
The Font Command Classes 545
Functions for Commands and Command Contexts 547
xvi
Accepting a Drag 575
Receiving a Drop 576
Drag and Drop Objects Reference 576
The <drag> Class 577
The <drag-item> Class 578
The <drag-flavor> Class 579
Drag Event Classes 580
Functions for Drag and Drop 582
xvii
Scripting Support Objects Reference 607
The Apple Event Classes 607
The <ae-desc> class 607
The <ae-list> class 608
The <ae-record> class 609
The <apple-event> class 610
The <object-specifier> class 610
Descriptor Classes 611
The <token> class 612
Scripting Event Classes 612
Property Designator Classes 615
The <property> Class 616
The <document-property> Class 616
The <file-property> Class 617
The <text-view-property> Class 617
The <text-view-selection-property> Class 618
The <window-property> Class 618
Scripting Support Functions 619
xviii
Using the Busy Cursor Class 633
Using the Framework Library Class 633
Using the External Reference Table Class 634
Geometry Objects Reference 635
The <region> Class 635
The <rect> Class 635
Geometry Functions 637
String Objects Reference 639
The <handle-string> Class 639
The <resource-string> Class 640
String Resource Functions 641
Condition Objects Reference 642
The <framework-error> Class 642
The <os-error> Class 643
Error Condition Functions 644
Debugger Behavior Reference 645
The <debugger-behavior> Class 645
Busy Cursor Reference 646
The <busy-cursor> Class 646
Busy Cursor Functions 648
Library Objects Reference 649
The <framework-library> Class 649
Framework Library Functions 651
External Reference Table Reference 651
The <external-reference-table> Class 652
External Reference Functions 653
Miscellaneous Function Reference 654
Index 657
xix
xx
Figures, Tables, and Listings
Chapter 1 Introduction 3
Listing 4-1 Header file with function pointer type and functions 77
Listing 4-2 A header file using a callback function 79
Listing 6-1 A sample rez file for a CFM shared library 127
Listing 6-2 A sample ASLM header file 130
Listing 6-3 A sample rez file for an ASLM shared library 132
Listing 6-4 An assembly language transfer vector 137
Listing 6-5 Header file for functions imported from a code resource 140
xxi
xxii
Figure 11-8 Behavior class hierarchy 257
Listing 11-1 Specifying the next handler for a window 259
Listing 11-2 Defining a do-event method 260
Listing 11-3 Defining a behavior subclass 261
Listing 11-4 Defining a behavior’s response to an event 261
Listing 11-5 Handling the cursor from a behavior 262
Listing 11-6 Adding and removing a behavior 262
Listing 11-7 The <event-handler> class definition 263
Listing 11-8 The <main-handler> class definition 265
Listing 11-9 The <behavior> class definition 267
Listing 11-10 The <event> class definition 267
Listing 11-11 The <toolbox-event> class definition 268
Listing 11-12 The <disk-event> class definition 270
Listing 11-13 Class definitions for key events 270
Listing 11-14 Class definitions for system events 271
Listing 11-15 The <window-event> class definition 272
Listing 11-16 The <activate-event> class definition 272
Listing 11-17 The <update-event> class definition 273
Listing 11-18 Class definitions for mouse events 273
Listing 11-19 The <become-target-event> class definition 274
Listing 11-20 The <resign-target-event> class definition 275
Table 11-1 General event-handling functions 276
Table 11-2 Event-handling functions for behaviors 278
Table 11-3 Event-handling functions for dispatching 279
Table 11-4 Event-handling functions for streaming 279
xxiii
Listing 12-12 The <menu> class definition 298
Listing 12-13 The <apple-menu> class definition 300
Listing 12-14 The <menu-event> class definition 301
Table 12-1 Functions for manipulating entire menus 302
Table 12-2 Functions for manipulating menu items 303
Table 12-3 Functions for handling menu events 303
xxiv
Chapter 14 Views 333
xxv
Listing 15-5 The <number-text> class definition 380
Table 15-1 Functions for text views 381
Table 15-2 Functions for text styles 382
xxvi
Figure 18-5 Moveable modal dialog box 425
Listing 18-1 Creating a dialog box 425
Listing 18-2 Creating a moveable modal dialog box 429
Listing 18-3 Setting up dialog box dismissers 429
Listing 18-4 Creating static text 430
Listing 18-5 Creating number text 430
Listing 18-6 Implementing a popup menu 431
Listing 18-7 Determining the current choice ID 432
Listing 18-8 Adding tabbing behavior 432
Listing 18-9 Posing a Dialog Box 433
Listing 18-10 The <dialog-behavior> class definition 434
Listing 18-11 The <tabber> class definition 435
Listing 18-12 The <edit-text-dialog-filter> class definition 436
Listing 18-13 The <cluster> class definition 437
Listing 18-14 The <simple-icon> class definition 438
Listing 18-15 The <static-text> class definition 439
Listing 18-16 The <control> class definition 441
Listing 18-17 The <button> class definition 443
Listing 18-18 The <check-box> class definition 443
Listing 18-19 The <radio> class definition 444
Listing 18-20 The <scroll-bar> class definition 444
Listing 18-21 The <popup> class definition 445
Listing 18-22 The <ctl-mgr-control> class definition 446
Listing 18-23 The <ctl-mgr-button> class definition 449
Listing 18-24 The <ctl-mgr-check-box> class definition 450
Listing 18-25 The <ctl-mgr-radio> class definition 450
Listing 18-26 The <ctl-mgr-scroll-bar> class definition 451
Listing 18-27 The <ctl-mgr-popup> class definition 452
Listing 18-28 The <control-event> class and subclass definitions 454
Listing 18-29 The <default-button-adorner> class definition 455
Table 18-2 Functions for Control Manager controls 456
Table 18-3 Functions for Control Manager scroll bar controls 456
Table 18-4 Functions for Control Manager popup menu controls 457
Figure 19-1 The relationship between a scroller view, scroll bars, and a content
view 461
Figure 19-2 Scrolling view hierarchy 462
Figure 19-3 The translation between a content view and a scroller 462
xxvii
Figure 19-4 Mouse tracking feedback 464
Listing 19-1 Setting up a scrolling view 465
Listing 19-2 Setting up a scroller view 467
Listing 19-3 Initiating mouse tracking 468
Listing 19-4 Defining a <tracker> subclass 468
Listing 19-5 Beginning mouse tracking 469
Listing 19-6 Ending mouse tracking 470
Listing 19-7 Constraining tracking 470
Listing 19-8 Implementing feedback 471
Listing 19-9 The <scroller> class definition 472
Listing 19-10 The <tracker> class definition 473
Listing 19-11 The <tracker-adorner> class definition 474
Table 19-1 Functions for scrolling 475
Table 19-2 Functions for tracking 475
xxviii
Chapter 22 Streams 503
xxix
Listing 23-8 The <command-context> class 539
Listing 23-9 The <command> class 540
Listing 23-10 The <typing-command> class 542
Listing 23-11 The <text-style-command> class 544
Listing 23-12 The <font-command>, <font-size-command>, and
<font-style-command> classes 546
Table 23-1 Functions for command contexts 547
Table 23-2 Functions for commands 548
Table 23-3 Functions for typing commands 548
xxx
Chapter 25 Drag and Drop 569
xxxi
Listing 27-2 Responding to an Apple event 606
Listing 27-3 Responding to an Apple event 606
Listing 27-4 Associating a scripting object with a window 606
Listing 27-5 The <ae-desc> class 608
Listing 27-6 The <ae-list> class definition 609
Listing 27-7 The <ae-record> class definition 609
Listing 27-8 The <apple-event> class definition 610
Listing 27-9 The <object-specifier> class definition 610
Listing 27-10 Apple event descriptor class definitions 611
Listing 27-11 The <token> subclass 612
Listing 27-12 The <scripting-event> subclass 613
Listing 27-13 Scripting event subclasses 614
Listing 27-14 The <property> class 616
Listing 27-15 The <document-property> class 617
Listing 27-16 The <file-property> class 617
Listing 27-17 The <text-view-property> class 618
Listing 27-18 The <text-view-selection-property> class 618
Listing 27-19 The <window-property> class 619
Table 27-3 Object model functions 619
Table 27-4 Scripting event functions 620
Table 27-5 Apple event descriptor functions 620
Table 27-6 Apple event descriptor list and record functions 621
Table 27-7 Apple event object specifier and descriptor functions 622
Table 27-8 Apple event descriptor list and record functions 623
xxxii
Table 28-5 Error condition functions 644
Table 28-6 Error string functions 644
Table 28-7 Functions for <os-error> objects 645
Listing 28-10 The <debugger-behavior> class definition 646
Listing 28-11 The <busy-cursor> class definition 646
Table 28-8 Busy cursor functions 648
Listing 28-12 The <framework-library> class definition 649
Table 28-9 Framework library functions 651
Listing 28-13 The <external-reference-table> class definition 652
Table 28-10 External reference functions 653
Table 28-11 Environment functions 654
Table 28-12 Miscellaneous utility functions 654
Table 28-13 Miscellaneous goodie functions 655
xxxiii
xxxiv
P R E F A C E
This book lists the language extensions that Apple has made to the Dylan
language, including the Apple Dylan framework extensions.
This book is not designed explicitly to teach object-oriented programming nor
the Dylan language. Familiarity with Macintosh application development,
object-oriented programming and the Dylan language is assumed. For
information about how to write Apple Dylan programs, see the book
Programming in Apple Dylan. For information about the Dylan language, see the
book Dylan Reference Manual. For information about Macintosh programming,
see Inside Macintosh.
Chapter Organization 0
This book is divided into two parts; Part I covers the Apple Dylan language
extensions, and Part II covers the Apple Dylan framework. Most chapters in
this book follow a standard general structure. For example, the chapter “Event
Handling” on page 241 contains these sections:
■ “About Event Handling.” This section provides an overview of the
event-handling mechanism in the Framework.
■ “Using Event Handling Objects.” This section describes the tasks you can
accomplish by handling events. It describes how to use the most common
functions and provides code samples.
■ “Event Handling Objects Reference.” This section provides a complete
reference for general purpose event-handling classes. (Classes related to
menu event handling, for example, are described in the Menus chapter.) This
section also identifies the functions that you can use with event handling.
xxxv
Special Fonts 0
All code listings, reserved words, and the names of data structures, constants,
fields, parameters, and functions are shown in a monospaced font (this is
monospaced).
Types of Notes 0
There are several types of notes used in this book.
Note
A note like this contains information that is interesting but
possibly not essential to an understanding of the main
text. ◆
IMPORTANT
A note like this contains information that is especially
important. ▲
Numerical Formats 0
Hexadecimal numbers are shown in this format: #x0008.
The numerical values of constants are shown in decimal, unless the constants
are flag or mask elements that can be summed, in which case they are shown in
hexadecimal.
xxxvi
P R E F A C E
xxxvii
P R E F A C E
xxxviii
PART ONE
1 Introduction
Contents
Apple Dylan and C-Compatible Libraries 5
Interface Importation 6
Cross-Language Calls 7
Contents 3
4 Contents
C H A P T E R 1
Introduction 1
This chapter provides a brief overview of the Apple Dylan language extensions
used to communicate with C-compatible libraries. The chapter begins by
examining the motivation of these language extensions, and then it surveys the
features provided by them.
Neither this chapter nor any part of this book is intended to provide a tutorial
introduction to these facilities. You can find tutorial material in the
accompanying book, Programming In Apple Dylan.
Introduction
the ability to make cross-language calls is only one of the many features offered
by the Apple Dylan language extensions.
Interface Importation 1
The C library extensions of Apple Dylan offer a number of features to facilitate
communication between Apple Dylan and other programming languages.
The first of these is interface importation. Before your Apple Dylan program
can make calls to C library functions, it must have some internal representation
of the interface to those functions—for example, your Apple Dylan program
needs to know what functions are available to it, and how many and what type
of values those expect as input and provide as output.
C-compatible languages use C header files to specify this type of information.
Interface importation is the process Apple Dylan uses to parse C header files
and produce a set of Apple Dylan objects that act as mediators between your
Apple Dylan program and C library code. In general, the goal of interface
importation is to create an Apple Dylan interface to C library functions—a set
of Apple Dylan objects that look and act like other Apple Dylan objects, but
that are actually conduits to C libraries.
Here are some parts of a C interface you can import into Apple Dylan:
■ Constants. C header files can define constants in a number of ways: const
variables, #define macros, enum constants. You can import constants defined
in a C header file into Apple Dylan. The resulting objects are Apple Dylan
constants—read-only variables you can reference in your program.
■ Types. C header files also define data types. These type definitions control
the shape of the data passed to and from the functions. Of particular
importance in C is the structure type definition. Apple Dylan imports
structure types as classes. You use these classes like other Dylan classes—
making instances, accessing slots, passing to functions. The difference is that
these classes’ objects are implemented using standard C structures.
Therefore, they can be accessed by C functions as easily as by Dylan ones.
■ Functions. Function definitions, of course, are a crucial part of C header
files. When importing functions, Apple Dylan creates function objects. These
function objects can be called from your program like other Apple Dylan
functions, but the purpose of one of these functions is to translate
6 Interface Importation
C H A P T E R 1
Introduction
Cross-Language Calls 1
After an interface is imported, you can use the resulting Apple Dylan objects to
perform cross-language calls.
Before you attempt to call an imported function, or examine an imported
variable, you must inform Apple Dylan how to find the compiled function or
the stored variable. In effect, you must ensure that Apple Dylan has a way to
link the interfaces imported from a C header file to actual runtime C objects in
Cross-Language Calls 7
C H A P T E R 1
Introduction
memory. Apple Dylan supports five different linking mechanisms you can
choose. These linking mechanisms are called access paths. You can use these
access paths to find Macintosh Toolbox functions, functions in shared libraries,
code fragments, code resources, and so on.
Access paths solve the problem of finding C runtime entities. Another problem
that must be addressed is the problem of communicating with these entities.
How do you use Apple Dylan objects to pass information in and out of C
functions? The answer is value translation, which is a consequence of the type
mappings established during interface importation. During a cross-language
call, the type mappings for the arguments (of the function being called) control
how values encoded as Apple Dylan objects are translated to C values, and
how C values are translated back into Apple Dylan objects.
Apple Dylan passes many types of values between languages by pointer. To
facilitate this, Apple Dylan provides pointer objects—objects used by your
Apple Dylan program that contain pointers to C runtime entities—pointers to
C structures, pointers to C strings, pointers to C functions, and so on. Apple
Dylan provides an array of pointer classes for the different kinds of pointers.
During value translation, Apple Dylan converts between C pointers and Apple
Dylan pointer objects that point to the same address in memory.
Pointer-to-function objects provide two more powerful abilities:
■ You can use these pointer objects to call C functions by pointer using the
callout mechanism: You use Apple Dylan to create a function that takes a
function pointer as an argument and calls the C function pointed to by that
pointer.
■ You can also use function-pointer objects to call Apple Dylan code from C
library functions using the callback mechanism: You create a C-callable
Apple Dylan function and Apple Dylan provides you with a
function-pointer object for it. When you pass the function-pointer object to C
functions, value translation translates it into a valid C pointer, which the C
function can then use to call the Apple Dylan function.
Finally, Apple Dylan provides some low-level facilities that you can use to
manipulate pointers and data in memory directly. You can also use these
facilities to call functions using a machine-level interface.
8 Cross-Language Calls
Figure 2-0
Listing 2-0
C H A P T E R 2 Table 2-0
2 Interface Definitions
Contents
About Interface Definitions 11
Interface Importation 12
The Interface Importation Process 13
Importing C Definitions 14
Importing C Containers 16
Name Mapping 16
Type Mapping 17
Interface Definitions 18
File Clauses 19
Other Clauses 21
Using Interface Definitions 23
Using File Clauses 23
Importing C Header Files 23
Controlling Conditional Processing 24
Selectively Importing or Excluding C Definitions 26
Controlling Dynamism 27
Using Other Types of Clauses 31
Using Structure and Union Clauses 31
Using Function Clauses 34
Using Variable Clauses 35
Using Constant Clauses 37
Using Callout and Callback Clauses 38
Interface Definition Reference 39
Interface Definition Syntax 39
Interface Definition Clauses 39
File Options 42
Contents 9
Container Options 43
Constant Options 46
Variable Options 47
Function Options 49
Callback Options 51
10 Contents
C H A P T E R 2
Interface Definitions 2
Interface Definitions
Interface Importation 2
Interface importation is the process by which a programming interface defined
in a C header file becomes available to Apple Dylan. When you import an
interface, Apple Dylan creates objects that correspond to entities defined in the
C header file. These objects, called imported objects, provide your program
with access to the C definitions.
There are two basic categories of C entities Apple Dylan allows you to import:
■ C definitions, which include function, constant, variable, and type
definitions.
■ C containers, which include C header files and structure and union type
definitions.
Note that structure and union types are both definitions and containers.
Apple Dylan imports C definitions as objects, as described in this table:
C header files are not imported as objects. Instead, the entities defined within
them are imported individually, as indicated in these two tables. Structure and
Interface Definitions
union types are imported as Apple Dylan classes. The entities defined within
structure and union types are also imported:
■ Type mapping. Apple Dylan associates an Apple Dylan class with each C
type used in the definition. For example, if the definition is a function
definition with one argument of type long, Apple Dylan associates the Apple
Dylan class <integer> with that argument when importing the function.
These processes are introduced in more detail later in this chapter. You can find
the complete discussions in Chapter 3, “Name Mapping,” and Chapter 5,
“Type Mapping.”
After parsing the C header file and translating the C definition, Apple Dylan
creates an Apple Dylan object that corresponds to the C entity (or, in some
cases, two Apple Dylan objects—a getter and a setter).
Apple Dylan provides default behavior for each aspect of the importation
process. You can modify this behavior in two ways: you can specify different
default behavior for the definitions inside an imported container, and you can
explicitly override the default behavior for specific imported definitions.
Interface Definitions
Importing C Definitions 2
This section discusses the different types of C definitions you can import from
C header files and includes information specific to each.
■ Constants. You can import three kinds of constants from C header files:
n variables declared with a const modifier
n constants defined within an enum declaration
n macro constants defined with the #define directive
A macro constant is a #define macro with no parameter list (macros with
parameter lists are imported as functions as described below). The body of
the macro must be a constant expression.
Apple Dylan translates the constant value when the constant is imported.
Therefore, when you reference the constant in your program, no
cross-language call is necessary.
Apple Dylan allows you to import C constants as read-only variables or as
inline code.
■ Functions. Apple Dylan allows you to import C function declarations from
C header files into Apple Dylan. In addition to standard function
declarations, you can also import macro functions—#define macros with
parameter lists. However, Apple Dylan must be able to translate the body of
the macro. In particular, after macro expansion the body of the macro must
be a simple expression that contains only these types of references:
n references to the parameters of the macro
n function calls to imported functions
n type casts using imported types
As with constants, you can import C function definitions as runtime objects
or as inline code.
Apple Dylan creates a new function object that provides an Apple Dylan
interface to a C function. When you call this function:
n It uses type mapping to translate the Apple Dylan objects you provide as
arguments into C values.
n It uses an access path to locate the corresponding C library function.
n It uses C calling conventions to pass the arguments to the C function.
n It uses type mapping again to translate any C values returned by the C
library function into Apple Dylan objects.
Interface Definitions
Interface Definitions
Importing C Containers 2
Name Mapping 2
Apple Dylan allows you to rename C definitions when you import them into
your Apple Dylan program. Common reasons for renaming imported
definitions include:
■ to resolve name conflicts that arise when importing multiple C definitions
into the same Apple Dylan module
■ to ensure that the imported names follow Apple Dylan naming conventions
Interface Definitions
Type Mapping 2
Interface Definitions
Apple Dylan class is the class of Apple Dylan object the imported function
expects for the argument.
When you call the imported Apple Dylan function, you provide arguments of
the appropriate Apple Dylan classes. Apple Dylan translates each argument to
a C value of the C type specified by the argument’s type mapping.
In this way, the type mappings established during interface importation allow
for type checking and value translation during cross-language calls.
During interface importation, Apple Dylan performs default type mapping for
you. You can modify the default type-mapping behavior for any imported C
container. You can also override the default behavior by specifying explicit type
mappings for any imported C entity.
Chapter 5, “Type Mapping,” provides the complete discussion of type mapping
and value translation.
Interface Definitions 2
Apple Dylan provides the interface definition, which you can use to import C
interfaces. An interface definition is a program constituent—you use it like
other types of Apple Dylan definitions.
An interface definition is structured as a series of clauses. Each clause specifies
a C definition or a C container to import. Each clause can also contain options,
which you use to override the default behavior provided by Apple Dylan.
The syntax of an interface definition is
define interface
{ interface-clause ;}
end [ interface ]
Interface Definitions
When you import a C header file that includes other C header files, Apple
Dylan does not automatically import the included C header files. You should
provide an interface definition for every C header file that contains definitions
you want to import.
You execute an interface definition, like any Apple Dylan definition, in a
specific module. Apple Dylan imports the C entities into that module.
The section “Interface Definition Syntax” on page 39 contains reference
information about interface definitions.
File Clauses 2
define interface
#include "SampleHeader.h";
end interface;
Interface Definitions
Interface Definitions
Other Clauses 2
In general, file clauses allow you to import entities from a C header file, and
container options allow you general control over how these C entities are
imported. The other types of interface definition clauses are provided to allow
you explicit control over the importation of specific C entities.
In addition to file clauses, Apple Dylan provides these container clauses:
■ Structure and union clauses allow you to specify information about how to
import a specific structure; in particular, you can specify information about
how to import the members of the structure.
These clauses, like file clauses, allow you to use container options to specify
how the definitions within the container (the members of the structure or
Interface Definitions
union) are imported. For example, you can use the read-only container option
to specify that the members of the structure are imported as getter functions
without corresponding setter functions.
The container options you specify in a a structure or union clause override the
container options for the file.
Apple Dylan also provides these three definition clauses:
■ Constant clauses allow you to modify the importation of a specific constant.
You use constant options to specify information about how to import the
constant.
■ Variable clauses allow you to modify the importation of a specific variable.
You use variable options to specify information about how to import the
variable.
■ Function clauses allow you to modify the importation of a specific function.
You use function options to specify information about how to import the
function.
Constant, variable, and function options override the default options specified
for the container that contains the constant, variable, or function. You can find
examples of these options in “Using Other Types of Clauses” on page 31.
There are also two special interface definition clauses. These clauses create
interfaces based on imported C pointer-to-function types:
■ Callback clauses create Apple Dylan functions that can call C functions
using a function pointer.
■ Callout clauses create Apple Dylan macros that you can use to create Apple
Dylan functions that can be called from C.
You can find examples using these types of clauses in Chapter 4,
“Cross-Language Calls.”
The section “Interface Definition Reference” on page 39 contains reference
information for all of the interface definition clauses and options.
Interface Definitions
The simplest version of an interface definition contains a single file clause with
no options, for example:
define interface
#include "QuickDraw.h";
end interface
Interface Definitions
This interface definition specifies that Apple Dylan import every entity defined
in the C header file QuickDraw.h. In other words, when this interface definition
is compiled, Apple Dylan creates an Apple Dylan interface to every importable
C entity defined in the header file.
Apple Dylan provides many options you can specify in the file clause of an
interface definition. These options allow you to specify information about the C
header file, to specify which C entities to import from the file, and to specify
default importing behavior for those entities.
The define and undefine file options allow you to control conditional
processing when Apple Dylan parses a header file.
The define option allows you to define preprocessor macros. For example, this
interface definition:
define interface
#include "SampleHeader.h",
define: { "my_macro" };
end interface;
indicates that Apple Dylan should import C entities from the file
SampleHeader.h, parsing the file as if it contained this macro:
#define my_macro
You can also use the arrow (=>) option to specify a particular value for a
preprocessor macro:
define interface
#include "SampleHeader.h",
define: { "my_macro" => 10 };
end interface;
#define my_macro 10
Interface Definitions
You can include multiple definitions in a single define option. For example,
consider the following interface definition:
define interface
#include "SampleHeader.h",
define: { "SystemSixOrLater" => 0 };
end interface;
This interface definition indicates the Apple Dylan should parse the C header
file as if it contained this C preprocessor macro:
#define SystemSixOrLater 0
which indicates that the functions in this header file will not necessarily be run
under Macintosh System Software version 6.0 or later.
The five default settings for C preprocessor macros are
#define __Dylan
#define applec
#define SystemSixOrLater 1
#define OLDROUTINENAMES 0
#define CGLUESUPPORTED 0
Interface Definitions
define interface
#include "SampleHeader.h",
define: { "SystemSevenOrLater" => 1,
"_STDC_" => 1};
undefine: { "applec" };
end interface;
This interface defines two additional preprocessor macros, and also undefines
one that would be defined by default.
The other file options concern access paths, and are discussed in Chapter 6,
“Access Paths.”
The import and exclude container options allow you to control which C entities
are imported from a C header file.
The import container option allows you to limit which C entities are imported
by naming the ones you want to import.
As an example, consider this C header file:
define interface
#include "QuickDraw.h",
import: { "Random", "GlobalToLocal" };
end interface
This interface definition imports two functions from the file QuickDraw.h—the
Random function and the GlobalToLocal function. The other C entities defined in
that file are not imported.
You can explicitly import all the C entities in a header file by specifying the
value all for this option:
define interface
#include "SampleHeader.h",
import: all;
end interface;
This value is the default value for this option—if you do not explicitly limit the
C entities to import, Apple Dylan imports them all.
Interface Definitions
Notice that the all option is not surrounded by braces or by quotes. The
following interface definition does not import all of the entities from a C header
file:
define interface
#include "SampleHeader.h",
import: { "all" }; // WARNING! This is a common mistake.
end interface;
This definition attempts to import a C entity named all, rather than all of the
entities.
You can also use the import option to rename C entities as you import them.
See Chapter 3, “Name Mapping,” for more details.
While the import option allows you to selectively import C entities by
specifying the entities you want to import, the exclude option allows you to
selectively import C entities by naming the ones you do not want to import.
Here is an example:
define interface
#include "Files.h",
exclude: { "AddDrive", "FSOpen" };
end interface;
This interface definition imports every C entity from the header file Files.h
except the functions named AddDrive and FSOpen. You might want to use the
exclude option for a number of reasons:
■ to exclude Macintosh Toolbox functions that are not in ROM (because Apple
Dylan has no access path to these functions)
■ to exclude other unnecessary or undesired C entities
■ to exclude redundant types, as explained in Chapter 5, “Type Mapping.”
Controlling Dynamism 2
Interface Definitions
define interface
#include "SampleHeader.h",
inline-constants: #f;
end interface;
This interface definition specifies that constants imported from the header file
SampleHeader.h be imported as objects that exist during runtime while your
program is executing.
Whether the default behavior you choose is to inline constants or to create
runtime objects, you can always override that default behavior for specific
constants using a constant clause, as described in “Using Constant Clauses” on
page 37.
Setting the inline-constants option to #f causes constants to be defined in the
style of define constant. Setting this option to #t causes constants to be defined
Interface Definitions
in the style of define inline constant (with the additional feature that no
runtime object is created for unused constants).
The read-only option allows you to specify whether imported variables (and
imported structure members) are imported as getter functions, or as getter/
setter pairs of functions. By default, Apple Dylan imports variables as getter/
setter function pairs. You can override this behavior using this container option:
define interface
#include "SampleHeader.h",
read-only: #t;
end interface;
With this interface definition, all of the variables imported from the file
SampleHeader.h are imported as getter functions. No setter functions are created.
You can override the default behavior for specific variables by using variable
clauses, as described in “Using Variable Clauses” on page 35.
The seal-functions option (which also applies to function macros and to getter
and setter functions for imported variables and structure members) allows you
to select one of the following three representations for imported functions:
■ As a generic function method, specified by seal-functions: open. In this
case, Apple Dylan creates a runtime object (a method) that represents the C
entity, and adds this method to a generic function. This approach maximizes
runtime flexibility, but it increases memory usage and may slow
cross-language calls slightly.
■ As a generic function method with a sealed domain, specified by
seal-functions: seal. This case is the same as the previous case except it
uses define sealed method instead of define method, allowing for increased
compiler optimization.
■ As a bare method that is always compiled inline, specified by
seal-functions: inline. This case is the default. The function is defined in
the style of define inline constant (with the additional feature that no
runtime object is created for unused functions). In this case, Apple Dylan
does not create a runtime object to represent the C entity; instead, the
development environment maintains information about the imported entity
and uses this information to replace references to the imported entity with
inline code. This approach provides little runtime flexibility, but it eliminates
memory requirements and optimizes the speed of cross-language calls. This
Interface Definitions
can save a lot of space if you import the entirety of a large header file but
only call a few of its functions.
You can override this default behavior to import functions as generic functions.
For example:
define interface
#include "SampleHeader.h",
seal-functions: open;
end interface;
This interface definition imports all of the C entities from the header files
SampleHeader.h as methods added to generic functions.
You can also import functions as generic function methods with a sealed
domain:
define interface
#include "SampleHeader.h",
seal-functions: sealed;
end interface;
This interface definition imports functions as method objects, adds the method
objects to generic functions, and seals the generic function branches. (It works
similarly to define sealed method.)
■ Open functions provide the greatest amount of dynamism. However, they
also potentially require the greatest amount of runtime storage space and the
greatest amount of overhead when making a cross-language function call.
■ Sealed functions provide less dynamism, but are potentially more efficient
than open functions.
■ Inline functions provide the least dynamism. However, this is the fastest
interface to imported functions and no runtime objects are required.
The seal-functions option specifies the default behavior for all functions and
function macros imported from a C header file. It also applies to all of the
getter and setter functions created when importing variables.
You can override the default behavior for specific functions and variables by
using function and variables clauses, as described in “Using Function Clauses”
on page 34 and “Using Variable Clauses” on page 35.
Interface Definitions
The remaining container clauses control name mapping and type mapping. See
Chapter 3, “Name Mapping,” and Chapter 5, “Type Mapping,” for examples
using those options.
Apple Dylan imports C structures (and unions) as Apple Dylan classes. For
example, consider this structure type defined in the header file Types.h:
struct Point {
short v;
short h;
};
Interface Definitions
You can import this structure type using the following interface definition:
define interface
#include "Types.h",
import: { "Point" => <CPoint> };
end interface;
This interface definition contains a single clause—a file clause with an import
option specifying that the C entity named Point should be imported from the C
header file Types.h (and renamed <CPoint> to avoid conflicts with the built-in
class <Point>).
Importing this C structure type creates a single Apple Dylan entity—a class
named <CPoint>. You can use this class to create C Point structures, and to pass
C Point structures during cross-language calls. See Chapter 5, “Type
Mapping,” for examples.
This structure clause is a container clause. By default, a container clause
indicates that Apple Dylan should import all entities defined within the
container. As a result, the above interface definition creates five Apple Dylan
entities:
■ an Apple Dylan class named <CPoint>
■ a function named Point$v
■ a function named Point$v-setter
■ a function named Point$h
■ a function named Point$h-setter
You use these getter and setter functions to access members of a Point structure
as if they were slots of an Apple Dylan class with the names Point$v and
Point$h. (These names result from the default name-mapping rules discussed
in the next chapter.)
By default, these functions are inline code. You can override that behavior
using the seal-functions container option:
define interface
#include "Types.h",
import: { "Point" => <CPoint> };
Interface Definitions
struct "Point",
seal-functions: open;
end interface
This interface definition uses the seal-functions container option to override the
default Apple Dylan behavior (which is to import structure members as inline
code) and instead create methods, which are added to generic function objects,
to represent the imported getter and setter functions.
You can also use other container options to modify the importation of these
structure members:
define interface
#include "Types.h",
import: { "Point" => <CPoint> };
struct "Point"
seal-functions: open,
read-only: #t,
import: { "h" };
end interface
This interface definition imports the Point structure type. It also uses an import
container option to import one of the members of this structure—the h member.
It also uses the read-only container option to specify that no setter function
should be created. As a result of this interface definition, three Apple Dylan
objects are created:
■ a class named <CPoint>
■ a generic function named Point$h
■ a method for Point$h specialized to the <CPoint> class
When you import a structure type (or a union type) that contains an
anonymous structure type (or union type), Apple Dylan ignores the extra level
of hierarchy. For example, consider this C struct:
struct doubleStruct {
int i;
struct {
char a;
Interface Definitions
char b;
} s;
};
When you import this structure type, Apple Dylan creates a class with three
slots: doubleStruct$i, doubleStruct$a, and doubleStruct$b. The original
member named s is ignored; its members are used directly instead.
The reference at the end of this chapter discusses the syntax of container
clauses and container options. You can find more information about importing
structure types and union types in Chapter 3, “Name Mapping,” and in
Chapter 5, “Type Mapping.”
Function clauses allow you to specify more options, and override default
options, when importing functions. In particular, you can use the function
options, which are listed here, to specify information about the imported
function:
■ The seal option allows you to specify whether a function is imported as an
open method, a sealed method, or as inline code. It overrides the
seal-functions option of the C container containing the function.
■ The argument-type and result-type options allow you to specify explicit
type mappings for a function’s arguments and result, respectively (which
you might want to do, for example, when a C integer is used as a Boolean
value). These type mappings override type mappings for the C container
that contains the imported function. Chapter 5, “Type Mapping,” discusses
these options.
■ The input-argument, output-argument, and input-output-argument
options allow you to specify, for each argument of an imported function,
whether the argument is used only for input, only for output, or for both.
Chapter 4, “Cross-Language Calls,” and Chapter 5, “Type Mapping,”
discuss these options in detail.
As a simple example, consider the following C function definition:
You might import this function using the following interface definition:
Interface Definitions
define interface
#include "SampleHeader.h",
seal-functions: open;
function "Negate",
seal: inline;
end interface;
This interface definition imports entities from the C header file SampleHeader.h.
In particular, it uses the seal-functions option to specify that functions
imported from the header file should be imported as open methods by default.
The interface definition uses a function clause to override this default behavior
for the imported C function Negate. The seal option in this clause specifies that
this particular function should be imported as inline code. This option
overrides the seal-functions option specified for the header file.
Note
To call imported functions, you must use one of the access
paths described in Chapter 6, “Access Paths.” ◆
For more examples of importing functions and using function clauses, see
Chapter 4, “Cross-Language Calls,” and Chapter 5, “Type Mapping.”
Variable clauses allow you to specify more information about the getter and
setter functions that Apple Dylan uses to access imported global variables and
the members of imported C structures and unions.
You can use the variable clause, without using any variable options, to rename
an imported structure member. You can also use the variable options to specify
additional information, or to override default information, when importing a
variable:
■ The getter and setter options allow you explicit control over the names of
the imported getter and setter functions. See Chapter 3, “Name Mapping,”
for more information.
■ The type option allows you to specify the class that the imported variable
should be type-mapped to—that is, the class of object that is returned by the
Interface Definitions
getter function and expected by the setter function. See Chapter 5, “Type
Mapping,” for more information.
■ The read-only option allows you to specify that Apple Dylan create only a
getter function for the imported variable or slot—that is, no setter function.
■ The seal option allows you to specify whether the getter and setter functions
for an imported structure member are open methods, sealed methods, or
inline code.
For example, consider this interface definition
define interface
#include "SampleHeader.h",
import: { "Point" => <CPoint>, "origin" };
variable "origin",
seal: open;
variable "Point::h",
read-only: #t;
end interface;
Interface Definitions
variable "Point::h",
setter: #f;
The value #f for the setter option indicates that no setter function should be
created for the imported member.
Note
Not all access paths provide access to C library variables.
See Chapter 6, “Access Paths,” for more information. ◆
See the reference section at the end of the chapter for the syntax description of
variable clauses and options. Chapter 3, “Name Mapping,” Chapter 4,
“Cross-Language Calls,” and Chapter 5, “Type Mapping,” contain related
information.
Constant clauses allow you to specify information about how Apple Dylan
imports constants from C header files, using these two constant options:
■ The inline option allows you to specify whether a constant is imported as
inline code or as a named constant object in memory. This option overrides
the default behavior for the C container that contains the constant.
■ The value option allows you to specify an explicit Apple Dylan value for the
constant, which you might want to do if the original C value is
inappropriate.
Here is an example:
define interface
#include "SampleHeader.h;
constant "kConstant",
inline: #f;
value: 100;
end interface;
Interface Definitions
Callout and callback clauses allow you to make cross-language calls using
function pointers. For both of these types of clauses, you specify a C function
pointer type to use. (Note: the C function pointer type must be imported
separately.)
■ A callout clause creates a corresponding callout function. You pass function
pointers of the imported type to the callout function, and it calls the
indicated C function for you.
■ A callback clause creates a corresponding callback macro. You use the
callback macro to define a callback function—a special Apple Dylan
function that is callable from C. The callback macro provides you with a
function pointer of the imported type that points to the callback function.
You can pass this function pointer to C functions, which can use it to call
your callback function.
You can use the function options with a callout or callback clause. When used
with one of these clauses, they modify the resulting callout or callback function.
The reference section, which follows, gives the syntax of the callout and
callback clauses. Chapter 4, “Cross-Language Calls,” gives examples of using
callout and callback functions.
Interface Definitions
define interface
{ interface-clause ;}
end [ interface ]
Each interface definition begins with the words define interface, contains
some number of interface definition clauses separated by semicolons, and ends
with the word end followed optionally by the word interface. The first clause
must be a file clause.
There are eight types of interface definition clauses, shown in the following list.
Notice that in these clauses, C entities are named using string literals (that is, in
quotes), whereas names of Apple Dylan entities are variable names (that is, not
in quotes).
Interface Definitions
Interface Definitions
Interface Definitions
File Options 2
The file options specify information about the header file and how it should be
parsed. File options are specified as part of a file clause.
undefine: { { string ,} }
language: C | ASLM
external-module: variable-name
CFM-library: string
CFM-library-version: integer
CFM-library-oldest-version: integer
These six file options exclusive to file clauses are described below.
■ The define option defines preprocessor macros for conditional parsing of the
header file. Define options contain a list of macro definitions, which have the
syntax
string [ => literal ]
where string is a string literal indicating the name of the macro to define, and
literal is an optional literal constant that indicates the macro’s defined value.
(The literal constant defaults to the value 1; if you provide it, you must
specify a number or a string.) See “Controlling Conditional Processing” on
page 24 for the default value of this option.
Interface Definitions
Container Options 2
Interface Definitions
container options can be used with file clauses, structure clauses, and union
clauses.
When one container is inside another (for example, a structure type definition
within a C header file), any container options specified for the inner container
(for example, the structure) override container options specified for the outer
container. The values for container options not specified for the inner container
are the same as for the enclosing container (except for import, exclude, and
rename).
Here are the syntax descriptions for the container options:
exclude: { { string ,} }
inline-constants: #f | #t
read-only: #f | #t
prefix: string
name-mapper: function
Interface Definitions
which indicates that all importable entities within the container should be
imported; they can also have the syntax
{ { string [ => variable-name ] ,} }
Interface Definitions
Constant Options 2
The constant options allow you to specify additional information about how to
import a particular C constant. You can use these options to override the
options of an enclosing container.
Here are the syntax descriptions for the constant options:
value: expression
Interface Definitions
Variable Options 2
The variable options allow you to specify additional information about how to
import a particular C variable or structure/union member. You can use these
options to override the options of an enclosing container.
Here are the syntax descriptions for the variable options:
getter: variable-name
setter: variable-name | #f
type: variable-name
Interface Definitions
The default value for this option is the value of the read-only option of the
container that encloses the variable.
■ The seal option allows you to specify the dynamism of the functions for a
particular imported variable. The value open indicates that functions should
be imported as open generic function methods. The value sealed indicates
that they should be sealed generic function methods. The value inline
indicates that they should be bare methods and that calls to them should be
replaced with inline code.
The default value for this option is the value of the seal-functions option of
the container that encloses the variable.
■ The getter option allows you to explicitly rename the getter function for a
particular imported variable.
The default value for this option is the name created by the name-mapping
process.
■ The setter option allows you to specify information about the setter function
for a particular imported variable. Setter options can have the syntax
setter: #f
which indicates that no setter function should be created for the variable.
They can also have the syntax
setter: variable-name
where variable-name indicates the name for the setter function for the
variable.
For read-only variables, the default value of this option is #f. For others, the
default value is the name created by the name-mapping process.
■ The type option allows you to specify an explicit type mapping for an
imported variable. You provide a symbol that indicates the Apple Dylan
class that this variable’s type is type-mapped to; the getter function for the
imported variable returns an object of the indicated class, and the setter
function (if any) expects an object of the indicated class as its first argument.
The default value for this option is determined by the type-mapping
process, as described in Chapter 5, “Type Mapping.”
Interface Definitions
Function Options 2
The function options allow you to specify additional information about how to
import a specific C function. You can also use these options to modify callout
functions and callback macros. As with constant and variable, you can use
these options to override the options of an enclosing container.
Here are the syntax descriptions for the function options:
result-type: variable-name
Interface Definitions
specify a parameter of the C function and an Apple Dylan class for the
parameter to be mapped to.
This option can be used multiple times.
The default value for this option is determined by the type-mapping
process, as described in Chapter 5, “Type Mapping.”.
■ The input-argument option allows you to specify that a particular
parameter to an imported C function is used only as input. You can specify
the parameter using the parameter’s name as a string literal or a variable
name, or the number of the parameter. You can have multiple
input-argument options in a single function clause.
This option can be used multiple times.
This option is the default for all parameters. The next two options override
this option for particular parameters.
■ The output-argument option allows you to specify that a particular
parameter to an imported C function is a pointer to a location used only as
output. This option eliminates the indicated parameter from the imported
function’s parameter list; instead the value returned by the C function in this
location is added as an additional result returned by the imported function.
This option can be used multiple times.
■ The input-output-argument option allows you to specify that a particular
parameter to a C function is a pointer to a location used as input and as
output. This option keeps the indicated parameter in the imported
function’s parameter list, and also adds the return value as a function result.
This option can be used multiple times.
For output-argument and input-output-argument options, Apple Dylan
automatically removes one level of indirection for the indicated parameters, as
shown in Chapter 4, “Cross-Language Calls,” and Chapter 5, “Type Mapping.”
Interface Definitions
Callback Options 2
In addition to the function options described in the previous section, you can
also use the universal option in callback clauses.
Here is the syntax descriptions for this option:
Interface Definitions
3 Name Mapping
Contents
About Name Mapping 55
Using Name Mapping 56
Specifying Explicit Name Mapping 56
Using the Import Option of a Container Clause 56
Using the Rename Option of a Container Clause 57
Using the Arrow Option of a Clause 58
Using the Getter and Setter Options of a Variable Clause 60
Adding Prefixes to Imported Names 60
Using the Name-Mapping Functions 62
Name Mapping Reference 64
The MacApp-to-Dylan Function 64
The C-to-Dylan Function 65
The minimal-name-mapping Function 66
The minimal-name-mapping-with-structure-prefix Function 66
The identity-name-mapping Function 67
Contents 53
54 Contents
C H A P T E R 3
Name Mapping 3
This chapter discusses how Apple Dylan renames C entities during interface
importation, and how you can modify the renaming process.
Name Mapping
■ Prefix name mapping allows you to add a prefix to the names of entities
imported from a specified container. These prefixes are added before any
automatic name mapping occurs.
■ Explicit name mapping allows you complete control over the imported
name of any C entity. Explicit name mapping overrides all other forms of
name mapping.
The next section shows how you use interface definitions to specify the
different kinds of name mapping.
When you import C entities from a C container, you can use the import option
to specify explicit name mappings. If you’re already using an import option to
selectively import C entities, this method provides a convenient way to rename
C entities without having to add more options or clauses to your interface
definition.
Name Mapping
Here is an example:
define interface
#include “SampleHeader.h”,
import: { "sqrt" => square-root,
"expt" => exponent,
"divide",
"remainder" };
end interface;
This example imports four entities from a header file. Two of those entities are
explicitly renamed using the import option; the other two are not. Notice that C
entity names are literal strings; they are surrounded by quotes. The Apple
Dylan names are variable names; no quotes are required.
define interface
#include "SampleHeader.h",
import: all, // the default
rename: { "sqrt" => square-root,
"expt" => exponent };
end interface;
This example imports all of the C entities from the header file SampleHeader.h
and explicitly renames two of them.
You can also use the import and rename container options to rename members
of imported structures and unions. You may want to do this, for example,
when importing structure type definitions that contain internal structure of
anonymous type.
Name Mapping
struct doubleStruct {
int i;
struct {
int i;
int j;
} s;
};
In C, the two members named i are in different scopes; however, when you
import this structure type into Apple Dylan, both of these members enter the
same name space. Therefore, you must rename at least one of these members.
The following example shows how you can use the rename option to resolve
this naming conflict:
define interface
#include "SampleHeader.h",
import: { "doubleStruct" };
struct "doubleStruct",
rename: { "i" => "outer-i",
"s::i" => "inner-i",
"s::j" => "inner-j" };
end interface;
This example resolves the name conflict by renaming the i member in the outer
structure outer-i and the i member in the inner structure inner-i.
This example shows the use of the :: notation to distinguish member names by
the name of their containers. The notation "s::i" specifies the i member that is
inside the s member of the doubleStruct structure type. Similarly, the notation
"s::j" specifies the j member that is inside the s member of the doubleStruct
structure type.
You can also rename a specific C entity in its own clause, rather than in the
clause of its container.
Name Mapping
define interface
#include "SampleHeader.h”;
This interface definition uses a file clause to import all of the entities from the
file SampleHeader.h. It uses a separate function clause to explicitly rename an
imported function, and it uses a separate structure clause to explicitly rename
an imported structure type.
Since you can rename imported entities in more than one way, it is possible to
specify multiple name mappings for the same entity. For example:
define interface
#include "SampleHeader.h”,
rename: { "sqrt" => root };
In this example, the C entity sqrt is renamed root in the file clause and
square-root in the function clause. Apple Dylan resolves this conflict using the
general rule that more specific clauses override less specific clauses. As the
specified function clause is more specific than the file clause, the function is
imported under the name square-root.
Name Mapping
Variable clauses allow you to rename imported variables in two different ways.
As with any interface definition clause, you can use the arrow option, as shown
here:
define interface
#include "SampleHeader.h”;
You can explicitly rename these two functions, independently, using the getter
and setter options. For example:
define interface
#include "SampleHeader.h”;
variable "global",
getter: get-c-global,
setter: set-c-global;
end interface;
As described in the previous chapter, you can also specify the value #f for the
setter option, to prevent Apple Dylan from creating a setter function.
Name Mapping
define interface
#include "SampleHeader.h",
prefix: "imported-",
import: { "sqrt", "expt" };
end interface
This definition imports two C functions from the file SampleHeader.h. The prefix
option specifies a prefix to be added to the imported names: the sqrt function
becomes imported-sqrt, and the expt function becomes imported-expt.
The explicit name mappings discussed earlier in this chapter always override
other kinds of name mapping—including prefix name mapping. For example:
define interface
#include "SampleHeader.h",
prefix: "imported-",
import: { "sqrt", "expt" => exponent };
end interface
In this example, the sqrt function is imported as imported-sqrt, but the expt
function is imported as exponent. Prefixes do not affect entities with explicit
name mappings.
Prefixes are applied to the names of imported entities before the default name
mapping behavior is applied (or before any of the automatic name-mapping
functions described later in this chapter). For example, the default
name-mapping algorithm adds structure names and $ characters before
member names. Consider this definition:
define interface
#include "SampleHeader.h";
By default, the h and v members of the Point structure are imported as Point$h
and Point$v.
Name Mapping
If you specify a prefix for these imported names, the prefix is added before the
default name mapping occurs. For example:
define interface
#include "SampleHeader.h";
In this definition, Apple Dylan first adds the prefix to the slot names, yielding
slot-h and slot-y, and then performs the default name mapping, which yields
Point$slot-x and Point$slot-y.
define interface
#include "SampleHeader.h",
name-mapper: C-to-Dylan,
import: { "SampleFunction", "SampleStruct" };
end interface
Name Mapping
define interface
#include "SampleHeader.h",
name-mapper: identity-name-mapping;
struct "Point",
import: { "h", "v" };
end interface
define interface
#include "SampleHeader.h",
name-mapper: identity-name-mapping;
struct "Point",
name-mapper: C-to-Dylan,
import: { "h", "v" };
end interface
In this example, the Point structure is still imported as Point, but the members
are imported as Point$h and Point$v (and Point$h-setter and Point$v-setter).
Here is a complete list of the name-mapping functions provided by Apple
Dylan:
■ MacApp-to-Dylan, which maps MacApp’s naming conventions to standard
Apple Dylan naming conventions, and adds the prefix get- to the front of
imported structure and union member names.
■ C-to-Dylan,which maps standard C naming conventions to standard Apple
Dylan naming conventions, and also adds the prefix get- to the front of
imported structure and union member names
■ minimal-name-mapping, which unlike C-to-Dylan, does not insert hyphens or
affect member names.
Name Mapping
Other translations performed are based on the type of C entity being imported:
■ Types. The initial T, if any, is removed from the name and the result is
surrounded by angle brackets.
■ Constants. The initial k, if any, is removed from the name and an initial
dollar sign is added.
■ Members. The initial f, if any, is removed from the name and the prefix get-
is added.
Name Mapping
Name Mapping
Name Mapping
Name Mapping
4 Cross-Language Calls
Contents
About Cross-Language Calls 71
Types of Cross-Language Calls 71
Overview of a Cross-Language Call 72
Using Cross-Language Calls 74
Calling Imported Functions 75
Calling C Library Functions Using Function Pointers 77
Calling Apple Dylan Functions From C Libraries 79
Contents 69
70 Contents
C H A P T E R 4
Cross-Language Calls 4
Cross-Language Calls
access path to find the C library variable; therefore, to import a variable, you
must use an access path that provides access to variables.
■ Imported members are Apple Dylan functions that allow you to read and
write the value of members of C structures and unions. When you import a
structure type from a C header file, Apple Dylan creates a getter/setter pair
of functions that allow you to read and to write the values of the members of
instances of that type. See Chapter 5, “Type Mapping,” for examples of
importing and accessing structure members.
■ Callout functions allow you to call C functions using function pointers. A
callout function is an Apple Dylan function that takes a pointer to a C
function and values to pass to the C function. The callout function uses the
function pointer to call the C function for you, translating and passing the
arguments you specified. “Calling C Library Functions Using Function
Pointers” on page 77 gives examples that use callout functions and function
pointers to call C library functions.
■ Callback macros allow you to call Apple Dylan functions from C library
code. A callback macro is an Apple Dylan macro that you use to create a
callback function; a callback function is a special kind of C-compatible
Apple Dylan function. When you pass a callback function to a C library
function, that C function can use the callback function as a standard C
function pointer to call your Apple Dylan callback function. “Calling Apple
Dylan Functions From C Libraries” on page 79 shows how to use callback
macros and callback functions to call Apple Dylan from a C library.
In addition to these types of cross-language calls, you can also make low-level
(assembly-language) cross-language calls using the information in Chapter 7,
“Low-Level Facilities.”
Cross-Language Calls
kind of information you provide when importing C functions and how Apple
Dylan uses that information to perform cross-language calls.
When you import a C function, Apple Dylan creates an Apple Dylan function
that represents the C library function. The C header file specifies information
about the original C function; your interface definition specifies information
about how that C function should be imported.
Here are some examples of options available to you when importing a function:
■ You can rename the function. For example, you may want the imported
function name to follow Apple Dylan naming conventions.
■ You can specify the dynamism of the imported function. For example, you
can specify that the function be imported as an open generic function
method, a sealed generic function method, or a bare method implemented as
inline code.
■ You can adjust the parameter list and the result values to reflect differences
between the way C functions and Apple Dylan functions pass values. C
functions can have input parameters, output parameters, input-output
parameters, and a single function result, while Apple Dylan functions use
parameters for input and function results for output. If you specify how the
C function uses its parameters, Apple Dylan automatically makes the
appropriate modifications to the parameter list and the result values of the
corresponding Apple Dylan function.
■ You can explicitly specify type mappings for the parameters and function
result—that is, the Apple Dylan class associated with each of the C
function’s parameters and function result.
You do not have to specify all of this information each time you import a
function—Apple Dylan provides default behavior that handles many imported
functions without requiring any customization.
Once you’ve created the imported function, you call it as you would call any
Apple Dylan function. The imported function then performs the
cross-language call. In particular, the function:
1. Translates the argument values from Apple Dylan objects to corresponding
C values.
2. Adjusts the argument list. If the parameter list was modified when the
function was imported, the imported function makes the appropriate
adjustments to match the C function’s specification.
Cross-Language Calls
3. Calls the C function, using the appropriate access path and handling the
differences in runtime environments, calling sequences, and so on.
4. Translates the value returned by the C function as well as the values of any
output arguments.
5. Returns the translated values as the function result.
As you can see, much of the cross-language call process involves translating
values between Apple Dylan and C. This value translation process is discussed
fully in Chapter 5, “Type Mapping.”
The “Using Cross-Language Calls” sections, which follow, provide examples of
the different kinds of cross-language calls—how you set them up, how you
make the calls, and what Apple Dylan does for you.
Cross-Language Calls
Here is a simple interface definition you could use to import the function:
define interface
#include "SampleHeader.h",
import: { "Withdraw" };
end interface;
This interface definition includes a single file clause, which specifies a single C
entity to be imported—the C function named Withdraw.
Adding a function clause to this interface definition allows you more control
over how the function is imported. For example, consider the following
interface definition:
define interface
#include "SampleHeader.h",
import: { "Withdraw" };
Cross-Language Calls
This interface definition imports the function Withdraw, but it also specifies
additional information about the Apple Dylan version of the function. In
particular, it specifies
■ the imported function should be renamed take-money-out
■ the imported function should be a sealed method of a generic function
■ the amount parameter is an input parameter
■ the balance parameter is an input-output parameter
■ the overdrawn parameter is an output parameter
■ the overdrawn parameter should be mapped to the Apple Dylan class
<Boolean>
■ This function returns two function result values —an <integer> object
indicating the new balance and a <Boolean> object indicating whether the
account is overdrawn.
The imported take-money-out function provides access to the original C
function. You call the imported function as you would any Apple Dylan
function, for example:
Cross-Language Calls
calls this C library function, making the appropriate adjustments for the
differences in the language calling sequences, and so on.
When the C library function returns, Apple Dylan translates the values
returned in the output arguments from C values to corresponding Apple Dylan
objects, and returns those objects as the multiple return values of the imported
function.
Listing 4-1 Header file with function pointer type and functions
processor getTodaysProcessor(void);
define interface
#include "FunctionPointer.h",
name-mapper: C-To-Dylan;
Cross-Language Calls
This interface definition uses a file clause to import the two C entities from the
header file and also uses a callout clause to create a callout function for the
imported function-pointer type. The resulting Apple Dylan entities are:
■ A class named <processor>, whose instances are Apple Dylan objects that
store pointers to C functions.
■ A function named get-todays-processor, which calls the C function
getTodaysProcessor.
Cross-Language Calls
Here is an example:
The call-processor callout function translates its first argument from an Apple
Dylan object back into a C function pointer. Then it calls the C function pointed
to by that function pointer, passing that function the translated values of the
other two arguments. The C function returns a value of type long, which Apple
Dylan converts to an object of class <integer>. This object is returned as the
result of the make-processor-call callout function.
Cross-Language Calls
■ a function pointer type, named processor, that points to functions with two
long arguments and a long return value
This simple function takes a function pointer and two arguments of type long,
applies the indicated function to the long arguments, and returns the result.
You can import the C header shown in Listing 4-2 using this interface definition:
define interface
#include "Callbacks.h",
name-mapper: C-to-Dylan;
This interface definition imports the two C entities from the header file and
also creates a callback macro. Executing this interface definition creates three
Apple Dylan entities:
■ A class named <processor>, which is used to represent pointers to processor
functions.
■ A function named apply-processor, which applies a function to two integers
and returns a single integer.
■ A callback macro named make-Dylan-processor. This macro allows you to
create a callback function.
Cross-Language Calls
Here is how you use the callback macro to create a callback function.
Note
This release does not support this syntax. Instead, you
must write:
Cross-Language Calls
2. The imported function passes the function pointer and the long values to the
C function applyProcessor.
3. The C function applyProcessor applies the function pointed to by its first
argument to the values provided in its second and third arguments.
4. Since the function pointed to by that first argument is the callback function,
control is passed back to Apple Dylan, which converts the long values to
objects of type <integer>, and passes them to your callback function.
5. The callback function evaluates the expression (1 * 1) + (2 * 2) and
returns the resulting value of 5.
6. Apple Dylan converts the integer object 5 into a C value of type long and
passes it back to the C function applyProcessor.
7. The C function applyProcessor finishes executing and returns the C value 5
to Apple Dylan, which converts it to an <integer> object and returns that
object as the result of the apply-processor function.
8. The result is bound to the variable name result.
Cross-Language Calls
The next chapter, “Type Mapping,” details the mechanism of passing values
between Apple Dylan and C-compatible library code during cross-language
calls.
Cross-Language Calls
5 Type Mapping
Contents
About Type Mapping 87
About Importing Type Definitions 87
About Type Mappings 89
Implicit Type Mapping 90
By-Value Types 91
Untyped-Pointer Types 92
Statically-Typed-Pointer Types 93
Explicit Type Mappings 93
About Value Translation 94
Using Type Mapping 95
Importing Structures 95
Arrays as Structure Members 97
Importing Pointer-To-Structure Types 98
Importing Pointer-To-Function Types 99
Using Explicit Type Mapping 100
Type Mapping Strings 100
Importing and Exporting Values 101
Type Mapping Reference 105
Pointer Classes 105
The <machine-pointer> Class 105
The <statically-typed-pointer> Class 106
The <C-string> Class 108
The <Pascal-string> Class 110
Structure-Related Functions 111
The structure-size Function 111
The destroy Open Generic Function 112
Contents 85
86 Contents
C H A P T E R 5
Type Mapping 5
Type Mapping
struct Position {
short x;
short y;
} Position;
C's unions are identical to structures, except for the algorithm that computes
the slot offsets. Apple Dylan supports unions; therefore, a pointer to a union is
a statically typed pointer. You are responsible to know which variant of the
union is used and only call the corresponding accessors (as in C).
See “Importing Structures” on page 95 for an example of importing a C
structure type into Apple Dylan.
Type Mapping
Type Mapping
The next few sections introduce the default (implicit) type-mapping behavior;
explicit type mapping is introduced on page 93.
Type Mapping
Note
You can specify an explicit type mapping in any of these
situations. (See “Explicit Type Mappings” on page 93.)
However, if no explicit type mapping is specified, and no
type mapping exists from a previous interface definition,
then Apple Dylan automatically provides an implicit type
mapping. ◆
By-Value Types 5
Type Mapping
Untyped-Pointer Types 5
■ long*
■ char*
Pointers to untyped pointers are also considered untyped. For example, these
types are also untyped-pointer types:
■ void**
■ long***
■ char****
Type Mapping
Statically-Typed-Pointer Types 5
Note
Handles to specific records are also statically typed
pointers; the slot getters and setters specialized to a record
handle do the extra indirection through the handle. ◆
Unlike C, Apple Dylan type checking requires that a function pointer argument
be of the same class as declared, rather than any function pointer with
compatible argument and result types.
Explicit type mapping is the mechanism that allows you to override and
customize the default type-mapping behavior provided by Apple Dylan. You
Type Mapping
■ A by-value type can map to any class. However, this class must have
import-value, export-value, and export-temporary-value methods if the
low-level Dylan value decoded from the C representation and high-level
Dylan value that your program handles are not identical. See the next
section and “Importing and Exporting Values” on page 101 for more
information.
Type Mapping
round-off error if the C number has different precision from the Apple Dylan
number.)
■ Structure and union types. The low-level value is a statically typed pointer
that points to the structure or union. (Where C allocates a temporary copy of
the structure or union, Dylan does the same and the low-level Dylan value is
a pointer to that copy).
■ Pointer types. The low-level value is a statically-typed pointer or an
untyped pointer.
Importing and exporting are the processes that translate between the low-level
value and the Apple Dylan value. These processes are controlled by the Apple
Dylan class.
You can extend the import and export steps by adding methods to the Apple
Dylan class. You might have to do this when creating an explicit by-value type
mapping, for example, in order to correct for discrepancies between the desired
Apple Dylan value and low-level value produced by decoding. See “Importing
and Exporting Values” on page 101 for more information.
If the low-level-value is a pointer and the class is a statically-typed-pointer
class, then the low-level-value is an instance of the class; otherwise, it is an
instance of <machine-pointer>. The decoding and encoding steps of value
translation are aware of the Apple Dylan classes for typed pointers.
Importing Structures 5
Apple Dylan imports C structure and union types as Apple Dylan
statically-typed pointer classes. For example, consider this structure type
defined in the header file Position.h:
struct Position{
short v;
short h;
};
Type Mapping
You can import this structure type using the following interface definition:
define interface
#include "Position.h",
import: { "Position" };
end interface;
my-c-point.Position$v := 5;
my-c-point.Position$h := 10;
Type Mapping
my-c-point.Position$v
my-c-point.Position$h
destroy(my-c-point);
The Macintosh Toolbox provides functions that deallocate memory for certain
types of Toolbox structures. When applicable, you should import those
functions and use them, rather than the destroy function, to deallocate memory.
The reference section at the end of this chapter contains reference descriptions
for the structure functions make, destroy, and structure-size. Chapter 7,
“Low-Level Facilities,” discusses additional structure functions.
When you import a structure (or union) member whose type is an array type,
the corresponding getter/setter functions take an extra argument that specifies
an array index. For example, consider this C structure type:
struct sample {
int a [10];
int b [10];
} sample;
Type Mapping
Importing the C sample structure type also creates getter/setter function pairs
for the members sample$a and sample$b. These functions require an extra
argument that specifies the array index. Therefore, these expressions are
invalid:
You can access the elements of the member arrays using this code:
If the array is multi-dimensional, the getter and setter take as many extra
arguments as the array has dimensions. Apple Dylan accesses only one array
element at a time. Array bounds are not checked because C does not check
them and many interfaces declare them incorrectly.
However, if the slot's type is mapped to a statically typed pointer class, Apple
Dylan does not require the extra arguments. For example, Types.h defines Str31
as unsigned char[32]. A structure slot of type unsigned char[32] is treated as
an array of unsigned 8-bit integers; however, because the type Str31 is mapped
to <Pascal-string>, the array in the slot is treated as a string and the getter and
setter do not take an extra argument.
typedef struct {
short x;
short y;
} Position;
Type Mapping
If you import the Position structure type, the Apple Dylan class <Position>
results. This class is a subclass of <statically-typed-pointer>.
Similarly, if you import the PosPtr type, the Apple Dylan class <PosPtr> results.
This class is a subclass of <Position>.
If you import the function DrawLineBetween, Apple Dylan creates implicit type
mappings for the two parameters:
■ The first parameter, start, is of type PosPtr. Apple Dylan maps the C type of
this parameter to the Apple Dylan <PosPtr> class.
■ The first parameter, end, is of type Position*. By default, Apple Dylan maps
this C type to the same Apple Dylan class that Position maps to—in this
case, the Apple Dylan class <Position>.
As a result, the C function expects two pointers to Position structures. The
Apple Dylan function expects an object of class <PosPtr> and an object of class
<Position>.
Type Mapping
Type Mapping
Both of these types are pointers to char types, which are implicitly type
mapped to the Apple Dylan class <machine-pointer>.
To access the power of the Apple Dylan <string> class for imported strings,
you can specify explicit type mappings when importing string types. For
example:
define interface
#include "StringTypes.h",
type: { "StringPtr" => <C-String>,
"Str255" => <Pascal-String> };
end interface
This type mapping allows you to manipulate imported strings as if they were
Apple Dylan strings, and provides Apple Dylan with the information
necessary to pass these types of strings between languages during
cross-language function calls.
(The string types defined in Types.h are imported for you already, as described
on page 92.)
Apple Dylan also allows you to pass a native Apple Dylan string to any
imported function that expects a <C-String> or a <Pascal-String> argument.
When you do, Apple Dylan allocates storage and copies the elements of the
native string into the appropriate format automatically. (The next section
describes how Apple Dylan implements this functionality.)
Finally, you can convert an imported string to a native Apple Dylan string
using the as function:
For more information, see the reference descriptions for the <C-String> and
<Pascal-String> classes, starting on page 110.
Type Mapping
There are times when you might want to specify an explicit type mapping that
presents importing and exporting issues that Apple Dylan does not know how
to handle. Since the by-pointer types are all imported and exported in the same
way, these issues typically arise when you are defining a new by-value type
mapping.
Note
As a simple example, let’s examine how to create a
Boolean by-value type mapping. This is example for
illustrative purposes only. Apple Dylan already provides
the Boolean type mapping behavior shown here.) ◆
In C, a value of 0 represents false, while the value 1 (or any other value)
represents true. The file Types.h contains the definition
By the default type-mapping rules, this C type maps to the Apple Dylan class
<integer>. Suppose you want to create a new by-value type mapping:
define interface
#include "Types.h",
type: { "Boolean" => <Boolean> };
end interface
This interface definition type maps the C type Boolean to the built-in Apple
Dylan class <Boolean>. As a result, any C function that expects a Boolean
argument is imported as an Apple Dylan function that expects a <Boolean>
argument.
When you call such an imported function, you provide an Apple Dylan
<Boolean> value—#t or #f. Unfortunately, the C function expects
an unsigned
short. The value needs to undergo an appropriate translation.
Apple Dylan provides three generic functions used when importing and
exporting values:
■ The import-value function is called to translate a decoded low-level value to
an Apple Dylan value.
■ The export-value and export-temporary-value functions are called to
translate an Apple Dylan value to a low-level value ready to be encoded and
passed to C:
Type Mapping
Type Mapping
The only difference between this method and the export-value method is that
Apple Dylan passes a function object to this method, which is expected to pass
the low-level value to that function rather than returning it as the method
result.
The reference sections for these three generic functions begin on page 114.
Chapter 7, “Low-Level Facilities,” contains additional information you may
find useful when specializing these functions.
In the previous section, you saw that Apple Dylan allows you to pass native
strings (of class <string>) to imported functions that expect imported strings.
This mechanism is implemented using export methods.
For example, Apple Dylan defines these two export-value methods:
The first of these methods accepts a <C-string> object as the high-level value
and uses it as the low-level value.
The second method accepts any <string> object as the high-level value. This
method allocates C memory for a C string, copies the elements of the native
string, and returns a statically-typed pointer to the C string as the low-level
value.
Similar methods exist for the export-temporary-value generic function.
The class <Pascal-String> has an analogous set of exporting methods.
Type Mapping
Pointer Classes 5
This section describes the Apple Dylan classes that represent machine pointers,
and the Apple Dylan superclass for statically-typed-pointer classes. Two
built-in statically-defined-pointer classes—the <C-string> class and the
<Pascal-string> class—are also described here.
DESCRIPTION
Type Mapping
SEE ALSO
DESCRIPTION
Type Mapping
Two pointers of mixed types (machine pointer and statically typed pointer) can
never be == or =.
The < operation is applicable to statically-typed pointers. It compares
addresses but not classes. The arguments can be of mixed types (for example, a
statically typed pointer can be compared to a machine pointer).
INITIALIZATION
Type Mapping
SEE ALSO
DESCRIPTION
Objects of class <C-string> are strings; you can manipulate them as you would
manipulate any Apple Dylan <string> object.
However, Apple Dylan stores C-string objects differently from native string
objects. C-string objects are stored as statically-typed pointers to C-compatible
strings.
Therefore, you can manipulate these objects as strings within Apple Dylan, and
you can pass them as strings to C library functions.
Type Mapping
INITIALIZATION
The initialize method for the <C-string> class allows you to allocate
C-compatible strings.
SEE ALSO
For a discussion of the C-compatible string classes, see “Type Mapping Strings”
on page 100.
Type Mapping
DESCRIPTION
Objects of class <Pascal-string> are strings; you can manipulate them as you
would manipulate any Apple Dylan <string> object.
However, Apple Dylan stores Pascal-string objects differently from native
string objects. Pascal-string objects are stored as statically-typed pointers to
C-compatible strings (with an initial length byte, rather than a null
termination).
Therefore, you can manipulate these objects as strings within Apple Dylan, and
you can pass them as strings to imported functions.
INITIALIZATION
The initialize method for the <Pascal-string> class allows you to allocate
C-compatible strings with initial length bytes.
Type Mapping
size argument, the maximum size for the string as the maximum-size argument,
and the initial value to fill the elements of the string as the fill argument.
After the string is initialized, you may use the standard Dylan function
size-setter to reset its size. However, you may not increase the size of the
string above the maximum size indicated in the initialization.
SEE ALSO
For a discussion of the C-compatible string classes, see “Type Mapping Strings”
on page 100.
Structure-Related Functions 5
This section discusses the functions provided by Apple Dylan that allow you to
manipulate C-compatible structures. The functions described here allow you to
■ determine the size of a C-compatible structure
■ free the memory allocated fora C-compatible structure
To allocate a C-compatible structure in the heap, you use the standard Dylan
function make, as described in the <statically-typed-pointer> reference section
on page 106.
To allocate a C-compatible structure on the stack, you use the Apple Dylan
macro with-stack-structure, which is described in Chapter 7, “Low-Level
Facilities,” or the macro with-stack, defined in the Apple Dylan Framework.
You can use the structure-size function to determine the size in bytes required
for instances of an imported C structure or union type.
Type Mapping
DESCRIPTION
struct CPoint {
long h;
long v;
} CPoint;
Apple Dylan creates a statically-typed pointer class named <CPoint>. You can
call the structure-size function on this class:
structure-size(<CPoint>);
The result is 8, indicating the number of bytes used by structures of type CPoint
(two C long values of 4 bytes each).
You use the destroy generic function to deallocate memory for C structures or
unions you created with the make function.
destroy( instance )
DESCRIPTION
Type Mapping
destroy(my-structure);
As a result, the allocated structure is freed, and the my-structure object contains
a null pointer.
SEE ALSO
For information about creating C structures and unions, see the description of
the <statically-typed-pointer> class on page 106.
For an example of creating a C structure from Apple Dylan, see “Importing
Structures” on page 95.
The functions described in this section are called by Apple Dylan during value
translation—that is, when passing values between C and Apple Dylan during
cross-language calls.
You can specialize these functions to override the default type mapping and
value translation behavior.
Type Mapping
Apple Dylan calls the import-value function when translating C values into
Apple Dylan.
DESCRIPTION
When a C value is passed into Apple Dylan during a cross-language call (or a
variable or member access), Apple Dylan determines
■ the target Apple Dylan class, which is specified by a type mapping
■ the low-level value, which is the result of decoding the C value
Apple Dylan passes these values to the import-value function, which is
responsible for translating the low-level value to the appropriate class.
When you specify an explicit type mapping, the Apple Dylan class you specify
may not match the class of the low-level values produced by Apple Dylan
during decoding.
For example, the section “Importing and Exporting Values” on page 101
includes an explicit type mapping that maps a C integer type to the Apple
Dylan class <Boolean>. Since C integer types decode to Apple Dylan integer
objects, additional translation is required for this type mapping. You perform
this translation by adding an import-value method specialized for the class
<Boolean>:
When a C value that is type mapped to the class <Boolean> is passed into Apple
Dylan, Apple Dylan decodes the C value, and calls the import-value function,
Type Mapping
with the class <Boolean> as the first argument and the decoded value as the
second argument.
By providing an import-value method specialized to the class <Boolean>, as is
the one above, you can perform the additional translation necessary to convert
the low-level value provided by Apple Dylan into an object of the class
<Boolean>.
Apple Dylan does not require that the value returned by an import-value
method be an instance of the specified target class. However, it is
recommended that your export methods be able to handle whatever classes of
objects your import method can produce.
SEE ALSO
For information on how Apple Dylan encodes and decodes values, see “About
Value Translation” on page 94.
For an example of specializing this function, see “Importing and Exporting
Values” on page 101.
Apple Dylan calls the export-value function when translating Apple Dylan
objects to C values.
DESCRIPTION
Type Mapping
SEE ALSO
For information on how Apple Dylan encodes and decodes values, see “About
Value Translation” on page 94.
For an example of specializing this function, see “Importing and Exporting
Values” on page 101.
Type Mapping
DESCRIPTION
As with the function export-value, you can specialize this function for a
particular class to perform any translation necessary to prepare objects of that
class to be encoded.
When you specialize this function, however, you typically
1. allocate temporary storage
2. calculate the low-level value
3. pass that value to the function provided
4. deallocate any allocated storage
5. return all values returned by the function provided
SEE ALSO
Type Mapping
6 Access Paths
Contents
About Access Paths 121
Using Access Paths 122
Using File Options to Specify Information About Access Paths 122
Using the Inline Machine Code Access Path 124
Using The Code Fragment Manager Path 126
Creating a CFM Shared Library 126
Using CFM Shared Libraries 128
Using The Apple Shared Library Manager Access Path 129
Creating an ASLM Shared Library 131
Using ASLM Shared Libraries 132
Using The External Module Access Path 133
Creating a Custom Application Nub 134
Using Statically Linked External Modules 135
Using The Direct Pointer Access Path 135
Preparing a Code Resource 136
Loading and Unloading a Code Resource 138
Calling Functions Imported from a Code Resource 140
Contents 119
120 Contents
C H A P T E R 6
Access Paths 6
This chapter discusses the various access paths that Apple Dylan can use to
locate C entities during a cross-language call. A programming example is
included for each type of access path.
Access Paths
define interface
#include "SampleHeader.h",
language: C;
end interface;
define interface
#include "SampleHeader.exp",
language: ASLM;
end interface;
define interface
#include "SampleHeader.crypticsuffix",
language: ASLM;
end interface;
Access Paths
The external-module file option allows you to specify that Apple Dylan should
use the external module access path to locate imported functions during
runtime. This option requires that you to specify the name of the external
module. For example:
define interface
#include "SampleHeader.h",
external-module: my-external-module;
end interface;
define interface
#include "SampleHeader.h",
CFM-library: "my_cfm_library",
CFM-library-version: 3,
CFM-library-oldest-version: 2;
end interface;
Access Paths
define interface
#include "SampleHeader.h",
CFM-library: my_cfm_library;
end interface;
If you don’t specify either of these two options, the default behavior causes the
newest version of the library to be used. If you specify the CFM-library-version
option, but not the CFM-library-oldest-version option, the latter defaults to the
former, thus requesting a specific version of a library.
Note
Actually, the function Random is defined as
extern pascal short Random(void)
ONEWORDINLINE(0xA861);
The ONEWORDINLINE macro is defined in the file
ConditionalMacros.h; if the CFMSystemCalls preprocessor
macro is not set, the ONEWORDINLINE macro is defined as
#define ONEWORDINLINE(trapNum) = trapNum
which is a macro that is expanded into an equals sign
followed by the argument to the macro. ◆
When you import the Random function, using this interface definition
Access Paths
define interface
#include "QuickDraw.h",
import: { "Random" };
end interface;
Apple Dylan parses the QuickDraw.h header file and notices that the machine
code implementation of the Random function is specified. Therefore, when you
call the Random function from your Apple Dylan program, for example:
Apple Dylan simply executes the machine code specified in the header file. In
the case of Macintosh Toolbox functions, such as Random, this machine code is a
trap instruction and the Macintosh trap dispatcher performs the necessary
linking dynamically.
When the Macintosh Toolbox function returns, Apple Dylan performs type
conversion on the function result. The function definition in QuickDraw.h
specified that the return value is of type short, so Apple Dylan converts the
value to an object of class <integer>. In the example above, this object is bound
to the name *new-number*.
When you call imported Toolbox functions that take arguments, Apple Dylan
performs type conversion on the Apple Dylan objects that you specify as
arguments, sets up the arguments on the stack, and then executes the specified
trap instruction.
For the above example to work on both 68K-based and PowerPC-based
Macintosh computers, you need to use the inline machine code access path on
the 68K and the Code Fragment Manager access path on the PowerPC. You do
this by adding the file option
CFM-Library: "InterfaceLib"
which will be ignored on the 68K-based machine because the Random function
has inline machine code, which supersedes this option.
Access Paths
Before you can use the CFM access path to call your own C-compatible
functions from Apple Dylan, you must package your functions as a CFM
shared library.
You also need to create a C header file to declare the C entities you want to
export from your shared library.
Access Paths
For CFM shared libraries, you specify information about the shared library and
its exported functions in your source code file and in a CFM resource.
In your source code file, you specify which functions are exported by the CFM
shared library using a special preprocessor directive. For example, here is the
definition of the function exported by the sample CFM shared library included
with Apple Dylan:
#pragma lib_export on
long scaled_sine(long angle, long amplitude) {
float argument = angle * 3.1415926535 / 180.0;
float wave = sin(argument) * (float)amplitude;
return((long)wave);
}
The first line in this example uses the #pragma preprocessor directive to specify
that the following function should be exported by the shared library.
Once you have the required elements (the CFM system extension, the C header
files, and the C-compatible source code with the proper CFM preprocessor
directives), you use a development environment such as MPW to compile and
package your source code as a CFM shared library system extension.
If you are using MPW, you need to create a rez file that controls the creation of
the system extension file that contains your shared library. Here is the sample
resource file for the CFM shared library example included with Apple Dylan:
#include "systypes.r"
#include "types.r"
#include "CodeFragmentTypes.r"
Access Paths
This rez file specifies the information needed by the resource compiler to create
a code fragment resource containing the compiled sample code. The Code
Fragment Manger uses this resource to load and locate the compiled functions
at runtime.
When you create your own CFM shared library, you must be sure that the CFM
system extension and your CFM shared library are installed on any machine
that runs your Apple Dylan application.
Before you can call CFM shared library functions from your Apple Dylan
program, you must import those functions, and any other necessary C entities,
using an interface definition. Since CFM shared libraries do not use a special
header file, as ASLM shared libraries do, you import CFM shared library
entities directly from a C header file.
When importing a CFM shared library, however, you must specify the name of
the code fragment that contains the functions you want to import. For example,
you could use this interface definition to import C entities from the CFM
example included with Apple Dylan:
define interface
#include "scaled_sine.h",
CFM-library: "dyln.scaled_sine_example";
end interface;
This interface definition imports all the exported entities defined in the
C header file scaled_sine.h. It also specifies which code fragment Apple Dylan
should use to locate the functions during runtime.
Access Paths
You can use any of the standard interface definition clauses and options to
provide more specific control of the importation process. For example:
define interface
#include "scaled_sine.h",
CFM-library: "dyln.scaled_sine_example",
rename: { "scaled_sine" => imported-scaled-sine };
end interface;
As with functions imported from a CFM shared library, you use the standard
Apple Dylan function call syntax to call functions imported from a CFM shared
library. Here is an example:
Access Paths
■ The ASLM shared library that contains the compiled functions you want to
call. This shared library will also be in the form of a system extension, which
must be installed on your Apple Dylan runtime machine.
■ The ASLM header file that contains information about the shared library,
such as its name and version, and lists the functions exported by the shared
library—that is, the functions that you can import into your Apple Dylan
program. By convention, ASLM header files have filenames that end with
the .exp suffix.
■ The C header files that declare the C entities available in the shared library.
These files use standard C header file syntax to declare the entities exported.
In your interface definitions, you instruct Apple Dylan how to parse these
files to create Apple Dylan objects that correspond to the shared library
entities.
You use the ASLM header file to import information into your Apple Dylan
program. For example, here is the sample ASLM header file included with the
Apple Dylan sample code:
#include "scaled_sine.h"
Library
{
id = "dyln:dyln$scaled-sine-example,1.0";
version = 1.0d1;
};
FunctionSet scaled_sine
{
id = "dyln:dyln$scaled-sine-example,1.0";
version = 1.0d1;
exports = extern scaled_sine;
};
This ASLM header file includes the C header file scaled_sine.h, which contains
the C declaration of the sample scaled_sine function:
Access Paths
The ASLM header file also includes a Library definition, which specifies the
name and version of the ASLM library, and a FunctionSet definition, which
specifies the function exported from the library.
(You cannot import ASLM classes into Apple Dylan; only function sets can be
imported. In addition, only functions declared extern in a function set can be
imported.)
If you want to use functions that have already been packaged into an ASLM
shared library, you must have the library’s ASLM header file, so that you can
import the necessary entities into your Apple Dylan program.
If you want to use the ASLM access path to call C-compatible functions that
you have written (or C-compatible functions for which you have the source
code), you create your own ASLM header file and package your C-compatible
functions into an ASLM shared library, as described in the next section.
Before you can use the ASLM access path to call your own C-compatible
functions from Apple Dylan, you must package your functions as an ASLM
shared library.
You also need to create an ASLM header file that contains information about
your shared library, as well as C header files that use standard C syntax to
declare the C entities you want to export from your shared library.
Once you have the required elements (the ASLM system extension, the ASLM
header file, the C header files, and the C-compatible source code), you use a
development environment such as MPW to compile and package your source
code as an ASLM shared library system extension.
If you are using MPW, you will also need to create a rez file that controls the
creation of the system extension file that contains your shared library. Here is
the sample resource file for the ASLM shared library example included with
Apple Dylan:
Access Paths
#include "VersionResource.r"
INCLUDE "scaled_sine.RSRC";
When you create your own ASLM shared library, you must be sure that the
ASLM system extension and your ASLM shared library are installed on any
machine that runs your Apple Dylan application.
Before you can call ASLM shared library functions from your Apple Dylan
program, you must import those functions using an interface definition. You
must also import any constants and types needed to call those functions.
In general, you
1. import the constants and types (but not the functions) from the C header file
2. import the functions from the ASLM header file (the .exp file)
The ASLM example included with Apple Dylan imports one function. No
imported C types or constants are necessary, so the example only needs one
interface definition:
define interface
#include "scaled_sine.exp";
end interface;
This interface definition imports all the entities defined in the C header files
included in the scaled-sine.exp header file. In particular, it imports all of the
functions explicitly exported by that file.
You can use any of the standard interface definition clauses and options to
provide more specific control of the importation process. For example:
define interface
#include "scaled_sine.exp",
rename: { "scaled_sine" => imported-scaled-sine };
end interface;
Access Paths
When you call an imported ASLM function, you simply use the standard Apple
Dylan function call syntax, as in this example:
Apple Dylan converts the integer objects named angle and amplitude to
C values of type long, calls the imported function, and converts the return
value from a C value of type long into an Apple Dylan integer object.
From the point of view of your program, the imported function is
indistinguishable from a standard Apple Dylan function.
Access Paths
interface definitions, described in the next section. The external module is used
by Apple Dylan as a linking mechanism. It is not a real Dylan module; you
don’t use it directly to access module variables, and so on.
The next section also explains how you use a header file, a compiled code file,
Apple Dylan, and MPW to create an external module and link it into your own
custom version of the Application Nub.
This interface definition specifies that Apple Dylan import all of the C
entities declared in the scaled-sine.h file into an external module named
scaled-sine-external-module. (If you have already connected to the
Application Nub, this interface definition results in an error because the
standard Application Nub does not contain an external module by that
name.)
3. Execute the special compile-time function write-external-modules. This
function collects information about all the external modules that you have
created and writes a description of them to an MPW file. Here is an example:
write-external-modules("external-modules.a");
Access Paths
creates the external-modules.a file in the project folder. You need to move
this file to a folder where it can be found by the MPW Linker.
4. Launch MPW (or a compatible development environment). If you are using
MPW, you need to use version 3.3 or newer.
5. Use the MPW linker to link your external-modules.a file, your compiled
C-compatible code (your .o file), and the RunDynamoLib.o file. into a custom
Application Nub. You can use the sample build file included with Apple
Dylan (as part of the Static Linking example), which builds a program
named "My Application Nub". You might have to redefine some variables in
this build file to reflect your file names and file hierarchy.
6. In the Apple Dylan development environment, connect to your custom
Application Nub. You can now update your project and access the imported
C entities from your Apple Dylan program.
Once you’ve gone to the trouble to create the custom Application Nub, you can
call the imported functions exactly as you would any Apple Dylan function.
As with functions imported from an ASLM shared library or a CFM shared
library, you use the standard Apple Dylan function call syntax to call functions
imported from an external module. As with the ASLM and CFM access paths,
the imported function is indistinguishable from a standard Apple Dylan
function.
Access Paths
Note
The code resource approach introduced here and described
in the next three sections is specific to 68K-based
Macintosh computers; it would require modification to
work on a PowerPC-based Macintosh. ◆
To prepare a code resource that contains functions suitable for calling from
Apple Dylan using the Direct Pointer access path, you add a transfer vector to
the beginning of the compiled C-compatible code and link the result into a
code resource.
As an example, consider a sample C program that contains three functions:
Each of these functions requires one argument of type long and returns a
function result of type long. The result of compiling this source file is a
compiled code (.o) file. To make this compiled code suitable for calling from
Apple Dylan using the Direct Pointer access path, you need to compile a
Access Paths
transfer vector suitable for the compiled code. A transfer vector is a series of
assembly language instructions (of equal length) that transfer control to each of
the exported functions.
A sample transfer vector, written in assembly language and suitable for the C
program above, is shown in the following code listing:
case on
macro
xfer &to
import &to:code
bra.w &to
endm
This transfer vector contains three elements, each of length 4. The first transfers
control to the modify function, the second transfers control to the mogrify
function, and the third transfers control to the morph function.
To create a suitable code resource, you compile the transfer vector and link it to
the beginning of the compiled C code, storing the result in a code resource. The
linker links the transfer vector to the compiled C code by name, so you must be
sure that the function names you specify in your transfer vector match the
function names in the compiled C code.
In this example, your code resource contains your transfer vector and the three
compiled functions. The transfer vector, located at the beginning of the code
resource, specifies instructions at locations 0, 4, and 8 that transfer control to
each of the three functions, respectively.
See the Code Resource example included with Apple Dylan for examples of the
MPW commands you can use to accomplish these compilations, linking, and
code resource creation.
Access Paths
define interface
#include "Resources.h",
import: { "OpenResFile", "GetResource",
"HomeResFile", "CloseResFile" };
function "OpenResFile",
argument-type: {"fileName" => <Pascal-string>};
#include "Memory.h",
import: { "MoveHHi", "HLock",
"RecoverHandle", "HUnlock" };
#include "OSUtils.h",
import: { "FlushCodeCache" };
end interface;
You might also want to define a constant that represents the resource ID of
your code resource, which you would have chosen during the MPW linking
process. Here is an example:
You will also need a variable to use as a pointer to the code resource when it is
loaded in memory. Apple Dylan provides the <machine-pointer> class for this
purpose; you can use machine-pointer objects to store actual memory
addresses, called machine pointers. Apple Dylan also provides the constant
Access Paths
Once you have imported the appropriate Macintosh Toolbox functions and
created your resource ID constant and your code resource pointer variable, you
can use this Apple Dylan function to load your code resource and initialize
your pointer to it:
MoveHHi(code-resource);
HLock(code-resource);
FlushCodeCache();
*code-resource* := pointer-at(code-resource); // deref handle
end method;
This function opens your resource file, loads your code resource, and stores a
machine pointer to your code resource in your *code-resource* variable.
Here is the corresponding code for unloading the resource and resetting your
machine pointer variable:
Access Paths
HUnlock(handle);
CloseResFile(file);
end method;
This function unlocks your code resource, closes the code resource file, and
resets the value of the module variable *code-resource*.
Listing 6-5 Header file for functions imported from a code resource
enum { kmodify = 0;
kmorph = 4;
kmogrify = 8 };
define interface
#include "SampleHeader.h";
Access Paths
if (*code-resource* = $null-machine-pointer)
load-code-resource();
end if;
call-modify(ptr-to-modify, input);
end method;
This function ensures that the *code-resource* global variable has been
initialized; if not, it calls the load-code-resource function (defined in the
previous section) to load the code resource and initialize *code-resource*.
Then, the function creates a local variable, ptr-to-modify, which points directly
to the transfer vector that transfers control to the modify function in the code
resource.
Finally, this function uses the call-modify callout function to apply the
imported modify function to the input argument.
Access Paths
7 Low-Level Facilities
Contents
About Low-Level Facilities 145
Using Low-Level Facilities 145
Using Machine Pointers Directly 146
Allocating Stack Storage 148
Making Low-Level Function Calls 150
Calling Dylan Methods From Other Languages 151
Using Preemption and Event Checking 151
Low-Level Facilities Reference 152
Reading and Writing Data Using Machine Pointers 152
Reading and Writing A Single Byte 153
The signed-byte-at Method 153
The signed-byte-at-setter Method 154
The unsigned-byte-at Method 155
The unsigned-byte-at-setter Method 155
The character-at Method 156
The character-at-setter Method 157
Reading and Writing Pairs of Bytes 158
The signed-short-at Method 158
The signed-short-at-setter Method 158
The unsigned-short-at Method 159
The unsigned-short-at-setter Method 160
The unicode-character-at Method 161
The unicode-character-at-setter Method 161
Reading and Writing Long Words 162
The signed-long-at Method 162
The signed-long-at-setter Method 163
The unsigned-long-at Method 164
Contents 143
144 Contents
C H A P T E R 7
Low-Level Facilities 7
In this chapter, you’ll see some of the low-level facilities provided by the Apple
Dylan language extensions. You’ll learn how to use the low-level facilities for
direct control of machine memory, cross-language calls, preemption, and event
checking.
Low-Level Facilities
unicode-character-at 2 <character>
signed-byte-at 1 <integer>
unsigned-byte-at 1 <integer>
signed-short-at 2 <integer>
unsigned-short-at 2 <integer>
signed-long-at 4 <integer>
unsigned-long-at 4 <integer>
pointer-at 4 <machine-pointer>
OStype-name-at 4 <byte-string>
Low-Level Facilities
named raw-pointer, you can use the following code to determine the character
stored at the address indicated by that machine pointer:
define interface
#include “Memory.h”,
import: { “NewPtr” };
end interface;
Low-Level Facilities
You can then use these machine pointers to control memory directly:
Notice the use of the extended syntax for the assignment operation:
The reference section “Reading and Writing Data Using Machine Pointers,”
beginning on page 152, contains a detailed description of each of the functions
for direct memory manipulation.
Low-Level Facilities
Note
The Application Framework provides the with-struct
macro, a somewhat higher-level interface for allocating
temporary memory. If you are using the Application
Framework, it is recommended that you use the
with-struct macro, rather than the macros described in
this section. ◆
The following example shows how you might use the with-stack-block macro
to implement the export-temporary-value method for <Pascal-string> objects.
(This example is for illustrative purposes only; Apple Dylan already defines
this method for you. See Chapter 5, “Type Mapping,” for more discussion
concerning the export-temporary-value function.)
with-stack-block ( string(<Pascal-string>, n + 1 ),
begin
let temp = as (<machine-pointer>, string);
unsigned-byte-at(temp) := n;
for (c in high-level-value,
p = (temp + 1) then (p + 1))
character-at(p) := c;
end for;
function(string);
end);
end method;
Low-Level Facilities
In this example, notice that the call to the with-stack-block macro takes two
arguments. The first argument is
string(<Pascal-string>, n + 1)
Low-Level Facilities
Low-Level Facilities
so, calls the built-in break function. You can provide your own event-check
function to override this default behavior.
The methods in this section allow you to use machine pointers to access
memory locations directly. These methods come in pairs: one method in each
pair allows you to read information at a particular address by copying that
information into an Apple Dylan object; the other method in each pair allows
you to copy information from an Apple Dylan object directly into memory.
The functions differ by how many bytes of information they read or write, and
how they interpret the information in those bytes.
Three pairs of functions provide access to single bytes in memory:
■ The signed-byte-at and signed-byte-at-setter methods interpret the byte
as a signed integer value.
■ The unsigned-byte-at and unsigned-byte-at-setter methods interpret the
byte as an unsigned integer value.
■ The character-at and character-at-setter methods interpret the byte as a
character value.
These function provide access to memory in two-byte chunks:
Low-Level Facilities
You can use the signed-byte-at method to read a signed byte of data from a
particular address.
Low-Level Facilities
DESCRIPTION
The Apple Dylan method signed-byte-at examines one byte of memory at the
address specified by the machine-pointer argument and returns its value as an
integer between –128 and 127.
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the signed-byte-at-setter method to write a signed byte of data to
a particular address.
DESCRIPTION
Low-Level Facilities
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the unsigned-byte-at method to read an unsigned byte of data
from a particular address.
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
Low-Level Facilities
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the character-at method to read one byte of data from a particular
address as a character.
Low-Level Facilities
DESCRIPTION
The Apple Dylan method character-at examines one byte of memory at the
address specified by the address argument and returns the value as a character
object. This function uses the Macintosh extended ASCII encoding.
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
DESCRIPTION
Low-Level Facilities
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the signed-short-at method to read two bytes of data from a
particular address.
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the signed-short-at-setter method to write two bytes of data to a
particular address.
Low-Level Facilities
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the unsigned-short-at method to read two bytes of data from a
particular address as an unsigned integer.
Low-Level Facilities
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
DESCRIPTION
Low-Level Facilities
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the unicode-character-at method to read two bytes of data from a
particular address as a Unicode character.
DESCRIPTION
The Apple Dylan method character-at examines two bytes of memory at the
address specified by the address argument, interprets the value as a Unicode
character encoding, and returns the value as a character object.
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
Low-Level Facilities
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the signed-long-at method to read a long word of data from a
particular address.
Low-Level Facilities
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the signed-long-at-setter method to write four bytes of data to a
particular address.
DESCRIPTION
The Apple Dylan method signed-long-at-setter copies the low four bytes of
the binary representation of the integer argument to the address specified by the
machine-pointer argument.
As the function result, the function simply returns the value of the integer
argument unchanged.
You can call this function using the extended assignment syntax, as shown here:
Low-Level Facilities
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the unsigned-long-at method to read a long word of data from a
particular address as an unsigned integer.
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
Low-Level Facilities
DESCRIPTION
The Apple Dylan method signed-long-at-setter copies the low four bytes of
the binary representation of the integer argument to the address specified by the
machine-pointer argument.
You can call this function using the extended assignment syntax, as shown here:
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the pointer-at method to read four bytes of data from a particular
address as a machine pointer.
DESCRIPTION
The Apple Dylan method pointer-at examines four bytes of memory at the
address specified by the address argument and returns the value as a
machine-pointer object.
Low-Level Facilities
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
Low-Level Facilities
You can use the ostype-name-at method to read a four-byte OSType value at a
particular address into a four-character native Apple Dylan string.
DESCRIPTION
The Apple Dylan method ostype-name-at reads four bytes of memory at the
address specified by the address argument, converts the bytes to characters, and
returns a native Apple Dylan string object containing those characters.
You use this method primarily to read the values of the Macintosh Toolbox
type OSType. Some examples include "CODE", "CDEV", "MENU" and so on.
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
string The native Apple Dylan string containing the four characters to
write to the indicated address.
address A machine pointer containing the address to write to.
Low-Level Facilities
DESCRIPTION
The Apple Dylan method ostype-name-at-setter writes the first four characters
contained the native Apple Dylan object provided as the string argument as
four bytes at the address specified by the address argument.
The Apple Dylan string object provided as the string argument must have at
least four characters; additional characters are ignored.
As the function result, the function simply returns the value of the string
argument unchanged.
You can call this function using the extended assignment syntax, as shown here:
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
Low-Level Facilities
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
You can use the c-string-at-setter method to write a native Apple Dylan
string as a null-terminated array of bytes at a particular address.
DESCRIPTION
Low-Level Facilities
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
Low-Level Facilities
DESCRIPTION
SEE ALSO
For examples of this and other machine-pointer methods, see “Using Machine
Pointers Directly” on page 146.
Low-Level Facilities
DESCRIPTION
This macro allocates a temporary block of memory on the stack, executes any
specified code, and then deallocates the temporary memory.
More specifically, this macro allocates size bytes of temporary memory, creates a
pointer object of the specified class, stores a pointer to the temporary memory
in the pointer object, and binds the specified variable name to the pointer object.
You may also supply optional keyword-value pairs to specify additional
initialization information, as appropriate for the specified class.
The macro then executes the body of code you supply. While this code is
executing, the temporary memory remains allocated and can be accessed
through the pointer object.
When the body of code finishes executing, Apple Dylan deallocates the
temporary memory and the pointer object, and the variable is unbound.
SEE ALSO
For an example using this macro, see “Allocating Stack Storage” on page 148.
For a higher-level version of this macro, see the description of the with-stack
macro in Part II of this book.
Low-Level Facilities
with-stack-structure
( variable ( class [, extra-bytes: n ] [, keyword-value-pairs ] ),
begin
body
end )
DESCRIPTION
Low-Level Facilities
SEE ALSO
Low-Level Facilities
return-location The location where a return value is passed. For every return
value expected from the foreign function, you specify the
location where the foreign function returns the value. For 68k
machines, you can specify the keyword stack: or a keyword
representing a machine register (D0:, A1: and so on). For
PowerPC, you can specify a register(R3:, R4:, . . . R10:).
return-encoding A keyword that indicates how the return value is encoded.
Possible values include long:, short:, byte:, char:, boolean:,
pointer:, unsigned-long:, unsigned-short:, unsigned-byte:, and
unicode-char:.
argument-location
The location where an argument is passed. For every argument
expected by the foreign function, you specify the location where
the foreign function expects to find the argument value. For 68k
machines, you can specify the keyword stack: or a keyword
representing a machine register (D0:, A1: and so on). For
PowerPC, you can specify a register(R3:, R4:, . . . R10:) or you
can specify the stack using the notation #(stack:, byte-offset)
where byte-offset is a positive integer.
argument-encoding
A keyword that indicates how the return value is encoded.
Possible values include long:, short:, byte:, char:, boolean:,
pointer:, unsigned-long:, unsigned-short:, unsigned-byte:, and
unicode-char:.
Low-Level Facilities
DESCRIPTION
This function calls the foreign function indicated by the callee parameter using
the access path indicated by the access-path parameter. The specified access path
determines how the callee is interpreted:
For each return value returned by the foreign function, you provide a pair of
arguments that indicate the location of the return value and the encoding used
for the return value.
Similarly, for each argument to the foreign function, you provide three values:
■ the location to pass the argument value
■ the encoding used for the argument
■ the value to pass for the argument
You can use the alien-method macro to create a callback function and a
C-compatible pointer to the callback function.
Low-Level Facilities
argument-location
The location where the callback function expects an argument
to be passed. For 68k machines, you can specify the keyword
stack: or a keyword representing a machine register (D0:, A1:
and so on). For PowerPC, you can specify a register(R3:, R4:, . . .
R10:).
argument-encoding
A keyword that indicates how the callback function expects the
argument to be encoded. Possible values include long:, short:,
byte:, char:, boolean:, pointer:, unsigned-long:,
unsigned-short:, unsigned-byte:, and unicode-char:.
parameter-variable
The parameter variable name bound to the argument value
passed to the callback function.
body The Apple Dylan code that makes up the body of the callback
function.
Low-Level Facilities
DESCRIPTION
This macro creates a callback function with the specified parameters, return
values, and body. The result of this macro is a function pointer of the specified
class that you can pass to C-compatible library code.
The preemption facilities allow you to control the preemption status—that is,
whether preemption is currently enabled or disabled.
Preemption Constants 7
Constant Meaning
$preemption-enabled Preemption status indicating that preemption is
permitted.
$preemption-disabled Preemption status indicating that preemption is
disallowed.
You can use these constants to specify preemption status when calling the
functions described in the next section.
Preemption Functions 7
Low-Level Facilities
DESCRIPTION
SEE ALSO
The values returned by this function are discussed in the previous section,
“Preemption Constants.”.
For an introduction to preemption, see “Using Preemption and Event
Checking” on page 151.
To change the current preemption status, use the %preemption-status-setter
function, described in the next section.
%preemption-status-setter ( status )
DESCRIPTION
This function sets the current preemption status to the value indicated by the
status argument. If status indicates that preemption should be enabled, this
function immediately checks for and processes any pending event checks. The
value of status must be one of the following:
■ the result of a call to the built-in function %preemption-status
■ the value bound to the variable in a saving-preemption-status macro call
■ one of the constants $preemption-enabled and $preemption-disabled.
Low-Level Facilities
SEE ALSO
%preemption-disable()
DESCRIPTION
SEE ALSO
Low-Level Facilities
DESCRIPTION
This function takes a single argument and returns true if that argument
indicates that preemption is enabled. The value of the status argument must be
one of the following:
■ the result of a call to the built-in %preemption-status function
■ the value bound to the variable in a saving-preemption-status macro call
■ one of the constants $preemption-enabled or $preemption-disabled
SEE ALSO
Preemption Macros 7
The macros described in this section allow you to control preemption status
during the execution of specific bodies of code.
body The body of code for which you want to disable preemption.
results The values returned by the body of code.
Low-Level Facilities
DESCRIPTION
This macro executes the body with preemption disabled. When the body of
code finishes executing, this macro restores the preemption status to its original
value. If preemption is enabled as a result, this macro immediately checks for
and processes any pending event checks.
This macro returns the values returned by the body of code.
SEE ALSO
For examples of using the preemption facilities, see “Using Preemption and
Event Checking” on page 151.
To determine the current preemption status, use the %preemption-status
function, described in the previous section.
To preserve the current preemption status before entering a block of code, use
the saving-preemption-status macro, described in the next section.
For the discussion of the possible preemption statuses, see “Preemption
Constants” on page 178.
DESCRIPTION
This macro stores the current preemption status, executes the specified body of
code, and then restores the preemption status. If the restored status is
Low-Level Facilities
preemption enabled, then this macro immediately checks for and processes any
pending event checks.
You may supply a variable name to this macro; if you do, the macro binds the
variable to the initial preemption status.
Note that the preemption status is not changed by this form. However, you
may set the preemption status within the body, and this macro will restore it to
its original value on exit.
This macro returns the values returned by the body.
SEE ALSO
For examples of using the preemption facilities, see “Using Preemption and
Event Checking” on page 151.
To determine the current preemption status, use the %preemption-status
function, described in the previous section.
To disable preemption during execution of a particular body of code, use the
without-preemption macro, described in the previous section.
Low-Level Facilities
result A Boolean value indicating whether the break request keys are
currently being pressed.
DESCRIPTION
SEE ALSO
Low-Level Facilities
Event-Checking Functions 7
The functions described in this section allow you to override the default
event-checking behavior and control the amount of time between preemptive
event checks.
You can use the event-check function to implement preemptive event checking.
event-check()
DESCRIPTION
saving-preemption-status ()
%preemption-status() := $preemption-enabled;
do-long-computation();
end;
Low-Level Facilities
SEE ALSO
For information about break requests, see “Preemption Constants” on page 178
and “Using Preemption and Event Checking” on page 151.
To determine the current preemption status, use the %preemption-status
function, described in the previous section.
To disable preemption during execution of a particular body of code, use the
without-preemption macro, described in the previous section.
You can use the event-check-interval function to determine the current time
interval between preemptive event checks.
DESCRIPTION
This function returns the current event check interval, as set by the most recent
call to set-event-check-interval. A positive number indicates milliseconds,
while a value of 0 indicates that preemptive event checking is disabled.
SEE ALSO
Low-Level Facilities
You can use the set-event-check-interval function to set the time interval
between preemptive event checks.
set-event-check-interval ( interval )
DESCRIPTION
This function takes a single argument, which you use to specify the desired
length of time between preemptive event checks. A positive number for this
argument indicates the number of milliseconds; a zero value indicates that
preemptive event checking should be disabled.
For example, calling
set-event-check-interval(333)
SEE ALSO
Microsecond Functions 7
You can use the %microsecond-time function to determine the current time in
microseconds.
Low-Level Facilities
DESCRIPTION
This function gets the current time in microseconds, and returns it as two
small-integers.
DESCRIPTION
This function calculates the difference between two times in the format
returned by the %microsecond-time function, returning the difference in the
same format.
Low-Level Facilities
DESCRIPTION
Low-Level Facilities
8 Garbage Collection
Contents
About Garbage Collection 193
Overview of Apple Dylan Garbage Collection 193
Ephemeral Garbage Collection 194
Garbage-Collecting Algorithms 195
Large-Object Garbage Collection 196
Using Garbage Collection 197
Using Spontaneous Garbage Collection 197
Requesting Garbage Collection 197
Controlling Garbage Collection Settings 198
Debugging 199
Error Handling 200
Garbage Collection Reference 201
Constants and Variables 201
Functions 202
Contents 191
192 Contents
C H A P T E R 8
Garbage Collection 8
Garbage Collection
garbage collection works for you, reclaiming memory behind the scenes,
undetectable except for a possible delay of a fraction of a second.
Although the default garbage collection behavior eliminates the need for you
to worry about memory management, Apple Dylan also provides flexibility in
the garbage collection system, allowing you to adjust its behavior when
fine-tuning your application’s performance. For example, you can disable
spontaneous garbage collection during time-critical tasks, and you can invoke
requested garbage collections at times more appropriate for your application.
Two important points to note:
■ Apple Dylan does move objects around in memory during garbage
collection. However, Apple Dylan never requires you to rely on the actual
address of an Apple Dylan object.
■ Not all memory is subject to garbage collection. For example, objects in C
libraries are allocated and deallocated using conventional memory
management techniques. Garbage collection does not affect these objects.
Apple Dylan also provides some debugging and error-handling facilities
relating to garbage collection and memory management. See “Debugging” on
page 199 and “Error Handling” on page 200 for more information.
Garbage Collection
The youngest and middle generations are called the ephemeral generations,
because objects do not belong to these generations for very long; instead they
are either garbage collected or promoted.
The middle generation contains two steps. Objects promoted to the middle
generation are placed in the first step. As they survive garbage collections, they
are promoted to the second step, and then eventually to the eldest generation.
The eldest generation is not an ephemeral generation; objects in the eldest
generation remain there until they are reclaimed.
Generations are numbered with nonnegative integers. Older generations have
larger numbers. The youngest generations number is zero. See the description
of the function object-generation-number, which is on page 203.
Spontaneous garbage collection is invoked when there is an attempt to allocate
memory and memory is exhausted, or when one of the ephemeral generations
reaches its size limit.
In general, the younger the generation, the fewer objects it contains and the
larger percentage of garbage (inaccessible objects) it contains. For example, the
youngest generation tends to be smaller and contain more garbage than the
middle generation.
Apple Dylan capitalizes on these statistical differences between generations to
increase the overall efficiency of garbage collection. By garbage collecting from
younger generations more frequently than older generations, Apple Dylan
maximizes the amount of garbage collected and minimizes the amount of
memory examined.
Apple Dylan allocates memory for these generations from the Macintosh
application heap. You can exert some control over this memory allocation using
the variables described in “Controlling Garbage Collection Settings” on
page 198.
Garbage-Collecting Algorithms 8
Apple Dylan provides two different algorithms for freeing memory during
garbage collection: the copying algorithm and the compacting algorithm.
The default algorithm is the copying algorithm. During garbage collection, this
algorithm examines regions of memory. For each region, the algorithm copies
the accessible objects into a new memory region, and ignores the inaccessible
Garbage Collection
objects. When an entire region of memory has been examined, all the accessible
objects have been copied, so the entire region of memory can be reclaimed.
An alternative is the compacting algorithm. As this algorithm examines a
region of memory, it moves the accessible objects to one end of the region.
When the entire region has been examined, one end of the region contains
accessible objects and the other end of the region is reclaimed.
The copying algorithm is generally faster, though it requires more memory.
Apple Dylan automatically switches to the compacting algorithm when there is
not enough memory for the copying algorithm.
You should note that under certain virtual memory situations, the extra
memory used by the copying algorithm causes this algorithm to be slower than
the compacting algorithm. Apple Dylan allows you to choose the algorithm, as
described in “Controlling Garbage Collection Settings” on page 198.
Garbage Collection
Garbage Collection
■ The compact: argument allows you to specify whether Apple Dylan should
perform copying or compacting garbage collection. The default value is
determined by the *enable-compacting-garbage-collections* variable, as
discussed in the next section.
When trying to optimize performance as much as possible, you can perform
occasional requested garbage collections, even if you’re taking advantage of
spontaneous garbage collection. You can increase the efficiency of garbage
collections by requesting them occasionally before spontaneous garbage
collection is necessary—that is, when your program has ample free memory
available. It is less efficient to perform garbage collection only when memory is
nearly exhausted.
Garbage Collection
Macintosh heap when expanding an existing object block. The default value
is 50,000.
■ You can use the *bytes-per-LOS-cluster* variable to specify the minimum
number of bytes that Apple Dylan should allocate from the Macintosh heap
when creating a new large-object space. The default value is 200,000.
■ You can use the *bytes-per-LOS-cluster-expansion* variable to specify the
preferred number of bytes that Apple Dylan should allocate from the
Macintosh heap when expanding a large-object space. The default value is
50,000.
■ You can use the *enable-compacting-garbage-collection* variable to specify
that Apple Dylan should use the compacting algorithm, rather than the
copying algorithm, when garbage collecting. This variable applies to all
spontaneous garbage collections. It also applies to requested garbage
collections (calls to collect-garbage) if you do not specifically override it
using a compact: argument. The default value for this variable is #f, which
indicates that the copying algorithm should be used (unless there is not
enough memory available).
Debugging 8
Apple Dylan also provides two variables you may find helpful when
debugging and optimizing your program.
The first of these is *clobber-oldspace*. When this variable is #t, Apple Dylan
fills reclaimed memory with the hexadecimal pattern: #xDEADBEEF. This
distinctive pattern makes it easy for you to identify any references that
mistakenly point to reclaimed memory—a situation that should never occur if
Apple Dylan is working correctly. The default value for this variable is #t.
Setting it to #f makes garbage collection slightly more efficient.
The second debugging-related variable is *report-garbage-collections*, which
by default is set to #f. If you set this variable to #t, Apple Dylan collects
pertinent information during each garbage collection and prints the
information to the Listener window. (Note that requesting garbage collection
reports slows garbage collection down significantly.) This variable applies to all
spontaneous garbage collections; it also applies to requested garbage
collections (that is, calls to collect-garbage) if you do not specifically override
it using a report: argument.
Garbage Collection
Error Handling 8
Apple Dylan provides a number of tools you can use to anticipate, avoid, and
address the error situations caused by low-memory conditions.
The memory-available function allows you to determine the amount of memory,
in bytes, available for new objects. You should be aware of the following when
interpreting the integer returned by this function:
■ The function simply totals the number of available bytes; it does not
consider memory fragmentation. You may not be able to allocate a single
object of the size indicated by the return value of the function.
■ The function does not include memory committed to large-object spaces.
■ The function does not include reclaimable space. You may want to request a
garbage collection immediately prior to calling this function to ensure the
most accurate total.
Apple Dylan also provides the following two variables to help you anticipate
low-memory situations:
■ You use the *memory-shortage-level* variable to indicate the minimum
amount of available memory, in bytes, needed for your application to
operate normally. Apple Dylan initializes this to 20,000.
■ The *memory-shortage* variable, initially #f, is set to #t whenever the
memory available immediately after a garbage collection is less than the
amount you indicated in the *memory-shortage-level* variable. This variable
is set back to #f if a subsequent garbage collection yields an acceptable
amount of available memory.
Garbage Collection
Apple Dylan also provides two condition classes that signal low-memory
conditions:
■ The <memory-shortage> class, which is a subclass of <condition>. This
condition is signaled when there is not enough memory to create a
requested object.
■ The <memory-exhausted> class, which is a subclass of <serious-condition>.
This condition is signaled when there are less than *memory-shortage-level*
bytes available after garbage collection and *memory-shortage* is not already
true.
See the “Condition-Handling” chapter of the Apple Dylan Tutorial for
information about these classes.
The following table lists the constants and variables relating to garbage
collection. The variables are organized by subject, and for each variable, the
variable’s class and default value are shown:
*enable-compacting-garbage-collection* <boolean> #f
Garbage Collection
*clobber-oldspace* <boolean> #t
*memory-shortage* <boolean> #f
Functions 8
Garbage Collection
DESCRIPTION
SEE ALSO
For a discussion of when you might use this function, see “Requesting Garbage
Collection” on page 197.
Garbage Collection
DESCRIPTION
This function returns a value that indicates the generation to which the
specified object belongs:
■ 0 indicates the youngest generation
■ 1 indicates the middle generation
■ 4 (the value of $eldest-generation) indicates the eldest generation
■ 5 indicates the static generation
If an object’s generation number is less than $eldest-generation, it can change
at any time that a garbage collection can occur. However, it can only increase.
DESCRIPTION
This function returns the number of bytes of available memory. It does not take
into consideration fragmentation, large-object memory, or reclaimable memory.
SEE ALSO
9 Termination
Contents
About Termination 207
Termination and Garbage Collection 207
Termination Processing 208
Using Termination 209
Enabling Termination For an Object 209
Termination Processing 209
Specifying Termination Behavior 210
Resurrecting an Object 210
Termination Reference 211
Variables 211
Functions 211
Contents 205
206 Contents
C H A P T E R 9
Termination 9
About Termination 9
Termination is the facility provided by Apple Dylan that allows an object to
perform additional computation after it becomes inaccessible but before it is
reclaimed by the garbage collector and its memory freed.
As an example, suppose you create a class whose objects contain slots that
point to memory allocated directly (using the Toolbox routine NewPtr, for
example). For those objects, you might want to specify termination behavior in
which you deallocate that memory since the garbage collector does not manage
it and will not reclaim it.
By default, objects have no termination behavior: when Apple Dylan
determines during garbage collection that an object is inaccessible, the object is
reclaimed immediately and its memory is freed.
You can override this default behavior by enabling termination for an object,
(which indicates to Apple Dylan that the object is terminatable) and by
specifying termination behavior (which Apple Dylan invokes when
terminating the object).
Termination
Termination Processing 9
During garbage collection, Apple Dylan creates a termination queue—a queue
that contains the terminatable objects that the garbage collector determined to
be inaccessible.
After garbage collection completes, Apple Dylan performs termination
processing—that is, Apple Dylan executes the termination behavior for each
object in the termination queue.
Automatic termination processing occurs by default immediately after
garbage collection completes. (Actually, if preemption is not enabled, automatic
termination processing is delayed until the next time preemption is enabled.)
You can enable or disable automatic termination processing. You can also
invoke termination processing explicitly, using requested termination
processing.
During termination processing, the order in which the queued objects are
terminated is unspecified, with one exception. If one terminatable object
references a second terminatable object, but both objects are otherwise
unreachable, the first object (the one containing the reference) is terminated
before the second object (the referenced one).
Unless a reference to the object is created by the termination behavior, the
object will be reclaimed by the next garbage collection.
Termination
Using Termination 9
terminate-when-unreachable(my-terminatable-object);
This function enables termination for the object—that is, it identifies the object
as needing termination processing. If Apple Dylan determines during garbage
collection that this object is inaccessible, the object is not immediately
reclaimed. Instead, Apple Dylan disables termination for the object and places
it in the termination queue for later termination processing.
You can call this function multiple times on the same object. When the object
becomes inaccessible, Apple Dylan executes the object’s termination behavior a
corresponding number of times. However, multiple execution of the object’s
termination behavior is not guaranteed in future versions of Dylan and so you
should not depend on it.
Termination Processing 9
By default, you don’t have to do anything to enable automatic termination
processing. During garbage collection, Apple Dylan automatically queues
inaccessible objects that have termination enabled. Automatic termination
processing occurs immediately following the garbage collection (if preemption
is enabled; otherwise, automatic processing occurs the next time that
preemption becomes enabled).
You can disable automatic termination processing by setting the value of the
Boolean variable *enable-automatic-termination* to #f. By setting the value of
this variable to #f, you prevent Apple Dylan from automatically processing the
termination queue after garbage collection.
Termination
You can re-enable automatic termination processing by setting the value of this
variable to #t.
You can also explicitly invoke termination processing by calling the
drain-termination-queue function. This function, which takes no arguments,
calls the terminate function on each object awaiting termination in the
termination queue.
Resurrecting an Object 9
Generally, once an object has been terminated, it is reclaimed during the next
garbage collection of its generation. However, there are two ways in which you
can avert this impending reclamation, thereby resurrecting the object.
■ You can use the terminate method to create a reference to the object:
define method terminate (terminating-object :: <my-terminatable-class>)
*global-reference* := terminating-object;
end method;
Termination
Termination Reference 9
Variables 9
You can use this variable to enable or disable automatic termination processing,
as described in “Termination Processing” on page 209.
Functions 9
The functions described in this section allow you to enable termination for an
object, specify termination behavior, and invoke termination processing.
Termination
DESCRIPTION
This method marks the specified object as terminatable. When Apple Dylan
garbage collection determines that the object is inaccessible, it is queued for
termination processing.
SEE ALSO
Apple Dylan calls the terminate generic function on each object in the
termination queue during termination processing.
terminate ( object )
Termination
DESCRIPTION
SEE ALSO
drain-termination-queue ( )
DESCRIPTION
SEE ALSO
Termination
Framework Reference 2
10 Introduction
Contents
Conceptual Model 219
Framework Foundation 220
Event Handling 223
User Interface Support 228
Documents and Data Interchange 236
Contents 217
218 Contents
C H A P T E R 1 0
Introduction 10
This chapter introduces the conceptual model of Apple Dylan Framework and
briefly describes the the classes provided by Framework.
Conceptual Model 10
Conceptually, the Framework can be divided in three major subsystems:
■ event handling support.
■ support for the Macintosh user interface.
■ support for data manipulation.
The three major subsystems are built on a small foundation that provides
additional basic services beyond those provided by the Dylan language and
environment.
Figure 10-1 shows the three subsystems as rings around the foundation.
Windows Views
Event Object model
Drag and handlers support Clipboard
drop
Menus Graphics
Events Foundation Behaviors
Introduction
Framework Foundation 10
The foundation provides general services not implemented in the Dylan
language and environment. (Services that are provided by Dylan include
Introduction
See
Class Description Use Page
<stream> A stream of data. Define 517
subclass
<handle-stream> A stream that is read from or written to a Make 519
handle.
<file-stream> A stream that is read from or written to a Make 518
file.
<object-stream> A stream of Dylan objects. Define 521
subclass
<file-object-stream> A stream of Dylan objects that is read Make 521
from or written to a file.
<handle-object-stream> A stream of Dylan objects that is read Make 521
from or written to a handle.
<handle-string> A string in a handle. Make 639
<resource-string> A string in a resource. Make 640
Introduction
See
Class Description Use Page
<file> A Macintosh file. Define 496
subclass
<slot-spec> Internal. A specification for streaming a — 523
slot.
<class-spec> Internal. A specification for streaming a — 522
class.
<framework-library> Internal. Manages a list of resources for a — 649
Framework library.
Table 10-2 shows the classes that support error reporting and debugging.
See
Class Description Use Page
<os-error> An error typically reported by the Make 643
operating system and handled by the
Framework.
<framework-error> An error typically handled by the Define 642
Framework. subclass
<debugger-behavior> A behavior that provides the Debug menu — 645
and actions associated with its menu
items.
Introduction
Table 10-3 shows the classes that support general geometric operations. For the
classes that support QuickDraw geometric operations, see Table 10-8 on
page 229.
See
Class Description Use Page
<rect> A rectangle. Make 635
<region> A region. Specialize 635
only
Event Handling 10
Event handlers are objects that can respond and handle events. For complete
information about event handling, see page 241. Remember that many user
interface elements identified in the section “User Interface Support” on
page 228 are also event handlers, as are documents (see page 236). Table 10-4
shows the general event-handling classes.
See
Class Description Use Page
<event-handler> An object capable of responding to an Specialize 263
event. Event handlers include only
documents, windows, views, controls,
and so on.
Introduction
See
Class Description Use Page
<main-handler> The event handler responsible for events Specialize 265
not handled by other event handlers. only
Events are notifications from the Macintosh OS that the state of the application
or the environment has changed. Table 10-5 shows the objects created by the
Framework after calling WaitNextEvent from the Framework’s main event loop.
See
Class Description Use Page
<event> An event representing a change in the Specialize 267
state of the hardware or operating only
system.
<toolbox-event> An event defined by the Macintosh Specialize 268
toolbox EventRecord data structure. only
<window-event> A window event, such as an activate, Specialize 271
update, or mouse event. only
<mouse-event> A mouse event, such as a mouse-down, Specialize 273
mouse-up, or mouse-moved event. only
<generic-mouse A mouse-down event, whether or not it Specialize 273
-down-event> is in an active window. only
<mouse-down-event> A mouse-down event within an active Specialize 273
window. only
Introduction
See
Class Description Use Page
<background-mouse A mouse-down event within an Specialize 273
-down-event> inactive window. only
<mouse-up-event> A mouse-up event. Specialize 273
only
<key-event> A key event, such as a key-up or Specialize 270
key-down event. only
<key-down-event> A key-down event. Specialize 270
only
<key-up-event> A key-up event. Specialize 270
only
<activate-event> An activate event. Specialize 271
only
<update-event> An update event. Specialize 271
only
<system-event> A system event, such as a suspend or Specialize 271
resume event. only
<suspend-event> A suspend event. Specialize 271
only
<resume-event> A resume event. Specialize 271
only
<mouse-moved-event> A mouse-moved event. Specialize 273
only
<disk-event> A disk event. Specialize 270
only
<become-target-event> An event that notifies event handlers in Specialize 274
the target chain of a new target. only
<resign-target-event> An event that notifies event handlers in Specialize 275
the target chain of a change in the target. only
Introduction
Object model support includes support for scripting and recordability. It also
uses and responds to Apple events. Table 10-6 shows the classes involved with
object model support.
See
Class Description Use Page
<ae-desc> An Apple event descriptor record. Define 607
subclass
<relative-descriptor> An Apple event descriptor record. Make 611
<index-descriptor> An Apple event descriptor record. Make 611
<range-descriptor> An Apple event descriptor record. Make 611
<logical-descriptor> An Apple event descriptor record. Make 611
<comparison An Apple event descriptor record. Make 611
-descriptor>
Introduction
See
Class Description Use Page
<get-data-event> A Get Data Apple event. Make 612
<set-data-event> A Set Data Apple event. Make 612
<create-element A Create Element Apple event. Make 612
-event>
Introduction
See
Class Description Use Page
<designator> A temporary reference used to specify Define 561
data in an object for object model support. subclass
<selection-designator> A designator for the cSelection class of Make 562
Apple event objects.
<text-designator> A designator for the cText class of Apple Make 563
event objects.
<character-designator> A designator for the cChar class of Apple Make 563
event objects.
<range-designator> Designates a range of bytes. Make 564
<offset-designator> Designates bytes of data offset from a Make 564
starting point.
<property> A designator for the cProperty class of Define 616
Apple event objects. subclass
<document-property> A designator for a specific property of the Make 616
cDocument class of Apple event objects.
Introduction
See
Class Description Use Page
<frame> The location and extent of a window, Specialize 319
view, or graphics port. only
<graphics-port> A port through which an image is Specialize 320
rendered. only
<text-style> A text style, such as font information. Specialize 322
only
<qd-region> A QuickDraw region. Make 324
<qd-text-style> Font information for QuickDraw text. Make 322
<qd-graphics-port> A QuickDraw GrafPort. Specialize 320
only
<qd-graphics A buffer for graphics based on a Make 320
-buffer> graphics world (GWorld).
<qd-graphics A buffer for graphics based on a Make 320
-buffer> graphics world (GWorld).
<rgb-color> An RGB color specification. Make 324
Introduction
See
Class Description Use Page
<window> A window. Make 407
<window-context> An event handler that manages one or Define 406
more windows. subclass
<view> An area within a window, typically Define 355
used for drawing or responding to subclass
events.
<view-determiner> A rule that determines how the location Define 362
and size of a view changes in relation to subclass
a change in the extent of its superview
or subviews.
<has-super-view A rule that specifies that a view has the Make 362
-bounds> same location and size as its superview.
<super-view-horiz A rule that specifies proportional Make 362
-relative-determiner> resizing of a view’s extent in relation to
a horizontal change in its superview.
<super-view-vert A rule that specifies proportional Make 362
-relative-determiner> resizing of a view’s extent in relation to
a vertical change in its superview.
<super-view-relative A rule that specifies proportional Make 362
-determiner> resizing of a view’s extent in relation to
a change in the extent of its superview.
<horiz-scroll-bar A rule that specifies how a horizontal Make 362
-determiner> scroll bar control can change in the
extent of its superview.
<vert-scroll-bar A rule that specifies how a vertical Make 362
-determiner> scroll bar control can change in the
extent of its superview.
Introduction
See
Class Description Use Page
<grow-icon A rule that determines the position of Specialize 413
-determiner> the size box if its superview’s extent only
changes.
<grow-icon> A size box for a window. Specialize 413
only
<scroller> A view that represents an area that can Make 471
be larger than the area of its associated
window, and thus be scrollable.
<tracker> An object that provides visual feedback Define 473
for mouse movements. subclass
Table 10-10 shows classes that implement TextEdit features and text entry in
dialog boxes.
See
Class Description Use Page
<text-view> A view for TextEdit operations. Make 375
<edit-text> A view for an editable text field used Make 378
typically in a dialog box.
<number-text> A view for an editable text field in which the Make 379
text is constrained to digits used typically in
a dialog box.
<edit-text-dialog A behavior that handles special characters Specialize 436
-filter> (tab, return, escape, and so on) while editing only
text in a dialog box.
Introduction
See
Class Description Use Page
<grid-view> A view that is subdivided into cells. Define 391
subclass
<list-view> A view that is a single column of cells. Make 394
<text-grid-view> A grid view whose cells display text. Make 394
<text-list-view> A list view whose cells display text. Make 395
<grid-arrow-key-behavior> A behavior that selects cells in a grid Make 396
by using the arrow keys.
<grid-select-behavior> A behavior that selects cells in a grid Make 396
for editing.
Table 10-12 shows classes for implementing dialog boxes and controls.
See
Class Description Use Page
<tabber> A behavior that provides tabbing Define 435
between fields in a dialog box. subclass
<dialog-behavior> A behavior that implements modal Make 433
dialogs.
<static-text> A view for unchangeable text. Make 439
<simple-icon> An icon. Make 438
<ctl-mgr-control> A Control Manager control. Make 446
<ctl-mgr-button> A Control Manager push button control. Make 449
<ctl-mgr-check-box> A Control Manager checkbox control. Make 449
Introduction
See
Class Description Use Page
<ctl-mgr-radio> A Control Manager radio button control. Make 450
<ctl-mgr-scroll-bar> A Control Manager scroll bar control. Make 451
<ctl-mgr-popup> A Control Manager popup menu Make 452
control.
<cluster> A view for a group of controls that Make 437
operate together, such as radio buttons.
<control> A control. Define 440
subclass
<button> A push button control. Define 443
subclass
<check-box> A checkbox control. Define 443
subclass
<radio> A radio button control. Define 443
subclass
<scroll-bar> A scroll bar control. Define 444
subclass
<popup> A popup menu control. Define 445
subclass
<control-event> An event associated with a control. Specialize 454
only
<button-event> An event associated with a push button Specialize 454
control. only
<check-box-event> An event associated with a checkbox Specialize 454
control. only
<radio-event> An event associated with a radio button Specialize 454
control. only
Introduction
See
Class Description Use Page
<scroll-bar-event> An event associated with a scroll bar Specialize 454
control. only
<popup-event> An event associated with a control. Specialize 454
only
<popup-menu> Internal. A menu inside a Control —
Manager popup menu control.
Table 10-13 shows classes that implement menus, including menu event
handling.
See
Class Description Use Page
<menu-bar> Internal. The menu bar. — .
<menu-element> A menu element, such as a menu item Specialize 292
or hierarchial menu. only
<menu> A menu, such as the File menu. Make 297
<menu-item> A menu item, such as the Save item of Make 294
the File menu.
<separator-item> A divider between menu items. Make 297
<apple-menu> The Apple menu. Specialize 300
only
<menu-event> An event that affects a menu item. Define 301
subclass
Introduction
See
Class Description Use Page
<adorner> A visible adornment to a view; for Define 360
example, a border. subclass
<draw-adorner> An adorner that controls the order in Specialize 360
which other adorners are drawn. only
<hilite-adorner> An adorner that controls the order in Specialize 360
which other adorners are highlighted. only
<frame-adorner> An outline just inside a rectangular view. Make 360
<black-background A rectangle behind a rectangular view. Make 360
-adorner>
Table 10-15 shows classes that implement context-sensitive undo and redo.
See
Class Description Use Page
<command> A command that handles undo and Define 540
redo operations. subclass
<command-context> Event handlers to which an undo or Make 539
redo operation applies.
<typing-command> A command that handles undo and Specialize 542
redo for text. only
Introduction
See
Class Description Use Page
<text-style-command> A command that implements undo and Define 544
redo for text styles. subclass
<font-command> A command that implements undo and Make 545
redo for the kind of font in a text style.
<font-size-command> A command that implements undo and Make 545
redo for the font size in a text style.
<font-style-command> A command that implements undo and Make 545
redo for the font style (bold, italic, and
so on) in a text style.
See
Class Description Use Page
<document> An object that represents the relationship Define 485
between data, views and files. subclass
Introduction
Table 10-17 shows the classes that provide general support for transferring data
to and from the clipboard or within or between applications via drag and drop.
See
Class Description Use Page
<typed-data> Data whose data type, such as text or Define 558
pict, is specified. subclass
<typed-pointer> Typed data that is referenced by a pointer. Make 559
<typed-handle> Typed data that is referenced by a handle. Make 560
<data-item> Data that may be represented with Make 560
several data types.
See
Class Description Use Page
<clipboard-behavior> A behavior that responds to clipboard Define 594
events, such as cut, copy, paste, or clear. subclass
It is automatically associated with text
views.
<clipboard-command> A command to handle a clipboard event. Specialize 596
only
<cut-command> A command to handle a cut event. Specialize 596
only
<paste-command> A command to handle a paste event. Specialize 596
only
Introduction
See
Class Description Use Page
<clear-command> A command to handle a clear event. Specialize 596
only
<clipboard-flavor> The kind of data stored in the scrap. Define 595
subclass
<clipboard> The clipboard. Specialize 594
only
Table 10-19 shows the classes that implement drag and drop support.
See
Class Description Use Page
<drag> A dragging operation. Make 577
<drag-item> An item selected in a drag operation. Make 578
<drag-flavor> The data in a drag item, which is Make 579
represented in a specific data type.
<drag-event> Internal. A mouse event interpreted as a — 580
drag.
<track-drag-event> Internal. An event which indicates that — 580
items are being dragged through a window.
<receive-drag Internal. An event which indicates that an — 580
-event> item was dropped on a window.
11 Event Handling
Contents
About Event Handling 242
Kinds of Events 242
Event Handlers 246
The Target Chain 248
Responding to Events 250
Event Handling Using the Target Chain 251
Mouse Event Handling 252
Changing the Target 254
Behaviors and Event Handling 254
Using Event Handling Objects 259
Adding an Event Handler to the Target Chain 259
Defining a do-event Method 260
Implementing a Behavior 260
Specifying Actions When the Target Changes 263
Event Handling Objects Reference 263
The <event-handler> Class 263
The <main-handler> Class 265
The <behavior> Class 266
The <event> Class 267
Toolbox Event Classes 268
The <disk-event> Class 270
Key Event Classes 270
System Event Classes 271
Window Event Classes 271
Mouse Event Classes 273
The <become-target-event> Class 274
Contents 239
240 Contents
C H A P T E R 1 1
Event Handling 11
Event handling is the mechanism that detects events and allows your
application to take action in response to them. Events include mouse clicks, key
strokes, window activation and update, Apple events, and so on. The event
handling mechanism is defined by functions that are called to detect these
events, package the events into objects, and dispatch them so that the code you
write can respond.
This chapter describes the general event handling mechanism and how your
application can respond to events. Events related to menus, controls, and
Apple events are described in detail in separate chapters. For specific
information about menu events, see “Menus” on page 283. For specific
information about menu events, see “Control Events” on page 423. For specific
information about Apple events, see “Scripting Support” on page 601.
In addition to describing the general event handling mechanism, this chapter
also shows you how to:
■ determine the state of an event
■ respond to an event
■ set up a behavior that responds to an event
241
Event Handling
Kinds of Events 11
An event is a notification by the Event Manager about a change in the state of
the Macintosh hardware or operating system. For example, the Event Manager
notifies the application when the user presses or releases the mouse button or a
key on the keyboard, when a window is activated or deactivated, when part of
the screen must be redrawn, when an Apple event is sent to the application,
and so on. For a complete discussion of the Event Manager and event
Event Handling
Event Handling
Objects created from the classes in Figure 11-1 represent the following kinds of
events:
<become-target-event> Represents a change in the target and specifies the
event handler to become the new target. This class is
used in conjunction with the <resign-target-event>
class. The <become-target-event> class is discussed
on page 274.
<control-event> Represents an event related to a control, such as the
pushing a button or clicking a radio button or
scroller. For information about the <control-event>
class, see page 454.
<menu-event> Represents an event in a menu, such as selecting a
menu item with the mouse or by a keyboard
equivalent. For more information about the
<menu-event> class, see “The <menu-event> Class”
on page 301.
<scripting-event> Represents an event related to the object support
model and Open Scripting Architecture (OSA). For
more information about the <scripting-event> class,
see “Scripting Event Classes” on page 612.
<resign-target-event> Represents a change in the target and specifies the
event handler to become the new target. This class is
used in conjunction with the <become-target-event>
class. The <resign-target-event> class is discussed
on page 275.
<toolbox-event> Represents an event defined by the Macintosh
toolbox EventRecord data structure. The
<toolbox-event> class is described on page 268.
<disk-event> Represents a disk event.
<key-event> Represents a key event, such as a key-up or
key-down event. For more information about this
class, see “Key Event Classes” on page 270.
<key-down-event> Represents a key-down event. For more information
about this class, see “Key Event Classes” on page 270.
<key-up-event> Represents a key-up event. For more information
about this class, see “Key Event Classes” on page 270.
Event Handling
Objects created from the classes in Figure 11-2 represent the following kinds of
events:
Event Handling
Event Handlers 11
Objects that can respond to events are called event handlers. Objects that
represent documents, windows, and views are event handlers because they can
respond to, and thus handle, events. Figure 11-3 shows some of the event
handler classes provided by the Framework.
Note
As a subclass of <event-handler>, classes such as <view>,
<window>, and <document>, inherit the ability to handle
events. The primary purpose of these subclasses is to
represent corresponding components of an application;
thus, each subclass is described in the chapter for the
relevant component. ◆
Objects created from the classes in Figure 11-3 represent the following kinds of
events:
Event Handling
Event Handling
Figure 11-4 Target chain for a document with one window and content view
<main-handler>
<document>
<window>
Event Handling
Event Handling
<main-handler>
<document> <document>
<my-view> <my-view>
Responding to Events 11
The response to an event may be handled completely or partially by the
Framework or the response may be left for the application to handle. In many
cases, the Framework responds to and completely handles the event for you.
For example, if the user clicks on a window that is not active, the Framework
detects the event, creates an object that represents it, and then responds to the
event by bringing the window to the front and making it active.
In other cases, the Framework may respond partially. For example, when the
user clicks the mouse, the Framework determines whether this is another click
in a sequence of double or triple clicks or whether it is the first click in a new
Event Handling
sequence. Your application can test the condition (single, double, or triple click)
and respond further.
Some events cannot be completely or partially handled because the events
drive specific functions in the application. Often events that occur in the
content area of a window, such as within a view, or within the menu bar are
often left for the application to handle because the response defines the
characteristics of the application. For example, a mouse-down and
mouse-moved events in a “paint” application may cause the application to
respond by drawing a line. The same events in a word-processing application
may cause the application to respond by highlighting text.
When an event occurs, the Framework packages the event into the appropriate
kind of event object and dispatches it for handling by an event handler—
usually the target event handler. Although the Framework may dispatch some
events so that they may be handled by other event handlers, the target event
handler is the first event handler that is allowed to respond to an event for any
event that your application can respond to.
The Framework handles most kinds of events by sending the event to the
target event handler and allowing event handlers in the target chain handle
event. The Framework, however, handles mouse events slightly differently. The
following sections describe how the target chain is used in event handling and
the differences for mouse event handling.
Event Handling
specialize the parameters for the event handler, the event itself, and another
object, which may be a singleton that uniquely identifies the object.
For example, to allow a document to respond to a particular menu item, you
can define a do-event method specialized on your document, event objects
from the <menu-event> class, and a singleton parameter that specifies the menu
item. The Framework will call the do-event method when it reaches the
document in the target chain. Of course, the event and singleton must also
match. For an example of setting up a do-event method, see “Defining a
do-event Method” on page 260. For information and examples about setting up
do-event methods for menu events, see “Responding to Menu Events” on
page 290.
Event Handling
Subview C
Subview A
Subview B
Target view
Mouse click
The target handler is the content view and the mouse down event could be
handled by the content view or its subviews B or C. Subview A does not have
the chance to handle the event because the event did not occur within its
bounds. The Framework starts with the deepest subview, which is subview C
in Figure 11-6. If subview C does not handle the event, the Framework allows
the next higher view to handle it and so on.
If the mouse event is not handled by a subview or the target handler, the event
is passed up the target chain, as with other events. Unlike other events,
Event Handling
however, mouse events are not passed up the target chain further than the
window. If a mouse event is not handled by any of the views in the view
hierarchy and is not handled by the window, the event is passed directly to the
main handler; event handlers between the window and the main handler, such
as a document, are skipped.
Event Handling
Event Handling
<main-handler>
<my-app-menu-behavior>
<document>
<window>
<my-menu-item-behavior>
<view>
(Root view)
Target <my-view>
<my-select-behavior>
<my-special-key-behavior>
Event Handling
Objects created from the classes in Figure 11-8 represent the following
behaviors:
<behavior> Represents the ability to usurp and handle events
associated with the event handler to which the
behavior is attached. The <behavior> class is
described in this section; see page 266.
<clipboard-behavior> Represents the behavior associated with the
clipboard, including the ability to handle the
following Edit menu items: Cut, Copy, Paste, and
Clear. For more information about the
Event Handling
Event Handling
Event Handling
If an event has been handled completely, it is not necessary to pass the event up
the target chain. If you want other event handlers or their behaviors to also
handle the event, call next-method from your do-event method.
Note
For examples of do-event methods that respond to menu
events. See “Responding to Menu Events” on page 290. ◆
Implementing a Behavior 11
Behaviors are useful for specifying additional actions for an event handler. For
example, you typically define a behavior and add it to the main handler so that
menu items, such as New, can be handled by the main handler without
requiring you to define a subclass of <main-handler> and specialize a do-event
Event Handling
method on the subclass. For an example of how a behavior can handle a menu
event, see “Responding to Menu Events” on page 290.
To implement a behavior, perform the following steps:
1. Define a subclass of the <behavior> class.
2. Define methods whose parameters are specialized on your behavior
subclass. For a list of methods, see Table 11-3, “Event-handling functions for
dispatching” on page 279.
3. Add the behavior to the appropriate event handler.
Listing 11-3 shows the class definition for a <tool> class that changes the cursor
and handles mouse tracking within a view.
Listing 11-4 shows the behavior-event method that specifies the actions to take
when the <paint-view> event handler is allowed to respond to a mouse-down
event. The behavior is allowed to respond before the event handler’s do-event
method is called.
Event Handling
Listing 11-5 shows the behavior-set-cursor method that specifies the actions to
take when the <paint-view> event handler is allowed to respond to a
mouse-moved event. The behavior is allowed to respond before the event
handler’s do-set-cursor method is called.
set-cursor($arrow-cursor);
end method;
You can add a behavior to the list of behaviors for an event handler at any time
and remove a behavior when it is no longer needed. Listing 11-6 shows how to
add and remove a behavior.
Behaviors receive a chance to handle and event in the order that they exist in
the event handler’s list of behaviors. You can specify the first:, before:, or
after: keyword parameters in the call to add-behavior to respectively place the
behavior first in the list, or before or after another behavior. If you do not
specify a keyword, the behavior is placed last in the list.
Event Handling
Event Handling
slot next-handler,
init-value: #f;
end class;
Slot descriptions
identifier Identifies the event handler. Set this slot if you need to
specialize a method on a singleton event handler. Use the
identifier: keyword to specify the identifier; otherwise,
the slot is set to $null-identifier.
behavior-list Specifies the behaviors associated with the event handler.
Use the behavior-list: keyword to specify the initial list of
behaviors; otherwise, the list is empty. You can call
add-behavior and remove-behavior to change the contents
of this list. For more information about behaviors, see
“Behaviors and Event Handling” on page 254.
enabled? Specifies whether the event handler or its behaviors is
prepared to respond to events. By default, event handlers,
and thus their behaviors can respond to events. Call
enabled? to determine if the event handler or its behaviors
is prepared to respond to events.
next-handler Specifies the next event handler in the target chain. To
access this slot, call next-handler and next-handler-setter.
Initialization
The initialize method for <event-handler> objects sets the sets the next
handler. Its parameters are defined as follows:
Event Handling
Slot descriptions
command-queue Internal queue of commands which are waiting to be
executed. Not exported.
document-type-list A list of pairs of file types and document classes supported
by the application, such as ‘PICT’, and the document class
that supports the type. Initially the list is empty. Call
add-document-type to add to the list. To determine which
document class supports a document type call
get-document-class. The document-type-list slot is not
exported.
close-with-last-window?
Specifies whether the children of a context should be
closed when the last window associated with the context is
closed (#t) or whether they should remain open after the
Event Handling
Initialization
The initialize method for the <main-handler> object sets the target event
handler to itself. Its parameters are defined as follows:
Event Handling
Slot descriptions
identifier Identifies the behavior. Set this slot if you need to
specialize a method on a singleton behavior or if you wish
to place behaviors in an event handler’s list of behaviors
based on the position of this behavior in the list.
Initialization
No initialize method is defined for <behavior> objects.
Slot descriptions
identifier Identifies the event. Set this slot if you need to specialize a
method on a singleton event. Use the identifier: keyword
to specify the identifier; otherwise, the slot is set to
$null-identifier.
Event Handling
Initialization
No initialize method is defined for <event> objects.
Event Handling
Slot descriptions
event-what The kind of event. It corresponds to the what field in the
toolbox EventRecord data type.
event-time The elapsed ticks since system start up. It corresponds to
the when field in the toolbox EventRecord data type.
global-mouse The location of the cursor, in global coordinates, when the
event occurred. It corresponds to the where field in the
toolbox EventRecord data type.
message Additional information associated with the event. It
corresponds to the message field in the toolbox EventRecord
data type.
modifiers The state of the modifier keys and mouse button when the
event occurred. It corresponds to the modifier field in the
toolbox EventRecord data type. The state of commonly
tested keys are specified in the following slots:
shift-key? The state of the shift key. True (#t) indicates that it was
down when the event occurred.
option-key? The state of the option key. True (#t) indicates that it was
down when the event occurred.
command-key? The state of the command key. True (#t) indicates that it
was down when the event occurred.
control-key? The state of the control key. True (#t) indicates that it was
down when the event occurred.
Initialization
The initialize method for <toolbox-event> objects replaces the default slot
values with those in the specified event record. Its parameters are defined as
follows:
Event Handling
Slot descriptions
key-character Specifies which key is affected by a key-up or key-down
event.
Event Handling
Slot descriptions
convert-clipboard? Specifies whether the contents of the clipboard must be
converted and copied to a private scrap when a resume
event occurs and whether the clipboard must be filled
from a private scrap when a suspend event occurs. It is
true (#t) if the clipboard must be converted by copying to
and filling from a private scrap; otherwise it is false (#f) if
these actions are not necessary.
Event Handling
and mouse events. (For information about mouse event subclasses, see the next
section, beginning on page 273.) You do not need to define subclasses from the
<window-event> class or its subclasses, nor do you create objects from these
classes yourself.
Listing 11-15 shows the class definition for the <window-event> class.
Slot descriptions
event-window-ptr Specifies the window associated with the event. The
window is defined using the toolbox WindowRecord data
type. For information about the WindowRecord data type,
see the Window Manager chapter of Inside Macintosh:
Macintosh Toolbox Essentials.
Listing 11-16 shows the class definition for the <activate-event> class.
Slot descriptions
activate-it? Specifies whether the window should be activated (#t) or
deactivated (#f). The Framework sets this slot from the
toolbox event record when an event occurs. You may call
the slot’s getter method to determine whether the window
is being activated or deactivated.
Listing 11-17 shows the class definition for the <update-event> class.
Event Handling
Event Handling
Slot descriptions
local-mouse Specifies the location of the mouse pointer in the local
coordinates of a window or view.
part-code Specifies the part of the screen or window the mouse
pointer is over; for example, the menu bar or the content
area of a window. For information about the part codes,
see the codes returned by the toolbox FindWindow function
in the Window Manager chapter of Inside Macintosh:
Macintosh Toolbox Essentials.
Event Handling
setter: #f,
required-init-keyword: same-window:;
end class;
Slot descriptions
new-target Specifies the event handler to become the new target.
same-window? Specifies whether the window associated with the current
target in the event handling chain is the same as the new
target. The Framework sets this slot when the target
changes; for example, when the user clicks the mouse in a
different view. You may call the slot’s getter method to
determine whether the window changed as a result of
changing the target.
Slot descriptions
old-target Specifies the event handler that is no longer the target.
same-window? Specifies whether the window associated with the current
target in the event handling chain is the same as the new
target. The Framework sets this slot when the target
Event Handling
Event Handling
do-drag Internal. √
do-go-away Internal.
do-zoom Internal.
double-click? Determine if a mouse click is the second √
one in a sequence.
triple-click? Determine if a mouse click is the third one √
in a sequence.
Event Handling
Event Handling
make-toolbox Internal.
-event
create-menu Internal.
-event
cloneable Internal. √
-behaviors
clone-behavior Internal. √
-list
Event Handling
12 Menus
Contents
About Menus 283
Menus and Menu Items 283
Menu Event Handling 284
Menu Classes 285
Using Menu-Related Objects 287
Creating Menus and Menu Items 287
Setting Up Menus 288
Responding to Menu Events 290
Setting up the About Menu Item 292
Menu Class Reference 292
The <menu-element> Class 292
The <menu-item> Class 294
The <separator-item> Class 297
The <menu> Class 297
The <apple-menu> Class 300
The <menu-event> Class 301
Functions for Menus 302
Contents 281
282 Contents
C H A P T E R 1 2
Menus 12
The Framework sets up your application’s menu bar and adds the Apple
menu, the Help menu and the Application menu for you automatically. The
Framework provides you with the ability to
■ set up menus and menu items
■ install, access, and remove your own menus
■ add items to a menu
■ enable and disable menu items
■ handle menu events
This chapter describes the classes that the Framework provides for supporting
menus and events related to menus and the concepts for their use. The chapter
also shows you how to use objects from these classes to set up menus and
respond to menu events.
The Framework’s event handling system is used to set up menus and respond
to menu events. You should be familiar with event handling, as described in
the chapter “Introduction” on page 219. For general information about event
handlers and behaviors, see the chapter “Event Handling” on page 241.
About Menus 12
This section describes the concepts and classes related to menus. For general
information about Macintosh menus and the Menu Manager that the
Framework uses to implement them, see the Menu Manager chapter of Inside
Macintosh: Macintosh Toolbox Essentials.
Menus
Menu items are associated with event handlers. The Framework provides two
methods specialized on event handler, do-setup-menus and
behavior-setup-menus, in which you can enable and mark menu items. Thus, an
event handler, such as a document or view, or its behavior can enable menu
items when it is in the target chain. The <main-handler> object representing the
application or its behaviors can control when application-wide menu items,
such as New, Open, or Quit are available. For an example of how to set up
menus, see “Setting Up Menus” on page 288.
Entire menus can also be installed and removed using the same event handling
mechanism and methods (do-setup-menus and behavior-setup-menus) that
allow menu items can be enabled.
Note
The Framework maintains state information about menus
and menu items. The Framework only calls the Menu
Manager when it is necessary to synchronize its state with
the state of the Menu Manager, which reduces the number
of system calls. For example, do-setup-menus may be called
several times to change the state of menu items before an
event occurs that actually makes it necessary to display a
menu. The Framework brings the Menu Manager
up-to-date just before the menu is displayed. ◆
Menus
Menu Classes 12
Figure 12-1 shows the menu-related classes provided by the Framework.
Menus
Menus
Listing 12-1 shows how to create a File menu with the New, Close, and Quit
items. The menu is installed, however, the items are not yet enabled.
make(<menu>,
title: "File",
install: #t,
items: list(make(<menu-item>,
title: "New",
identifier: #"new",
command-key: 'N'),
make(<separator-item>),
make(<menu-item>,
title: "Close",
identifier: #"close",
command-key: 'W'),
Menus
make(<separator-item>),
make(<menu-item>,
title: "Quit",
identifier: #"quit",
command-key: 'Q')));
A title, event, and keyboard equivalent is defined for each menu item. The
Framework creates a <menu-item> object whose identifier is specified by the
identifier: keyword.
Listing 12-2 shows how to create menu items by specifying an actual event
object using the event: keyword instead of the identifier.
Setting Up Menus 12
When the Framework dispatches a menu event, it also updates the menu bar. It
clears its internal menu state and calls do-setup-menus for each event handler in
the target chain. It also calls behavior-setup-menus for each behavior of an event
handler before calling the event handler’s do-setup-menus.
Menus
Note
The Framework does not actually call the Menu Manager
routines to set up menus until it is necessary to display a
menu. ◆
You provide specializations of do-setup-menus and behavior-setup-menus to
reenable menu items and to mark reenabled items. Listing 12-3 shows the
menu items that are enabled when a behavior is added to an event handler.
enable-item(#"new");
enable-item(#"float-test");
enable-item(#"dialog-test");
enable-item(#"grid-test");
if (*has-quickdraw-gx*)
enable-item(#"gx-test");
end if;
enable-item(#"benchmark");
end method;
Listing 12-4 shows the menu items that are enabled and marked when an
<O-tile-view> object is in the target chain.
Menus
enable-item(#"tile-type");
mark-item(#"tile-type", tile-type: view.tile-type);
...
enable-item(#"tile-show-dual");
mark-item(#"tile-show-dual", mark: view.show-dual);
end method;
The menu items to be enabled or marked are identified by the menu event; not
the menu item. If several menu items are associated with an event, all of them
are enabled or marked.
The actual way that events are enabled or marked is determined by
specializations of do-enabling and do-marking methods. These methods are
called by enable-item and mark-item, respectively. Listing 12-5 shows a
specialization of the do-marking method on <tile-type-event> objects. This
specialization of do-marking only marks tiles if the type of the tile matches the
type specified in the call to mark-item in Listing 12-4.
The technique of specializing the do-marking method rather than the mark-item
method hides much of the logic that would be required to test each menu item
against a slot in its event before determining whether to mark the item.
Menus
with an event handler. These methods specify the application logic to execute
when the event is dispatched.
Listing 12-6 shows a do-event method that is specialized on an event handler
and on a singleton identifier of a menu event.
view.show-dual := ~ view.show-dual;
invalidate-all(view);
end method;
If you specialize a menu event by its class, it may not be necessary to specialize
on its identifier. Listing 12-7 shows the do-event method that responds to any
tile-type menu event.
Menus
event :: <menu-event>,
id == #"new")
ignore(behavior, next-behaviors, event, id);
post-command(main-handler,
make(<new-window-command>,context: main-handler));
end method;
Menus
// private
// use title, title-setter, enabled? and enabled?-setter to access
// these
slot %title :: <string>,
init-value: "",
init-keyword: title:;
end class;
Slot descriptions
menu-bar Specifies the menu bar to which a menu or menu item is
attached. The Framework sets up the association with the
application’s menu bar for you and stores the association
in the *menu-bar* variable. If you want to associate a menu
or item with another menu bar, you can use the menu-bar:
keyword; otherwise menus and elements are associated
with the menu bar represented by the *menu-bar* variable.
The menu-bar slot is not exported. Changing the association
of this slot with the *menu-bar* variable requires modifying
the Framework.
parent-menu Specifies the menu associated with a menu item or the
parent menu item associated with a submenu in a
hierarchial menu. Typically, the parent menu is the <menu>
object to which a list of items are specified in the make
Menus
Initialization
No initialize method is defined for <menu-element> objects.
Menus
// private
// use generic functions event, mark, icon, style, command-key,
// and their setters to access these.
slot %event :: <object>,
init-value: #f;
slot %command-key,
init-value: #f,
init-keyword: command-key:;
end class;
Slot descriptions
toolbox-mark Internal; not exported.
%event Specifies the event object associated with the menu item.
Use the event: or identifier: keywords to specify the
event object, as described under “Initialization;” otherwise,
no event object is specified when you create the menu
item. You can call event and event-setter, respectively, to
get or set the value of this slot. The %event slot is not
exported.
Menus
%mark Specifies the mark to the left of the title; for example, a
check mark. Use the mark: keyword to specify the mark;
otherwise, no mark is present when you create the menu
item. You can call mark and mark-setter, respectively, to get
or set the value of this slot. The %mark slot is not exported.
%icon Specifies the icon associated with the menu item. Use the
icon: keyword to specify the icon; otherwise, no icon is
specified. You can call icon and icon-setter, respectively,
to get or set the value of this slot. The %icon slot is not
exported.
%style Specifies the style associated with the menu item. Use the
style: keyword to specify the style; otherwise, the style is
Plain. You can call style and style-setter, respectively, to
get or set the value of this slot. The %style slot is not
exported.
%command-key Specifies the keyboard equivalent for the menu item. Use
the command-key: keyword to specify the keyboard
equivalent; otherwise, no keyboard equivalent is defined.
You can call command-key and command-key-setter,
respectively, to get or set the value of this slot. . The
%command-key slot is not exported.
Initialization
The initialize method for <menu-item> objects sets up the association between
the <menu-item> object and a <menu-event> object. In your make function, use the
event: keyword if the <menu-event> object already exists. Use the identifier:
keyword if you want to make an object that is subclassed from <menu-event>.
The initialize method’s parameters defined as follows:
Menus
Slot descriptions
%title Internal; not exported. Do not change the title of a
<separator-item> object.
Initialization
No initialize method is specified for <separator-item> objects.
Menus
slot id :: <integer>;
Slot descriptions
items Specifies the menu items associated with the menu. For
information about menu items, see “The <menu-item>
Class” on page 294. To add a menu item to a menu, call
add-menu-item. Only the getter method is defined for this
slot.
Menus
Initialization
The initialize method for <menu> objects sets up a <menu> object and associates
menu items with the menu and, optionally, installs the menu in the menu bar.
The <menu> object can be created from a resource. The initialize method’s
parameters are defined as follows:
Menus
If you specify true (#t) for the install: keyword, the menu is installed in the
menu bar immediately. If you do not specify the install: keyword or if you
specify false (#f) for it, you must call install-menu when you want to add the
menu to the menu bar.
Slot descriptions
about-item Specifies the object that corresponds to the About menu
item. You can set the slots of the <menu-item> object stored
in the about-item slot. For more information about
<menu-item> objects, see “The <menu-item> Class” on
page 294.
last-user-item Internal; not exported.
Initialization
The initialize method for the <apple-menu> object sets up the Apple menu and
the object that represents the About menu item. The initialize method’s
parameters are defined as follows:
Menus
You can define subclasses of the <menu-event> class. For example, you may
want your event to include additional slots. If you subclass <menu-event>, you
must create an object of your subclass and specify it as the event corresponding
to a menu item. For an example of how to define a subclass of <menu-event>, see
“Responding to Menu Events” on page 290.
Listing 12-14 shows the <menu-event> class definition.
Slot descriptions
menu-item Specifies the menu items associated with this event. Use
the menu-item: keyword to specify a menu item; otherwise,
the event is never dispatched.
Initialization
The initialize method for <menu-event> objects associates a menu event with a
menu item. The initialize method’s parameters are defined as follows:
Menus
Menus
Menus
13 Graphics
Contents
About Graphics 307
About Graphics Ports and Buffers 309
About Graphics Caches 310
About Frames 310
Frame Coordinate Systems 313
About Regions 314
About Text Styles 315
About Color 316
Using Graphics Objects 317
Changing an Object’s Location and Extent 317
Manipulating Regions and Rectangles 317
Defining Text Styles 318
Defining Colors 318
Graphics Objects Reference 319
The <frame> Class 319
Graphics Ports Classes 320
Text Style Classes 322
The QuickDraw Region Class 324
RGB Color Class 324
Graphics-Related Functions 325
Contents 305
306 Contents
C H A P T E R 1 3
Graphics 13
Graphics classes provide support for drawing in views. This chapter describes
classes that handle graphics, including those that represent
■ frames, which define the location and extent of a window, view, or graphics
port
■ graphics ports, which define a drawing environment
■ graphics buffers, which are associated with graphics ports
■ graphics caches, in which clipping and focus information reside
■ color and text style characteristics
■ specific QuickDraw implementations of ports, graphics systems, caches,
buffers, regions, and styles
About Graphics 13
Graphics concepts include topics that relate to the mechanism that manages
views and windows so that they can be displayed onscreen or manipulated
offscreen, and topics that related to geometric areas. The remainder of this
section introduces the graphics mechanism. For information about the
geometric aspects of graphics, see “About Frames” on page 310 and “About
Regions” on page 314.
The graphics mechanism consists of several objects that operate within a
graphics system, such as QuickDraw. The Framework provides one graphics
system that supports both QuickDraw and QuickDraw graphics worlds
(GWorlds). Figure 13-1 shows the mechanism.
Graphics
Graphics system
Graphics Graphics
world cache
Root
view
Graphics
cache
Graphics Graphics
port cache
Window View
Graphics
cache
Graphics
A graphics cache translates information about a view into a form that can be
handled by a graphics port. For example, a graphics cache can store
information about how to draw the view into the port, clipping and translation
information, and other information that is relevant to a graphics port. A view
has one graphics cache for each graphics port that it can draw into. Thus, if a
view can appear in several windows, it has a cache for each of them.
In general, you need not be concerned with graphics ports and graphics caches.
When you create a window, the Framework creates a graphics port for you. [In
the future, you may need to specify the kind of graphics port.] When you add a
view to a window, or a subview to a view that is already associated with a
window, the Framework automatically sets up a cache to match the
requirements of the window’s graphics port.
Objects created from the classes in Figure 13-2 represent the following kinds of
graphic systems:
<graphics-port> Represents an abstract class for a graphics port.
<qd-graphics-port> Represents a QuickDraw graphics port.
<qd-graphics-buffer> Represents a QuickDraw graphics world, which can
be used for offscreen drawing.
Graphics
About Frames 13
Frames are inherited by classes whose objects need to maintain their location
and extent in relation to some other object or on a screen or within an offscreen
buffer. These classes are shown in Figure 13-3.
The classes that inherit from the <frame> class are identified as follows:
<graphics-port> Represents a graphics cache from which you may
create a subclass.
<view> Represents an area within a window typically used
for drawing.
<window> Represents a Window Manager window.
Note
Windows and views are also event handlers, thus they also
inherit (directly or indirectly) from the <event-handler>
class. ◆
Graphics
The <frame> class allows an area to be defined by the objects of its subclasses.
Figure 13-4 shows the area defined by a window and the window’s root view.
Figure 13-4 Location and extent for windows and root views
Location. v
Location. h
Window
Root view
Extert.v + location.v
Extert.h + location.h
The location is a point that identifies the top-left corner of the area. Points are
defined by their vertical (v) and horizontal (h) slots.
The window’s location defines the top-left corner of the content area of the
window in relation to the top-left corner of the main monitor. The root view’s
location defines its location in relation to the window’s location. Because, the
Framework always defines the root view to be the same area as the window,
the root view’s location is always $zero-point, which is point (0,0), meaning
that if the window moves, its root view also moves to the same location.
The location of a subview is relative to its superview. Thus, if a subview is
defined with its v slot as 20 and its h slot as 30, the subview’s location is 20
pixels down and thirty pixel’s to the right of its superview’s location. If the
superview is the root view, then the subview is 20 pixels down and thirty
pixel’s to the right of the top-left corner of the window’s content area.
Graphics
The extent is a point that identifies the size of the area. The botton-right corner
of an area is a point representing the sum of the respective h and v slots in the
object’s location and extent. The root view’s extent is the same as the window’s
extent, as shown in Figure 13-4.
A <frame> object also provides a slot that represents the translation between a
scroller and its subviews. Because a view in a window is relative to its
superview, its location does not change. If a view is scrolled in a window,
however, the relation between that view and the scroller view can change,
allowing different parts of the view to show through the scroller. Figure 13-5
shows a scroller view with one subview.
Location.v
Location.h
View
Translation.v
Translation.h
Scroller
Extert.v + location.v
Extert.h + location.h
Graphics
The translation is a point that defines how the location would appear to
change if the subview is scrolled in the window. For example, if the view is
scrolled down to show more of its bottom content, which means that the view
moves up in relation to the scroller, the vertical translation increases to
accommodate the greater apparent distance between the location of the
subview and the location of the scroller view. The translation is handled by the
Framework for you when you call appropriate methods, such as local-bounds
to determine the bounding rectangle for a view. If you access the location and
extent slots of a scroller view’s subview directly, you may need to handle the
translation yourself.
Graphics
Screen
(0,0) Root coordinates
100 ?
View B
About Regions 13
Regions are classes that represent an area. The Framework provides the
<region> abstract class and two subclasses:
Graphics
You can define subclasses of the <region> class and create objects from them. If
you use the QuickDraw graphics system, you typically create objects from the
<qd-region> and <rect> classes. Figure 13-7 shows the region classes.
Objects created from the classes in Figure 13-7 represent the following kinds of
geometric structures:
<region> Represents an abstract region.
<qd-region> Represents a region associated with a QuickDraw
region handle.
<rect> Represents a rectangle.
Objects created from the classes in Figure 13-8 represent the following kinds of
text styles:
Graphics
About Color 13
The RGB color scheme is used to represent color information. You create objects
from the <rgb-color> class. The Framework provides the following color
constants for RGB colors, as shown in Table 13-2:
Color Description
$no-color No color; used for “transparent” drawing.
$black-color Black
$white-color White
$red-color Red
$green-color Green
$blue-color Blue
Graphics
Note
The syntax view.super-bounds is equivalent to
super-bounds(view). ◆
Graphics
Defining Colors 13
RGB colors specify a red, green, and blue component, each of which can have a
value from 0 to 65535, inclusive. If each component is 0, the color is black. If a
component is 65535, it is red, green, or blue, depending on the component. If all
components are 65535, the color is white.
The Framework provides color constants for red, green, blue, white, and black.
It also provides the constant $no-color; when used, no drawing occurs. For
information about color constants, see “About Color” on page 316.
Graphics
The Framework provides an rgb-color method that you can use to create color
objects. Listing 13-4 shows the definition of a color constant for gray.
Slot descriptions
location The top-left corner of the frame.
Graphics
Initialization
No initialize method is defined for <frame> objects.
Graphics
init-value: #f,
init-keyword: is-window:;
end class;
Slot descriptions
graf-port The Window Manager GrafPort data structure.
owning-window The window associated with the graphics port.
port-is-window? Specifies whether the graphics port associated with a
window (#t), or if it is associated with an offscreen buffer
(#f).
Initialization
No initialize method is defined for <qd-graphics-port> objects.
Slot descriptions
world A color GrafPort.
Graphics
Initialization
The initialize method for <qd-graphics-buffer> objects sets up the toolbox
data structures and calls NewGWorld. For information about the NewGWorld
function, see Inside Macintosh: Imaging With QuickDraw. The initialize
method’s parameters are defined as follows:
Graphics
Slot descriptions
font The font name, such as Geneva or Chicago.
font-number The font number.
font-size The font size.
font-style The font style.
Initialization
No initialize method is defined for <text-style> objects. The initialize
method for <qd-text-style> objects determines the font name from the font
number if a number is specified and allows you to specify the style, The
method’s parameters are defined follows:
Graphics
Slot descriptions
rgn-handle A handle to a QuickDraw region.
Initialization
The initialize method for <qd-region> objects registers the region handle for
garbage collection when the region is no longer in use. The initialize
method’s parameters are defined as follows:
Graphics
Slot descriptions
red The red component of an RGB color. Use the red: keyword
to define the component. You cannot change the
component after it has been is defined.
green The green component of an RGB color. Use the green:
keyword to define the component. You cannot change the
component after it has been is defined.
blue The blue component of an RGB color. Use the blue:
keyword to define the component. You cannot change the
component after it has been is defined.
Initialization
The initialize method is defined for color objects.
Graphics-Related Functions 13
Graphics-related functions are grouped in the following categories:
■ functions that operate on frames to handle conversion between coordinate
systems
■ functions for determining or setting the characteristics of graphics ports
Graphics
Graphics
Table 13-5 identifies the functions for manipulating the buffer associated with a
graphics port.
Graphics
Graphics
Graphics
Graphics
Graphics
14 Views
Contents
About Views and Supporting Classes 335
View Hierarchies 337
Adorners 339
View Determiners 341
Drawing in Views 342
Highlighting 343
Cursor Manipulation 344
Using View Objects 345
Defining a View Class 345
Setting Up Views 346
Setting the Target View 347
Drawing in Views 348
Setting Up a View for a Graphics World 348
Drawing With Buffered Views 349
Setting Up Adorners 350
Implementing a View Determiner 352
View Objects Reference 354
The <view> Class 355
Adorner Classes 360
View Determiner Classes 362
View-Related Functions 364
Functions for Graphics Support 367
Functions for Adorners 368
Functions for View Determiners 369
Contents 333
334 Contents
C H A P T E R 1 4
Views 14
Views have two major purposes in the Framework—they handle drawing and
they can respond to events. This chapter describes view classes and classes that
support them:
■ adorners, which allow borders or other adornments to be drawn as part of a
view
■ determiners, which specify rules for how a view can be associated with its
superview.
For information about text views, see “Text Views” on page 373. For
information about grid and list views, see “Grid and List Views” on page 387.
Note
The Framework provides several kinds of views to
implement dialogs. These classes represent controls,
groupings of controls (called clusters), static text, and
icons. These classes are discussed in the chapter “Dialogs
and Controls” on page 419. ◆
Figure 14-1 shows the subclasses of the <view> class.
Views
Objects created from the classes in Figure 14-1 represent the following kinds of
views:
<cluster> Represents a group of views associated with a
control. For information about the <cluster> class,
see page 437.
<control> Represents a control. For information about the
<control> class, see page 440.
<grid-view> Represents a view that is divided into cells. For
information about the <grid-view> class, see
page 391.
<list-view> Represents a view that is a single column of cells.
For information about the <list-view> class, see
page 394.
<text-grid-view> Represents a grid view that handles editable text.
For information about the <text-grid-view> class,
see page 395.
<grow-icon> Represents a size box in a window. For information
about the <grow-icon> class, see page 414.
Views
View Hierarchies 14
Views are organized into hierarchies. A view hierarchy establishes the
relationship between the views within it and defines the order in which events
can be handled. When you create a view, you can specify its subviews. You can
also add subviews to a view after it is created.
When you create a window, the Framework creates a view that is associated
with the window. This view is the window’s root view. Other views within the
window must descend directly or indirectly from the root view.
Typically, you create a view that displays your content, called a content view,
as a direct or indirect subview of the root view. If the window does not allow
scrolling, you can make the view a subview of the root view directly. Consider
the dialog box in Figure 14-2.
Views
The view hierarchy consists of the root view and two subviews, one that
contains static text and one that represents a button. Figure 14-3 shows the
view hierarchy.
Root view
Both the static text and button views represent the content of the dialog and are
direct subviews of the root view. For information about dialogs, see the chapter
“Dialogs and Controls” on page 419.
Figure 14-4 shows views that support scrolling in a window.
Views
Content view
Root view
Scroller
Scroll bars
Figure 14-5 shows the view hierarchy for the scrolling window.
Root view
Scroller
Scroll bars
Content view
Adorners 14
Adorners represent reusable modifications to views, which are drawn when
the view itself is drawn. For example, the Framework provides an adorner,
Views
called a frame adorner, that draws an outline just inside the border of a view.
You can add a frame adorner to any view that needs to be outlined without
having to create a subclass of the view.
Figure 14-6 shows the subclasses of the <adorner> class.
Objects created from the classes in Figure 14-1 represent the following kinds of
views:
<black-background-adorner>
Provides a a black background behind a view. For
information about the <black-background-adorner>
class, see “Adorner Classes” on page 360.
<default-button-adorner> Provides a border associated with a default button
control. For information about the
<default-button-adorner> class, see “The
<default-button-adorner> Class” on page 455.
<draw-adorner> Specifies drawing the view itself. For information
about the <draw-adorner> class, see “Drawing in
Views” on page 342.
<frame-adorner> Provides a frame that outlines a view. For
information about the <frame-adorner> class, see
“Adorner Classes” on page 360.
Views
View Determiners 14
View determiners represent the rules for changing a view when its superview
changes. The Framework provides view determiner classes that represent
common rules, such as keeping view within a superview’s bounds or
maintaining a view’s size in proportion to its superview’s size. The Framework
also provides view determiner classes that handle resizing of scroll bars and
moving a window’s grow box.
Figure 14-7 shows the subclasses of the <view-determiner> class.
Objects created from the classes in Figure 14-1 represent the following kinds of
views:
<grow-icon-determiner> Represents the rules for moving a <grow-icon> object
when its superview changes. For information about
the <grow-icon-determiner> class, seepage 414.
Views
Drawing in Views 14
The Framework draws the contents of all views when an update event occurs.
The draw method associated with the view defines its contents. For example,
Views
the draw method could contain code to draw a series of shapes, such as lines or
rectangles, pictures, or any other visual content.
The Framework only draws the visible part of each view that has been
invalidated, which meaning the part that is in the window’s update region. The
Framework provides methods that allow you to invalidate or validate all or
part of a view.
Drawing starts with the root view. After its contents are drawn, the contents of
its subviews are drawn. If a subview also has subviews, they are also drawn
before drawing the next subview of the root, and so on. Thus, drawing of
subviews proceeds until the deepest subview of a view has been drawn and all
subviews at the same level in a branch of a hierarchy are drawn before drawing
for the next branch starts.
For each view, adorners control the order in which the adorner and the view
itself is drawn. The Framework draws adorners in the order they occur within
the view’s list of adorners. The view always contains at least two adorners, a
draw adorner, which is a <draw-adorner> object and a highlight adorner, which
is a <hilite-adorner> object. The draw adorner causes the view’s draw method
to execute, thus drawing the contents of the view. The hilite adorner causes the
view to be highlighted (see the following section for more information).
Note
The Framework provides ways for you to draw without
waiting for an update event by calling redraw or
redraw-all. ◆
Highlighting 14
The Framework changes the highlighting for views and adorners after they are
drawn by calling the hilite method of the view or adorner. If you do not
define a hilite method, nothing happens when the Framework attempts to
highlight the view or adorner.
Higlighting for views is performed in the reverse order of drawing. Thus,
highlighting for a subview is performed before highlighting for its superview.
In other words, drawing occurs on the way down the view hierarchy;
highlighting occurs on the way back up the hierarchy.
The order in which a view and its adorners are highlighted depend on the
specific transition between highlight states (described below) and the order
Views
that adorners are placed in the view’s list of adorners. The Framework either
highlights the adorners in a forward order or in reverse order as they are found
in the list. When the highlight adorner is found, the view itself is highlighted.
The order of iteration, depends on the current highlight state for a view and the
new state. The highlight states are either on, off, or dim. Table 14-1 shows the
state transitions and the iteration order.
New State:
Off Dim On
Current State:
— Forward Forward
Off
Reverse — Forward
Dim
Reverse Reverse —
On
Cursor Manipulation 14
The Framework provides a mechanism that allows each view to set the kind of
cursor. The kind of cursor can also be constrained while in a view by specifying
a cursor region that has less area than the view itself.
Initially, the cursor region is defined as the sleep area, which is the combined
area of all screens less the area of active windows. The Framework restricts the
cursor region of a view within a window to be the area of the view less the area
of its subviews. This has the effect of allowing the cursor to be controlled by the
deepest subview over which the cursor is positioned.
The normal event-handling protocol determines which view will set the cursor.
The Framework updates the mouse position in response to mouse-moved
events. When a mouse-moved event occurs, the behaviors of the target event
handler have the opportunity to set the cursor, followed by the event handler
(typically a view) itself. Once the cursor is set, there is no need to pass the event
up the target chain. If the cursor is not set, the event is passed up the chain and
other event handlers and their behaviors can set the cursor. If the event reaches
Views
the main handler, the cursor is changed to an arrow cursor and the sleep region
is reset to the area for all screens less the area of active windows.
The Framework provides the following cursors, as shown in Table 14-2:
Cursor Description
$arrow-cursor Arrow cursor
$iBeamCursor I-beam cursor
Most of these cursors are defined as resources in the Framework’s library. You
can set the cursor in a view attached to a behavior or by the view itself. By
default, the cursor is an arrow cursor.
Views
You can then create objects of the <my-view> class after you have a document
object. For example, the following example shows one way to create the view:
Note
Always define an extent for your view; otherwise its size is
$zero-point, which will never be visible. ◆
Setting Up Views 14
You typically set up views when you create a window. If the window is
associated with a document, the window and its views are created in the
document’s make-windows method.
After you define a view class, you can create an object from it and add it as a
subview to another view. If you want to add the view to a window, you add
the view as a subview of the root view.
If you want to associate the view with a new window, you can follow this
procedure:
1. Create your view.
2. Create your window.
3. Add your view as a subview of the window’s root view.
Listing 14-2 shows an example.
Views
has-go-away: #t,
moveable-modal: #t,
title: "Untitled",
target-view: my-content);
add-sub-view(the-window.root-view, my-content);
The make-scrolling-window method adds each view in a list of views to the root
view.
If you want to add a view to an existing window, you must be able to access
the window object. For example, if you know any view in the window, you call
get-window and specify the view as the parameter. For more information about
windows, see “About Windows” on page 401.
Views
Drawing in Views 14
The draw method specifies how to draw the content of the view. Listing 14-3
shows a draw method that draws the contents of a document’s data as
rectangles.
When you use a graphics buffer, you are responsible for creating it, initializing
it, and disposing of it when it is no longer needed. Listing 14-4 shows an
example of creating a graphics buffer and the view that uses it.
Views
dispose(buffer);
Note
Although the Dylan language will dispose of an object
when it is no longer used, you may wish to dispose of
large objects yourself earlier to guarantee that other large
objects will not be created before memory for unneeded
ones is released. ◆
with-focused-view (buffered-view)
// your QuickDraw drawing calls go here
end;
Views
Your draw method should take the contents of the buffer and render it onscreen.
The Framework provides the draw-buffer method to handle this task, as shown
in Listing 14-7.
Note
The draw-buffer method is equivalent to CopyBits in the
Macintosh Toolbox. ◆
Setting Up Adorners 14
Adorners are reusable objects that can be attached to a view. When the view is
drawn, the view’s adorners are also drawn. To set up an adorner, you must
follow these steps:
1. Define a subclass of the adorner class.
2. Define an adorner-draw method that specifies the drawing actions for the
adorner.
3. Optionally, define one or more adorner-hilite methods to specify how the
adorner is to be highlighted for each state transition.
4. Add the adorner to any views.
Listing 14-8 shows the definition of an adorner subclass that draws a border
around the view to which it is attached so that the adorner’s view is clearly
visible within the view’s superview. The area outside the view but inside its
superview is drawn in the color specified by the adorner’s color slot.
Views
Listing 14-9 shows the adorner-draw method that specifies the drawing actions.
set-fore-color(adorner.color);
paint-region(region);
dispose(region);
set-fore-color(view.fore-color);
end method;
Views
ignore(adorner);
if (old-hilite ~= new-hilite)
hilite(view, hilite-region, old-hilite, new-hilite);
end if;
end method;
You can add and remove an adorner as needed. Listing 14-11 shows an
example of creating and adding the adorner to the scroller view of a scrolling
window.
You can control the order in which adorners are added to the view’s list of
adorner by using the first:, before:, and after: keywords. If you do not
specify one of these keywords, the adorner is added last. For example, if you
want the adorner to draw before the view is drawn, you could specify before:
$draw-adorner when you call add-adorner. For information about the order in
which a view and its adorners are drawn, see “Drawing in Views” on page 342.
Views
To implement your own view determiner, you must define a subclass of the
<view-determiner> class and define one or more methods whose view
determiner parameter specialize on your subclass. These methods are defined
as follows:
Function Specialize to
super-view-extent Specify the actions to take when the extent of the
-changed view’s superview changes.
sub-view-extent Specify the actions to take when the extent of a
-changed view’s subview changes.
super-view-location Specify the actions to take when the location of
-changed the view’s superview changes.
sub-view-location Specify the actions to take when the location of a
-changed view’s subview changes.
Views
view.location := point(
max(0, floor/((super-view.extent.h - view.extent.h), 2)),
max(0, floor/((super-view.extent.v - view.extent.v), 2)));
end method;
After you define the class you can add your view determiner to a view by
using the determiner: keyword as shown in Listing 14-12, or you can assign it
to the view, as in the following statement:
view.determiner := make(<center-in-super-determiner>);
Views
Views
// private
// use generic functions super-view, visible?
// and their setters to access these slots.
slot %super-view,
init-value: #f,
Views
init-keyword: super-view:;
slot graphics-port,
init-value: #f,
init-keyword: graphics-port:;
end class;
Slot descriptions
visible-bounds The location and extent of the visible part of the view. You
can determine the visible bounds by calling
visible-bounds. If you only need to know if the view is
visible, call visible?. To set this slot, you must call
compute-visible-bounds. Typically, you do not need to set
the value of this slot; the Framework does it for you.
sub-views A list of views that are directly subordinate to this view in
the view hierarchy. Use the sub-views: keyword to specify
the list; otherwise, the list is empty. The Framework
provides functions that allow you to manipulate this list.
They are add-sub-view, find-sub-view, and remove-sub-view.
adorner-list A list of adorners that draw before the view is drawn. By
default, the Framework adds the drawing adorner and the
highlight adorner (see “Drawing in Views” on page 342) to
the list for you. To add an adorner to the list, call
add-adorner. To remove an adorner, call remove-adorner.
Views
Views
Views
view-to-port-offset
The translation between local coordinates and root
coordinates.
clip-region The clipping region that specifies the visible part of the
view.
Initialization
The initialize method for <view> objects allows you to specify subviews of a
view. The initialize method’s parameters are defined as follows:
Adorner Classes 14
The <adorner> class is a class that specifies items to draw along with the view
itself. You do not create objects directly from the <adorner> class, rather you
create subclasses and create objects from the subclasses. You may also create
objects from subclasses provided by the Framework. For example, if you want
to outline your view, you can create a <frame-adorner> object and add it to the
list of adorners for the view. The frame is drawn before the view. For an
example of setting up an adorner and adding it to a view, see “Setting Up
Adorners” on page 350.
Listing 14-16 shows the class definition for the <adorner> class and subclasses
provided by the Framework. The subclasses are <frame-adorner>,
<black-background-adorner>, <draw-adorner>, and <hilite-adorner>.
Views
Slot descriptions
identifier Identifies the adorner. Set this slot if you need to find or
remove the adorner or add it relative to some other
adorner. Use the identifier: keyword to specify the
identifier; otherwise, the slot is set to $null-identifier.
Views
Initialization
No initialize method is defined for adorner objects.
Views
Slot descriptions
identifier Identifies the view determiner. Set this slot if you need to
specialize a method on a specific view determiner. Use the
identifier: keyword to specify the identifier; otherwise,
the slot is set to $null-identifier.
Initialization
No initialize method is defined for view determiner objects.
Views
View-Related Functions 14
Table 14-3 shows the functions you can use with views.
Views
get-default Internal.
-cursor-region
get-graphics Internal.
-cache
add-graphics Internal.
-cache
remove-graphics Internal.
-cache
notifiy-super-view Internal.
-location-changed
notify-sub-view-locatio Internal.
n-changed
notifiy-super-view-exte Internal.
nt-changed
Views
prepare-to-draw Internal.
-region
prepare-to-draw Internal.
done-drawing Internal.
-region
done-drawing Internal.
invalidate Invalidate the specified part of a
view.
invalidate-all Invalidate the visible part of a view.
validate Validate the specified part of a view
validate-all Validate the visible part of a view. √
redraw Immediately redraw the specified √
part of a view.
redraw-all Immediately redraw the view. √
compute-visible-bounds Internal. Use the visible-bounds slot.
activate Internal.
set-target Scroll the view so it is visible in the √ √
-selection window.
adjust-extent Change the extent to allow for a √ √
change in the view’s content.
Views
Views
Views
Views
15 Text Views
Contents
About Text View Classes 373
Using Text View Objects 374
Creating a Text View 374
Getting and Setting Font Styles 374
Growing a Text View 375
Text View Objects Reference 375
The <text-view> Class 375
The <edit-text> Class 378
The <number-text> Class 379
Text View Functions 381
Contents 371
372 Contents
C H A P T E R 1 5
Text Views 15
Text views are views that use the Macintosh TextEdit facility to display and
manipulate text. TextEdit, and thus the Framework, provide the following
capabilities:
■ entering new text
■ deleting characters that are backspaced over
■ translating mouse activity into text selection
■ replacing or deleting text
The Framework also provides undoable and redoable commands, supports cut,
copy, and paste of text to the clipboard, and scripting.
Objects created from the classes in Figure 15-1 represent the following kinds of
views:
<text-view> Represents a view that supports TextEdit operations.
<edit-text> Represents a view that sets up and highlights the
text in a view. It is primarily intended for use in
dialog boxes.
Text Views
Text Views
The toggle: #t keyword specifies that, if the selection is already set, it is unset.
Note
If the toggle: keyword is false (#f), the style would remain
set if it is already set. ◆
Text Views
end class;
Slot descriptions
te-handle A handle to a Text Edit record. You can use the getter and
setter to access this slot.
typing-command A command that contains the current text.
word-wrap? Specifies whether you want the text to wrap without
breaking a word across lines (#t) or whether a word may
start and end on different lines (#f). Use the word-wrap:
keyword to specify the value; otherwise, the value is true
Text Views
(#t), meaning that words are not split between lines. You
can use the getter to access this slot.
view-only? Specifies whether the text can only be viewed(#t) or
whether the text is also editable(#f). Use the view-only:
keyword to specify the value; otherwise, the value is
false(#f), meaning that the text in the view can be changed.
use-styles? Specifies whether the text can have multiple styles (#t) or
whether the text can have only a single style (#f). Use the
use-styles: keyword to specify the value; otherwise, the
value is false(#f), meaning that the text in the view is
monostyled. You can use the getter and setter to access this
slot.
max-text-length The maximum length for text within the view. Use the
max-text-length: keyword to specify the value; otherwise,
the value is 32,767. You can use the getter and setter to
access this slot.
record-editing? Specifies whether adding or changing the text is recorded
for Apple events(#t) or whether the text is not
recorded(#f). By default, the value is true(#t), meaning
that changes to the text are recorded. You can use the
getter and setter to access this slot.
wants-to-be-target?
Specifies whether or not the view can become the target if
the user tabs into the view. By default, the value is true (#t)
for text views. You can use the getter and setter to access
this slot. For more information about tabbing behavior, see
“Adding a Tabbing Behavior” on page 432.
inset A rectangle that defines the inset for the view. Use the
inset: keyword to specify the inset; otherwise, the top,
left, bottom, and right coordinates for the rectangle are 2,
meaning a 2-pixel inset on each side. You can use the getter
and setter to access this slot.
Initialization
The initialize method for <text-view> objects initializes a Macintosh TextEdit
record and allows you to specify the initial text and style for text in the view.
The initialize method’s parameters are defined as follows:
Text Views
Slot descriptions
record-editing? Specifies whether adding or changing the text is recorded
for Apple events(#t) or whether the text is not
recorded(#f). By default, the value is false (#f), meaning
that changes to the text are not recorded. You can use the
getter and setter to access this slot.
Text Views
Initialization
The initialize method for <edit-text> objects allows you to specify the initial
text and whether you want to filter characters used to control the operation of a
dialog box. The initialize method’s parameters are defined as follows:
Text Views
Slot descriptions
min-value The minimum value. Use the min: keyword to specify the
value; otherwise, the slot is set to 0.
max-value The maximum value. Use the max: keyword to specify the
value; otherwise, the slot is set to 1000000.
Initialization
The initialize method for <number-text> objects allows you to specify the
initial value, which is right-justfied in the view. The initialize method’s
parameters are defined as follows:
Text Views
Text Views
Text Views
Text Views
Contents
About Grid and List Views 387
Grid and List View Classes 387
Grid View Behaviors 388
Using Grid and List View Objects 388
Setting Up Grid and List Views 389
Drawing in Views 389
Selecting Cells 390
Highlighting Cells in a View 390
Handling Variable Column Widths 390
Handling Variable Row Heights 391
Grid and List View Objects Reference 391
The <grid-view> Class 391
The <text-grid-view> Class 394
The <list-view> Class 394
The <text-list-view> Class 395
The <grid-select-behavior> Class 396
The <grid-arrow-key-behavior> Class 396
Grid and List View Related Functions 397
Contents 385
386 Contents
C H A P T E R 1 6
The Framework provides a grid view class that represents rows and columns of
cells, such as those contained in a spreadsheet, and subclasses to handle lists
(one-column grids) and text within grids or lists.
Objects created from the classes in Figure 16-1 represent the following kinds of
views:
<grid-view> Represents a view that is divided into cells.
<text-grid-view> Represents a grid view whose cells display text.
<list-view> Represents a view that is a single column of cells.
<text-list-view> Represents a list view whose cells display text.
The behaviors added to the grid view allow automatic selection of a cell by
clicking the mouse and moving the arrow key. For more information about
selecting cells, see “Selecting Cells” on page 390.
Drawing in Views 16
The draw method for a grid view calls the draw-cell method for each cell in the
view. You can specialize the draw-cell method on the view, the row, or the
column, or on some combination of these parameters.
With the exception of the <text-grid-view> objects, if a cell is not specific to the
parameters of a draw-cell method that you provide, such as its row or column
not being listed as a specialized parameter, the contents of the cell is not drawn.
The draw method for a list view calls the draw-item method for each item in the
list. The draw-item method, in turn, calls draw-cell for each row in the first
column, which is column 0. Thus, you can either specialize the draw-item
method itself or specialize the column parameter for column 0 in your
draw-cell method to draw the contents of a list view.
Selecting Cells 16
You can call select-cell, deselect-cell, and cell-selected? to handle
selection of individual cells. You can add the <grid-select-behavior> and
<grid-arrow-key-behavior> objects to your grid or list view to handle selection
using the mouse and arrow-keys. For an example of setting up these behaviors,
see Figure 16-2 on page 389.
Slot descriptions
%rows The number of rows in the view. Use the rows: keyword to
specify the initial number of rows; otherwise, the view is
created with only one row. You can use the rows method to
determine the number of rows and the rows-setter
method to change the number of rows.
%columns The number of columns in the view. Use the columns:
keyword to specify the initial number of columns;
otherwise, the view is created with only one column. You
can use the columns method to determine the number of
columns and the columns-setter method to change the
number of columns.
Initialization
The initialize method for <grid-view> objects sets the view’s extent to contain
the number of rows and columns specified initially. The initialize method’s
parameters are defined as follows:
Slot descriptions
text-getter specifies the function that is called to get the text. By
default, the default-<text-grid-view>-text-getter
method is used, which concatenates the row and column
number into a string, such as “1,2”, where 1 is the row and
2 is the column.
Initialization
No initialize method is defined for <text-grid-view> objects.
objects from the subclasses. Listing 16-3 shows the class definition for the
<list-view> class.
Slot descriptions
columns Specifies the number of columns to be 1.
Initialization
No initialize method is defined for <list-view> objects.
Slot descriptions
text-getter specifies the function that is called to get the text. By
default, the default-<text-list-view>-text-getter
method is used, which returns the row number as text.
Initialization
No initialize method is defined for <text-list-view> objects.
Slot descriptions
multiple-selection?
Specifies whether you want to keep previous selections
and adding the cell to the selection when the user clicks on
a cell while depressing the shift key. Use the
multiple-selection: keyword to specify true (#t) for
multiple-selection support; otherwise, previous selections
are lost when a cell is selected—the use of the shift key has
no effect.
Initialization
No initialize method is defined for <grid-select-behavior> objects.
Listing 16-6 shows the class definition for the <grid-arrow-key-behavior> class.
Initialization
No initialize method is defined for <grid-arrow-key-behavior> objects.
Although you can use the functions for grid views to manipulate list views, the
Framework provides several additional functions to make manipulation of list
views easier. Table 16-2 identifies these functions.
17 Windows
Contents
About Windows 401
Using Window Objects 402
Creating a Window 402
Creating a Window for a Dialog Box 404
Creating a Floating Window 404
Window Objects Reference 406
The <window-context> Class 406
The <window> Class 407
The Grow Icon Classes 413
The <grow-icon> Class 414
The <grow-icon-determiner> Class 414
Functions for Windows 415
Contents 399
400 Contents
C H A P T E R 1 7
Windows 17
About Windows 17
You can create the same kinds of windows with the Framework as you can
with the Window Manager. The <window> class represents Window Manager
windows. The <window> object is a frame and an event handler. The frame
defines a window’s size and location. The event handler allows the window to
respond to events. If you do not specify otherwise, a window’s next handler is
the main handler. Thus, you must specify a document as the window’s next
handler if the window displays a document’s contents.
Associated with each window is a root view provided by the Framework,
which is at the top of a view hierarchy. In general, you do not need to
manipulate windows because most events in windows are handled by either
by the Framework or passed to the root view to handle. If an event is in the
content area of the window, the root view allows subviews, which are your
content views, to handle the event. For more information about views and the
view hierarchy, see “About Views and Supporting Classes” on page 335.
Windows and window contexts are subclasses of the <event-handler> class and
the <command-context> class. The window class is also a subclass of the <frame>
class. Figure 17-1 shows the subclasses of the <command-context> class.
Windows
Creating a Window 17
The Framework provides a method, make-scrolling-window, that creates a
window and sets up the views required for scrolling. For information about
setting up a window for scrolling, see “Setting up a Scrolling View” on
page 465. Listing 17-1 shows how to create a window for a document. The code
shows a call to make-scrolling-window, which is used as the parameter to the
open function that opens the window once it has been created.
Windows
Windows
The apply function creates a call to make for the <window> class, using the #rest
parameters passed into the make-scrolling-window method. One of the things
that the initialize method does is create the root view, which is then available
for use as the root of the view hierarchy associated with the window.
Windows
open(the-window);
Windows
Note
Defining and using subclasses of <window-context> is
completely experimental. ◆
Listing 17-5 shows the class definition for the <window-context> class.
Slot descriptions
main-window The main window in this context. Use the main-window:
keyword to specify the main window; otherwise, the value
is false (#f). You can use the getter and setter to access this
slot.
Windows
close-with-last-window?
Specifies whether the children of a context, which typically
are windows, should be closed when the last window
associated with the context is closed (#t) or whether they
should remain open after the last window associated with
the context is closed (#f). Use the close-with-last-window:
keyword and specify false (#f) to allow children of a
context to remain open; otherwise, the value is true (#t),
meaning that all children of the context will be closed
when the last window is closed. You can use the getter and
setter to access this slot.
Initialization
No initialize method is defined for <window-context> objects.
Windows
Windows
init-value: $window-minimum-extent,
init-keyword: minimum-extent:;
slot scripting-object,
init-value: #f,
init-keyword: scripting-object:;
slot window-content-color,
init-value: #f,
init-keyword: window-content-color:;
// private
// use the generic functions location, window-size, visible?
// root-view, title, and their setters to access these slots.
slot %root-view, init-value: #f;
slot %visible? :: <boolean>,
init-value: #f;
slot was-visible? :: <boolean>,
init-value: #f;
slot %title :: <string>;
end class;
Slot descriptions
target-view The view that initially receives events when this window is
active. Use the target: or target-id: keywords to specify
the target view; otherwise, the target is assumed to be
defined in a stream. Call target-view to determine the
value of this slot. Call the set-target method to set the
value of this slot.
window-ptr The Macintosh Window Manager window. The window is
defined using the toolbox WindowRecord data type. For
information about the WindowRecord data type, see the
Window Manager chapter of Inside Macintosh: Macintosh
Toolbox Essentials.
window-kind The type of window, which are described in the Window
Manager chapter of Inside Macintosh: Macintosh Toolbox
Windows
Windows
Windows
minimum-extent A point that specifies the minimum size for the window.
Use the minimum-extent: keyword to specify the extent;
otherwise the value is $minimum-extent, which is defined as
point(80, 80). You can use the getter and setter to access
this slot.
maximum-extent A point that specifies the minimum size for the window.
Use the maximum-extent: keyword to specify the extent;
otherwise the value is $maximum-extent, which is defined as
point(1000000, 1000000). You can use the getter and setter
to access this slot.
scripting-object Specifies the scripting object that responds to Apple events
sent to the window. For more information about scripting
objects, see “About Scripting Support” on page 601.
window-content-color
Specifies the color to use for the window’s contents.
%root-view The root view associated with the window. Use the
root-view: keyword to specify whether the view is visible;
otherwise, it is false (#f). Use the root-view and
root-view-setter functions to access this slot. The
%root-view slot is not exported.
%visible? Specifies whether any part of the view is visible onscreen.
Use the visible: keyword to specify whether the view is
visible; otherwise, it is true (#t). Use the visible and
visible-setter functions to access this slot. The %visible?
slot is not exported.
was-visible? Specifies whether a floating window was visible onscreen.
Internal.
%title The window’s title. Use the title: keyword to specify the
title; otherwise, the slot is empty. Use the title and
title-setter functions to access this slot. The %title slot is
not exported.
Note
Setting the value of most slots has no effect if the window
is already open. For example, if you change a window
from modal to not modal, the change does not become
effective until the window is closed and reopened. ◆
Windows
Initialization
The initialize method for <window> objects. Use the item-list: keyword to
load the items dynamically. Use the menu-rsrc-id: keyword if you want to load
the menu items from a resource. The initialize method’s parameters are
defined as follows:
Windows
Listing 17-7 shows the class definition for the <grow-icon> class.
Slot descriptions
identifier The identifier for a <grow-icon> object.
Initialization
The initialize method for <grow-icon> objects installs a determiner so that the
icon is placed in the lower-right corner of the window. The initialize
method’s parameters are defined as follows:
Listing 17-8 shows the class definition for the <grow-icon-determiner> class.
Initialization
No initialize method is defined for <grow-icon-determiner> objects.
Windows
Windows
Contents
About Dialogs and Controls 419
Dialog Behaviors 419
Control View Classes 421
Control Events 423
Highlighting in Controls 424
Using Dialogs and Controls 424
Creating a Modal Dialog Box 425
Creating a Window for a Modal Dialog Box 429
Setting up Dialog Box Dismissers 429
Creating Static Text 430
Creating Number Text 430
Implementing a Popup Menu 431
Adding a Tabbing Behavior 432
Opening the Modal Dialog Box 432
Dialog and Control Objects Reference 433
The <dialog-behavior> Class 433
The <tabber> Class 435
The <edit-text-dialog-filter> Class 436
The <cluster> Class 437
The <simple-icon> Class 438
The <static-text> Class 439
The <control> Class 440
Subclasses of the <control> Class 442
The <button> Class 443
The <check-box> Class 443
The <radio> Class 443
Contents 417
418 Contents
C H A P T E R 1 8
This chapter discusses the implementation of dialogs and controls. Dialogs are
implemented as behaviors that are attached to windows. These windows are
the dialog boxes that contain views, such as the following:
■ edit text and number text, which are views.
■ Control Manager controls, which are classes derived from several
Framework classes including views.
The views and controls respond to events in the same way that other event
handlers do.
For information about edit text and number text view classes, see “About Text
View Classes” on page 373. This chapter discusses the behaviors that
implement dialogs and the controls that are commonly found in dialog boxes
and the events that are specific to controls.
Dialog Behaviors 18
The Framework implements dialog boxes as windows that are posed modally.
You create a window object. When you call the pose-modally function, the
Framework attaches a dialog behavior to the window that controls which
keystrokes or mouse clicks allow the dialog box can be dismissed. When the
dialog box is dismissed, the behavior is removed.
The dialog may contain fields, which are text views, such as edit text or
number text objects. The Framework provides a behavior that allows the user
to tab (or back-tab) between these views. The Framework also provides a
behavior that prevents the keys associated with a dialog box from being
interpreted as data in an edit text field.
Figure 18-1 shows the dialog-related subclasses of the <behavior> class.
Objects created from the classes in Figure 18-1 represent the following kinds of
views:
<dialog-behavior> Represents a behavior that implements modal
dialogs. For more information about the
<dialog-behavior> class, see “The <dialog-behavior>
Class” on page 433.
<edit-text-dialog-filter>
Represents a behavior that handles conflicting keys,
such as Tab and Return, while entering text in a
dialog. For more information about the
<edit-text-dialog-behavior> class, see “The
<edit-text-dialog-filter> Class” on page 436.
<tabber> Represents a behavior that provides tabbing
between fields in a dialog box. For more information
about the <tabber> class, see “The <tabber> Class”
on page 435.
Objects created from the classes in Figure 18-2 represent the following kinds of
views:
<cluster> Represents a group of controls that operate together,
such as a group of radio buttons.
<control> Represents a control. See the next section for
information on the <control> class and its subclasses.
<simple-icon> Represents an icon.
<static-text> Represents a view for unchangeable text.
Figure 18-3 shows the <control> class (from Figure 18-3) and its subclasses.
Objects created from the subclasses of <control> in Figure 18-3 represent the
following kinds of views:
<button> Represents an event associated with a push button
control.
<check-box> Represents an event associated with a check box
control.
<popup> Represents an event associated with a popup menu
control.
<radio> Represents an event associated with a radio control.
<scroll-bar> Represents an event associated with a scroll bar
control.
<ctl-mgr-control> Represents a Control Manager control.
<ctl-mgr-button> Represents a Control Manager push button control.
Control Events 18
Control events are a subset of window events to which controls respond. These
controls are the views that are subviews of a window’s root view, such as push
buttons. Figure 18-4 shows the subclasses of the <control-event> class and its
subclasses.
Objects created from the classes in Figure 18-4 represent the following kinds of
views:
<control-event> Represents an event associated with a control.
<button-event> Represents an event associated with a push button
control.
<check-box-event> Represents an event associated with a check box
control.
<popup-event> Represents an event associated with a popup menu
control.
Highlighting in Controls 18
Controls can be defined to support one of three mode styles, where these
modes determine the hiliting behavior for the control. These modes are
specified using symbols shown in Table 18-1:
These modes are used by the do-event method to determine how to handle the
hiliting for the control. This can primarily be used to implement customized
controls that do not use the Control Manager.
Note
The control class does not do any hiliting based on these
modes it is up to the subclass to implement the
appropriate hiliting, either in the draw method or in an
adorner. ◆
■ creating a modal dialog box that consists of a window, static text, number
text, and controls
■ responding to control events
Listing 18-1 shows the code that creates this dialog box and displays it.
let dialog-prompt
= make(<static-text>, text: "Create New Document…",
location: point(16, 16),
extent: point(300, 16));
add-sub-view(the-window.root-view, dialog-prompt);
add-sub-view(the-window.root-view, depth-popup);
add-behavior(the-window.root-view, make(<tabber>));
the-window.target-view := height-text;
open(the-window);
block()
let dismisser = pose-modally
(the-window, default: ok-button, cancel: cancel-button);
if (dismisser = cancel-button)
abort();
end if;
*last-height* := current-value(height-text);
*last-width* := current-value(width-text);
*last-depth* := select(current-choice-id(depth-popup))
#"1" => 1;
#"2" => 2;
#"4" => 4;
#"8" => 8;
#"16" => 16;
#"32" => 32;
otherwise => #f;
end select;
A modal dialog box is simply a window that does not have close, grow, or
resize icons. The window is still moveable. For more information about
windows, see “About Windows” on page 401. Listing 18-2 shows how the
dialog box is created.
Dialog box dismissers are controls that dismiss the dialog. The dismisser: #t
keyword specifies this capability. Listing 18-3 shows two <ctl-mgr-button>
objects, either of which dismisses the dialog.
The OK button is also the default button (default: #t), meaning that it has a
wide border that makes it stand out. Note that both controls are added as
views to the window’s root view.
Static text is text that is displayed but which is not editable. Listing 18-4 shows
creating static text and adding it to the dialog box.
Number text is text that can be edited, however, its contents are restricted to
digits. Listing 18-5 shows creating number text and adding it to the dialog box.
The current value of the field is set, although the range is not specified. Note
that a frame adorner is added to the view; otherwise, the field’s size would not
be obvious.
current-value: *last-height*);
add-adorner(height-text, $frame-adorner);
add-sub-view(the-window.root-view, height-text);
Listing 18-6 shows how to create a popup menu and add it to a dialog box. The
item-list: keyword specifies the items’ titles and assigns an identifier to each
one. For example, the title of the first item is “1” and its identifier is #"1". The
current value is also being set using the item identifiers, such that if the value
of *last-depth* is 1, the item corresponding to identifier #"1" is selected to be
the current value for the popup menu.
add-sub-view(the-window.root-view, depth-popup);
*last-depth* := select(current-choice-id(depth-popup))
#"1" => 1;
#"2" => 2;
#"4" => 4;
#"8" => 8;
#"16" => 16;
#"32" => 32;
otherwise => #f;
end select;
Because the dialog box contains several fields, it is useful to allow the tab and
shift-tab characters to change the target view. The tabbing behavior does this,
as shown in Listing 18-8.
add-behavior(the-window.root-view, make(<tabber>));
As with any window, you must set the target view if you do not want it to be
the root view. You must open the window to make it visible onscreen. You then
call pose-modally to cause the window to behave like a dialog box. In the call to
pose-modally you specify the default and cancel items. The default item
responds to the return and enter keys. The cancel item responds to the escape
key.
The pose-modally function returns the item that dismissed the dialog. If the key
is the cancel key, you must ignore any settings to the control and revert to the
previous values. The easiest way to do this is to call the abort method, which
immediately executes the cleanup section of a block. If the key is the OK key,
you may set the values and terminate the block normally. The cleanup section
is still executed.
Listing 18-9 shows the code that sets the target view and then opens, poses, and
closes the dialog box.
the-window.target-view := height-text;
open(the-window);
block()
let dismisser = pose-modally
(the-window, default: ok-button, cancel: cancel-button);
if (dismisser = cancel-button)
abort();
end if;
*last-height* := current-value(height-text);
*last-width* := current-value(width-text);
*last-depth* := …
creates the behavior object for you and attaches it to your window when you
call the pose-modally function; it removes the behavior from the window when
it is no longer needed. The window typically contains buttons for the default
and cancel items, such as buttons representing “OK” and “Cancel.”
Listing 18-10 shows the class definition for the <dialog-behavior> class.
Slot descriptions
default-item The <ctl-mgr-button> object that represents the default
button, which is the one that typically responds to the
return or enter keys. Use the default-item: keyword to
specify the button; otherwise, the value is false (#f),
meaning the dialog does not have a default button.
cancel-item The <ctl-mgr-button> object that represents the cancel
button, which is the one that typically responds to the
escape key or Command-period. Use the cancel-item:
keyword to specify the Escape button; otherwise, the value
is false (#f), meaning the dialog does not have a cancel
button.
dismisser The object that caused the window to which the behavior
is attached to be dismissed.
Initialization
No initialize method is defined for <dialog-behavior> objects.
Slot descriptions
first-target The first view eligible to be the target. Internal.
next-target The next view eligible to be the target. Internal.
found-current-target
Specifies whether the view actually found matches the
next view. Internal.
search-recursively Specifies whether to search recursively (#t), or not (#f).
Use the recursive: keyword to specify true (#t) if you
want to support tabbing recursively through each view’s
list of views; otherwise, the value is false (#f), meaning
that the tabbing behavior only operates on the subviews of
the view to which the behavior is attached.
Initialization
No initialize method is defined for <tabber> objects.
Listing 18-12 shows the class definition for the <edit-text-dialog-filter> class.
'\t' // tab
);
end class;
Slot descriptions
control-char The keys (Enter, Return, Escape, and Tab) that are not
considered part of the editable text, rather they are used to
terminate the dialog or move to the next field.
Initialization
No initialize method is defined for <edit-text-dialog-filter> objects.
Slot descriptions
title The view’s title. Use the title: keyword to specify the
title; otherwise, the slot is empty. Use the getter and setter
functions to access this slot.
Initialization
No initialize method is defined for <cluster> objects.
Slot descriptions
resource-id The resource ID of the resource that contains the icon. You
must use the resource-id: and specify the resource id for
your icon.
Initialization
No initialize method is defined for <simple-icon> objects.
Slot descriptions
text The text to be displayed in the view. Use the text:
keyword to specify the text; otherwise, an empty string is
displayed. Use the getter and setter functions to access this
slot.
%justification Specifies how the text is to be justified in the view. Use the
justification: keyword to specify the justification as
either #”left”, #”right”, or #”center”; otherwise, the value
is left (#”left”). You can use the justification and
justification-setter methods to determine or set the
justification. The %justification is not exported.
truncate? Specifies whether or not to truncate text that is too wide to
fit within the view (#t), or not,(#f). Use the truncate:
keyword to specify true (#t) if you want to truncate the
text; otherwise, the value of this slot is false(#f), meaning
that text that is too long is broken into separate lines. You
can use the getter and setter to access this slot.
invalidate-all-on-resize?
Specifies whether or not the entire view is invalidated
when the view’s size changes (#t), or not,(#f). Use the
invalidate-all-on-resize: keyword and specify false (#f)
if you do not want to redraw the entire view; otherwise,
the value of this slot is true(#t), meaning that all the text
is redrawn whenever the view’s size changes. You can use
the getter and setter to access this slot.
Initialization
The initialize method for <button> objects sets up the button to be a default
button. The initialize method’s parameters are defined as follows:
Slot descriptions
title The control’s title. Use the title: keyword to specify the
title; otherwise, the slot is empty. Use the getter and setter
functions to access this slot.
dismisses-dialog? Specifies whether the control can dismiss the window it is
in (#t), or not,(#f). Use the dismisses-dialog: keyword
to specify true (#t) if you want the control to dismiss the
dialog box; otherwise, the value of this slot is false(#f),
meaning that the dialog box remains onscreen after the
control is activated. You can use the getter and setter to
access this slot.
control-mode Specifies the way in which highlighting is to be performed
for non-Control Manager controls. Use the control-mode:
keyword to specify to specify the control mode; otherwise,
the value of this slot is #"no-mode", meaning that the
control appears as normal for Control Manager controls.
You can use the getter and setter to access this slot. For
acceptable values for this slot, see Table 18-1 on page 424.
%dimmed? Specifies whether the control appears to be dim (#t), or
not,(#f). Use the dimmed: keyword to specify true (#t) if
you want the control to appear dimmed; otherwise, the
value of this slot is false(#f), meaning that the control
appears as normal. You can use the dimmed? and
dimmed?-setter to access this slot.
%hilited? Specifies whether the control appears highlighted (#t), or
not,(#f). Use the hilited: keyword to specify true (#t) if
you want the control to highlighted; otherwise, the value
of this slot is false(#f), meaning that the control appears
as normal. You can use the hilited? and hilited?-setter
to access this slot. This slot is applicable to buttons.
%on? Specifies whether the control is on (#t), or off,(#f). It
applies to check boxes, radio buttons, or other controls
with two states, such as “checked” or “unchecked,” in the
case of a checkbox. Use the on: keyword to specify true
(#t) if you want the control to be on; otherwise, the value
of this slot is false(#f), meaning that the control is in its
“off” state. You can use the on? and on?-setter to access
this slot. This slot is applicable to buttons.
Initialization
No initialize method is defined for <control> objects.
Listing 18-17 shows the class definition for the <button> class.
Initialization
No initialize method is defined for <button> objects.
Listing 18-19 shows the class definition for the <radio> class.
Listing 18-20 shows the class definition for the <scroll-bar> class.
Slot descriptions
scroll-increment The number of pixels to scroll if the user clicks in the up or
down arrow boxes in the scroll bar. Use the
scroll-increment: keyword to specify the number of
Initialization
No initialize method is defined for <scroll-bar> objects.
Slot descriptions
dynamic-menu? Specifies whether the menu items for a popup menu are
created at runtime (#t), or whether they are loaded from a
resource,(#f). Use the dynamic-menu: keyword to specify
true (#t) if you specify the menu items at runtime;
otherwise, the value of this slot is false(#f), meaning that
the items are loaded from a resource. You can use the
getter and setter to access this slot. You do not need to
Initialization
No initialize method is defined for <popup> objects.
// private
slot %min :: <integer>,
init-value: 0,
init-keyword: min:;
slot %max :: <integer>,
init-value: 1,
init-keyword: max:;
slot %value :: <integer>,
init-value: 0,
init-keyword: value:;
end class;
Slot descriptions
control-handle The Control Manager ControlHandle record associated with
the control.
ref-con A reference constant stored in the ControlHandle record.
The Framework uses this slot to maintain information
about popup menus and scroll bars.
proc-id The control definition ID, which determines which control
definition function to use with the control. The Framework
defines this value for its subclasses of <ctl-mgr-control>.
Use the proc-id: keyword to specify the control definition
ID if you define a subclass of <ctl-mgr-control> so that
you can create a custom control; otherwise, the value of
this slot is -1 for your subclass. You can use the getter and
setter to access this slot. For more information about
control definition IDs and functions, see the Control
Manager chapter of Inside Macintosh: Macintosh Toolbox
Essentials.
action-proc The action procedure that follows and responds to cursor
movements in a control. Use the action-proc: keyword to
specify the routine descriptor for the action procedure;
otherwise, the value of this slot is false (#f), meaning that
the Control Manager’s standard actions are taken.
uses-color? Specifies whether the control uses colors other than the
default one used by the system software. Use the
uses-color?: keyword to specify that non-default system
colors may be used (#t); otherwise, the value of this slot is
false (#f), meaning that a control color table is not used
even if it is available.
invalidate-all-on-resize?
Specifies whether or not the entire control is invalidated
when the view’s size changes (#t), or not,(#f). Use the
invalidate-all-on-resize: keyword and specify false (#f)
if you do not want to redraw the entire view; otherwise,
the value of this slot is true(#t), meaning that the entire
control is redrawn whenever the view’s size changes. You
can use the getter and setter to access this slot.
%min The minimum value for the control. Use the min: keyword
and specify a value that represents the minimum value;
otherwise, the value of this slot is 0. You can use the
scroll-min and scroll-min-setter methods to access this
slot for scroll bars. You can use the control-min and
control-min-setter methods to access this slot for other
kinds of controls. The %min slot is not exported.
%max The maximum value for the control. Use the max: keyword
and specify a value that represents the maximum value;
otherwise, the value of this slot is 1. You can use the
scroll-max and scroll-max-setter methods to access this
slot for scroll bars. You can use the control-max and
control-max-setter methods to access this slot for other
kinds of controls. The %max slot is not exported.
%value The current state of the control; for example a 0 if a check
box or radio button is not marked or 1 if it is marked. Use
the value: keyword and specify a value that represents the
state; otherwise, the value of this slot is 0. You can use the
control-value and control-value-setter methods to
access this slot. The %value slot is not exported.
Initialization
No initialize method is defined for <ctl-mgr-control> objects.
Slot descriptions
proc-id The control definition ID, which determines which control
definition function to use with the control. It is
$pushButProc, which is the Control Manager’s control
definition ID for buttons.
Initialization
The initialize method for <button> objects sets up the button to be a default
button. The initialize method is defined as follows:
Slot descriptions
proc-id The control definition ID, which determines which control
definition function to use with the control. It is
$checkBoxProc, which is the Control Manager’s control
definition ID for checkboxes.
Initialization
No initialize method is defined for <ctl-mgr-check-box> objects.
Slot descriptions
proc-id The control definition ID, which determines which control
definition function to use with the control. It is
$radioBoxProc, which is the Control Manager’s control
definition ID for radio buttons.
Initialization
No initialize method is defined for <ctl-mgr-radio> objects.
Slot descriptions
proc-id The control definition ID, which determines which control
definition function to use with the control. It is
$scrollBarProc, which is the Control Manager’s control
definition ID for scroll bars.
hide-on-deactivate?
Specifies whether the scroll bar is hidden when the scroll
bar is not active (#t), or not hidden when the scroll bar is
not active (#f). Use the hide-on-deactivate: keyword and
specify false (#f) if you want the scroll bar to be drawn
when it is not active; otherwise, the value is true (#t),
meaning that a framed rectangle is drawn in place of the
scroll bar. You can use the getter and setter to access this
slot.
Initialization
The initialize method for <ctl-mgr-scroll-bar> objects sets up a control
action procedure for the scroll bar. The initialize method’s parameters are
defined as follows:
slot res-menu-type,
init-value: #f,
init-keyword: res-menu-type:;
end class;
Slot descriptions
proc-id The control definition ID, which determines which control
definition function to use with the control. It is
Initialization
The initialize method for <ctl-mgr-popup> objects loads the menu items in a
popup menu either dynamically or from a resource. Use the item-list:
keyword to load the items dynamically. Use the resource: and library:
keywords if you want to load the menu items from a resource. The initialize
method’s parameters are defined as follows:
You must use both the resource: and library: keywords together if you want
to load the menu items from a resource. If you are loading from a resource, do
not specify the item-list: keyword.
Slot descriptions
control The control that initiated the event, such as a
<ctl-mgr-control> object that responded to a <mouse-down>
event.
Initialization
No initialize method is defined for control event objects.
Slot descriptions
identifier The identifier for a <default-button-adorner> object.
Initialization
No initialize method is defined for <default-button-adorner> objects.
Table 18-3 shows functions you can use with scroll bars.
Table 18-4 shows functions you can use with popup menus.
Contents
About Scrolling 461
About Tracking 463
Using Scrolling and Tracking 465
Setting up a Scrolling View 465
Setting up a Scroller View 466
Setting up Scroll Bars 467
Implementing Mouse Tracking 467
Scrolling and Tracking Objects Reference 471
The <scroller> Class 471
The <tracker> Class 473
The <tracker-adorner> Class 474
Functions for Scrolling and Tracking 475
Contents 459
460 Contents
C H A P T E R 1 9
This chapter discusses how to set up scrolling views and how to track mouse
movements across a view. For information about scroll bars, see “The
<ctl-mgr-scroll-bar> Class” on page 451.
About Scrolling 19
Scrolling provides the ability to manage a view, only part of which is visible
through a window. Figure 19-1 shows a view whose contents are too large to
entirely display in the window.
Figure 19-1 The relationship between a scroller view, scroll bars, and a content view
Scroller view
Scroll bars
Content view
The content view is a subview of the scroller. The scroller and scroll bars are
subviews of the root view, as shown in Figure 19-2.
Root view
Scroller
Scroll bars
Content view
When a mouse event occurs in the scroll bar, the scroller translates its position
in relation to the its subviews. Thus, you may want to think of the scroller
“moving” to expose a different area of its subviews in response to mouse-down
events in a scroll bar. Figure 19-3 shows the visible part of the content view
after mouse-down events have occurred.
Content view
Scroller view
Scroll bars
Note
The relationship between the scroll bars and scroller do not
change as a result of mouse-down events in a scroll bar;
they change only in relation to a change in the root view,
such as the result of a change in the size or position of the
root view’s window. ◆
The Framework handles the translation between the content view and the
scroller for you and also handles mouse down events in a scroll bar. You are
responsible for setting up a view hierarchy, similar to the one shown in Figure
19-2, and for specifying the scroll increments, which controls how many pixels
to “move” the scroller in response to an event in the arrow or the bar part of
the scroll bar.
For an example that implements a scrolling view, see “Setting up a Scrolling
View” on page 465. For information about the <scroller> class, see “The
<scroller> Class” on page 471.
About Tracking 19
Tracking provides feedback about mouse movements while the mouse is
down. Tracking is typically provided for mouse movements over content
views. For example, a graphics program could provide tracking feedback to
show the shape of an object that will be drawn when the mouse is released.
Figure 19-4 shows an example of feedback for a drawing a rectangle.
Mouse tracking is provided by a <tracker> class, from which you can provide
subclasses. In addition to tracking the mouse and returning its the position
when the button is released, the Framework allows you to constrain the
movement of the mouse; for example, by requiring the feedback to be a square
instead of a rectangle. In this example, the position when the mouse is released
would be a corner of a square, regardless of whether the mouse was moved
further to the left or right than up or down, and so on.
For an example of that implements mouse tracking, see “Implementing Mouse
Tracking” on page 467. For information about the <tracker> class, see “The
<tracker> Class” on page 473.
The following sections describe the major steps, which are setting up the
scroller view and setting up the scroll bars.
In this example, the scroller is the same size as the root view, and thus the same
size as the window, after reserving space for the scroll bars.
Note
You must attach the scroll bar to the scroller after you have
added your content subviews. ◆
Listing 19-7 shows a track-constrain method that limits the current mouse
position to be within the rectangle,
point(new-h, new-v);
end method;
PenMode($srcXor);
PenPat($gray-pattern);
frame-region(draw-rect);
PenNormal();
end method;
Slot descriptions
%translation The distance between a scroller view’s location and the
location of its subviews. You can use the translation:
keyword or translation-setter to change this value. Use
translation to get the value.
sub-view-extent The extent of the largest subview. The Framework
calculates the extent for you when a subview is added to
the scroller or a subview’s extent changes.
vertical-size-sub-views
Specifies whether to resize the vertical side of a subview
(#t) or not (#f) when a view is added to or removed from
the scroller or when a view’s extent changes.
horizontal-size-sub-views
Specifies whether to resize the horizontal side of a subview
(#t) or not (#f) when a view is added to or removed from
the scroller or when a view’s extent changes.
Initialization
No initialize method is defined for <scroller> objects.
Slot descriptions
tracker-view The view on which the mouse is being tracked. Use the
view: keyword to specify the value; otherwise, the value is
false (#f). You can use the getter and setter to access this
slot.
tracker-scroller The scroller whose subview is the view on which the
mouse is being tracked. The Framework sets the value of
this slot for you. You can use the getter and setter to access
this slot.
auto-scroll? Specifies whether you want the view to scroll during
tracking (#t) or not (#f). Use the auto-scroll: keyword
and specify false (#f) to prevent scrolling; otherwise, the
value is true (#t), meaning that scrolling occurs when the
mouse if moved outside the scroller. You can use the getter
and setter to access this slot.
start-point The starting point for tracker feedback. Use the
start-point: keyword to specify the point; otherwise, the
value is not defined. You can use the getter and setter to
access this slot.
Initialization
No initialize method is defined for <tracker> objects.
Slot descriptions
the-tracker The tracker to which the adorner is attached.
the-last-point The previous mouse position.
the-current-point The current mouse position.
Initialization
No initialize method is defined for <tracker-adorner> objects.
20 Documents
Contents
About Documents 479
The Open Protocol 479
Commands and Change Counts 480
Document Menu Items 480
Using Documents 481
Defining a Document Subclass 481
Registering a Document 482
Creating and Opening a Document 482
Creating a Document’s Windows 483
Specifying a Document’s File Type 484
Document Objects Reference 484
The <document> Class 485
Functions for Documents 487
Contents 477
478 Contents
C H A P T E R 2 0
Documents 20
About Documents 20
A document represents data that is displayed in a window. Often this data is
stored in a file. A document does not by itself contain data, although it may
refer to collections, TextEdit handles, or other structures that do contain data. A
document instead manages the representation of data onscreen and also
manages its movement between the application and disk.
Documents
Documents
Using Documents 20
The following sections provide examples of using documents:
■ defining document subclasses
■ creating and opening documents
■ creating windows for documents
■ registering a document
■ specifying the kind of data in a document’s files
Documents
Registering a Document 20
You must register each document class with the main handler. This allows the
application to open a document by looking at the data type of the file
associated with the document. If the file type is registered, the application can
create the appropriate document object to manage the file.
You specify the file type and the document class that supports the type to your
application by calling the add-document-type method from the method that
initializes your application. Listing 20-2 shows the call to add-document-type
that sets up this correspondence between text files and the <text-document>
class.
open(make(<text-document>));
end method;
Documents
Note
A file is not associated with a document until the
document has been saved. For more information about the
relationship between documents and files, see “Documents
and Files” on page 492. ◆
add-behavior(view, make(<styled-text-behavior>));
if (~ nil?(document.text-handle))
set-text(view, document.text-handle, style-handle:
document.style-handle);
DisposeHandle(document.text-handle);
document.text-handle := $null-machine-pointer;
Documents
end if;
Documents
Documents
Slot descriptions
change-count The number of changes to the document’s contents since it
was last saved. The Framework manipulates this value for
you when you use commands to change the document.
You can call the getter to determine the number of changes.
commit-on-save? Specifies whether the current command is considered
complete and cannot be undone at the time the
document’s contents are saved. By default, the command
is considered undoable after a save operation.
open? Specifies whether the document is open. Call open to open
the document, which sets the value of this slot to true (#t),
or close to close the document, which sets the value of this
slot to false (#f). You can call open? to determine whether
or not a document is open.
main-file The file that stores the document’s data. For more
information, see the section “Initialization,” described
below.
main-file-type The OS type that specifies the kind of file.
main-file-creator The OS type of the creating application.
%title The document’s title. Use the title: keyword to specify
the title; otherwise, the title is an empty string. Use the
title and title-setter functions to access this slot. The
%title slot is not exported.
Initialization
The initialize method for <document> objects sets up the association between a
document and its file and the next event handler in the target chain for the
document. The initialize method’s parameters are defined as follows:
Documents
Documents
The following functions can be used for document file manipulation. For
information about files, see “About Files” on page 491.
21 Files
Contents
About Files 491
Manipulating Files 491
Manipulating Resources 492
Documents and Files 492
Using Files 493
Reading From a File 493
Writing To a File 494
Reading From a Resource Fork 495
Updating a Resource Fork 495
File Objects Reference 496
The <file> Class 496
File Functions 500
Contents 489
490 Contents
C H A P T E R 2 1
Files 21
This chapter discusses the use of files, which represent Macintosh File Manager
files. This chapter also discusses resources that you may store in or retrieve
from the resource fork of a file. The use of files is closely related to the use of
documents and streams. This chapter discusses how to use files with
documents. For information about streams, see “About Streams” on page 505.
About Files 21
A <file> object represents a file on disk. Specifically, the <file> class defines a
Macintosh File Manager file specification record that the Framework uses to
implement file operations. These operations include:
■ creating files
■ opening, closing, and deleting files
■ reading and writing files
Reading and writing files may require you to read and write resources as well
as data. The Framework provides functions that allow you to retrieve and save
data into both the data fork and resource fork of a file.
Manipulating Files 21
Before you can manipulate a file on disk, you must create a file object, for
which you must define a Macintosh File Manager file specification record. The
Framework allows you to build the record from an alias or from a pathname if
you do not have the file specification record itself.
After you create a <file> object, you can use it in the following ways:
■ create a file that matches the specification in the <file> object, if the file does
not exist
■ open the file
■ close the file
■ delete the file; it must be closed first
■ read the contents of the file
Files
Manipulating Resources 21
The Framework provides functions that:
■ change the current resource file
■ retrieve resources
■ add resources
■ delete resources
IMPORTANT
Each Framework-provided function may change the
current resource fork. If you are calling both Framework
functions and Macintosh Toolbox routines to manipulate
the contents of a resource fork, you may wish to explicitly
set the current resource fork before calling a Toolbox
routine. ▲
Table 21-2 on page 501 identifies the functions you can use to perform
operations on resources.
Files
data to a file when the user requests Save, Save As, or Save a Copy. The
Framework does not create a file object before the contents need to be written.
You must specify how to store the document’s contents in a file and retrieve
those contents. You provide methods that
■ read the contents of the file associated with a document when a document is
opened. See “Reading From a File” on page 493 for an example.
■ write the contents of the file when its document is saved. See “Writing To a
File” on page 494 for an example.
■ restore the contents of a document from a file when the user chooses Revert.
Table 21-3 on page 502 identifies the file-related functions for documents.
Using Files 21
The following sections show examples of how to:
■ read data from a file
■ write data to a file
■ read a resource from a resource fork
■ update a resource fork
Files
with-locked-handle(document.text-handle)
let ptr = pointer-at(document.text-handle);
end;
end method;
Writing To a File 21
When writing data to a file associated with a document, the Framework calls
write-to-file. You must define a write-to-file method whose document
parameter is specialized on your document subclass. If you are writing to a file
that is not associated with a document, you must decide when to actually write
the data. In either case, you can call write-data to write data to a file.
Listing 21-2 shows a write-to-file method that calls write-data to write data
to a file. The write-to-file method calls set-end-of-file to reset the file’s
length to 0 bytes. The data in memory is locked down while it is being written.
set-end-of-file(file, 0);
Files
with-locked-handle(handle)
let ptr = pointer-at(handle);
let length = GetHandleSize(handle);
if (file.resource-fork-open?)
let style = get-ith-resource-from-file(file, ostype("styl"), 1);
unless(nil?(style))
DetachResource(style);
document.style-handle := as(<StScrpHandle>, style);
end unless;
end if;
Files
if (file.resource-fork-open?)
delete-all-resources-in-file(file, ostype("styl"));
add-resource-to-file(file,
as(<machine-pointer>,
get-style-handle(document.text-view)),
ostype("styl"),
128);
end if;
Files
Slot descriptions
file-name The name of the file. Use the name: keyword to specify the
file name; otherwise, the name must be specified in a
Macintosh File Manager file specification record. For more
information about using a file specification record, see the
following section, “Initialize.”
Files
Files
Initialization
The initialize method for <file> objects sets up a File Manager file
specification record to associate with the object. If you do not specify keywords
when you create a <file> object, you must specify either a file specification
record or an alias handle. The initialize method’s parameters are defined as
follows:
Files
File Functions 21
The following functions can be used to manipulate files.
Files
Files
The following functions can be used for document file manipulation. For
information about documents, see “About Documents” on page 479.
22 Streams
Contents
About Streams 505
About Class and Slot Specifications 507
Using Class and Slot Specifications 507
Setting up the Class and Slot Specifications 508
Using Slot Specification Getters and Setters 509
Cloning Objects 511
Using Shared and Default Objects 512
Using Streams 513
Using Handle Streams 513
Using Object Streams 514
Reading and Writing Objects 515
Reading and Writing Primitive Data Types 516
Stream Objects Reference 517
The <stream> Class 517
The <file-stream> Class 518
The <handle-stream> Class 519
Object Stream Classes 521
The <class-spec> Class 522
The <slot-spec> Class 523
Functions for Streams 525
Contents 503
504 Contents
C H A P T E R 2 2
Streams 22
This chapter discusses streams, which allow you to interpret data, such as the
contents of a handle or file, as a sequence of bytes or other data types. The
Framework provides a mechanism for interpreting its objects, which are
defined by class and slot specifications. You must provide a mechanism of
interpreting other kinds of data in streams. This chapter also discusses other
uses of class and slot specifications, namely their use in cloning and sharing of
objects.
About Streams 22
Streams provide the ability to work with a sequence of data at a higher level of
abstraction than might otherwise be possible if you need to also manage the
source of the data, in the case of input, or its sink, in the case of output. For
example, if you are reading a file and examining its contents, you must be
concerned about when you to read the next chunk of data from the file into
memory, how to detect the end of the file, and so on. These requirements add to
the complexity of obtaining the next byte, integer, string, or object from the
source.
A stream allows you to divide the responsibility for obtaining a piece of data
from the responsibility of managing the source or sink for the data. In the case
of a file stream, the stream manages the file to which it is attached and, thus,
transfers data between the file and the stream at the appropriate times. You are
only concerned about obtaining data from the stream or adding to the stream.
You may, of course, need to specify requirements, such as the interval
(determined by buffer size) that transfers take place between the file and
stream, but this is a one-time task and separate from manipulating the stream
itself.
The Framework provides streams whose source or sink can be either handles
or files. It allows you to read or write to the stream in several ways, which may
be combined:
■ by byte or by a series of bytes
■ by numbers, which are two-byte or four-byte integers
■ by strings, which can be either null-terminated or Pascal-style strings
■ by objects, which are defined by their respective classes and can be
identified by name or symbol
Streams
Note
You can use the functions that read data from streams and
write data to streams without specialization, or you can
define implementations of the methods that efficiently
meet your special needs. For a list of functions that read
from and write to streams, see Table 22-1, “Functions for
streams” on page 525. ◆
Figure 22-1 shows the <stream> class and its subclasses.
The classes shown in Figure 22-1 represent the following kinds of objects:
<stream> Represents an abstract stream from which subclasses
can be defined.
<file-stream> Represents a stream associated with a file.
<handle-stream> Represents a stream associated with a handle.
<object-stream> Represents a stream that contains objects.
<file-object-stream> Represents a stream associated with a file that
contains objects.
<handle-object-stream> Represents a stream associated with a handle that
contains objects.
Streams
Streams
make-class-spec(<window>, #"window",
list(
make-slot-spec(title, title-setter, title:),
make-slot-spec(resizable?, $no-setter, resizable:),
…
make-slot-spec(maximum-extent,
Streams
maximum-extent-setter,
maximum-extent:)
)
);
make-class-spec(<view>, #"view",
list(
// getter should only get streamable adorners
make-slot-spec(streamable-adorners,
adorner-list-setter,
adorners:,
cloning-getter: clone-adorner-list),
…
)
);
For example, the Framework allows you to specify whether to allow adorners
to be streamed. (For information about adorners, see “Adorners” on page 339.)
When writing to the stream, therefore, it is necessary to specify a getter
function that only obtains streamable adorners.
Streams
For example, the Framework does not clone shareable adorners; it only creates
a clone it if it should not be shared. Because the getter function does not make
this distinction, a separate clone getter function is specified.
Listing 22-4 shows the definition of the clone-adorner-list function used in
Listing 22-2.
map(get-adorner, view.cloneable-adorners);
end method;
Streams
Cloning Objects 22
By default, the contents of a slot are cloned. You do not typically want to clone
numbers, booleans, constants, or references to shared objects because the value
itself is sufficient. In these cases, you specify clone: #f when you call
make-slot-spec.
Listing 22-5 shows the make-slot-spec calls for the slots that define a rectangle.
Cloning is not performed because it would cause <number> objects to be created
when integer values are sufficient.
make-class-spec(<rect>, #"rect",
list(
make-slot-spec(top, top-setter, #"top", clone: #f),
make-slot-spec(left, left-setter, #"left", clone: #f),
make-slot-spec(bottom, bottom-setter, #"bottom", clone: #f),
make-slot-spec(right, right-setter, #"right", clone: #f)
)
);
The Framework provides a clone method to clone an object of any class for
which make-class-spec has been called. If you want to create a clone of an
object for which make-class-spec has not been called or if you wish to specify
the way that cloning is implemented for an object, you may provide a clone
method whose object parameter is specialized on your class. Listing 22-6 shows
a clone method that handles cloning of rectangles.
Streams
IMPORTANT
If a large object could be shared but it is rarely used, you
may wish not to share it because the Framework
guarantees that a sharable object always exists. ▲
You can specify shareable: #t in your call to make-class-spec to prevent an
object from being written to a stream more than once. Listing 22-7 shows an
example of the class specification for frame adorners. Because views can share
adorners, an adorner needs to appear in a stream only once.
Note
Listing 22-7 also shows how to specify a class that does not
have slots. Its slot list parameter is an empty list (#()). ◆
To make use of a shared object, you call the default-instance function
wherever you would have created the object. Listing 22-8 shows a call to
default-instance. Whenever a frame adorner is needed, you use to
$frame-adorner instead of creating a <frame-adorner> object.
You could still create a <frame-adorner> object or call clone if, for some reason,
you needed an unshared version.
Streams
Using Streams 22
The Framework provides stream classes that you can use without defining
subclasses:
■ file streams provide a stream whose source or sink is a file
■ handle streams build a stream whose source or sink is a handle
■ file object streams are file streams that support reading and writing objects
■ handle object streams are handle streams that support reading and writing
objects
The following sections show examples of using these kinds of streams.
Streams
fail-nil(error-list-handle);
HNoPurge(error-list-handle);
// keep it non-purgeable so it is there when we have problems
read-error-list-resource(error-list-handle);
end for;
end method;
element(*os-error-table*, error-number)
:= pair(reason-string, recovery-string);
end for;
end method;
Streams
After you set up your make-class-spec forms, the objects specified by them
may be written to streams and retrieved from streams. You must create a
stream and write objects to it. After the stream contains an object, it may be
read.
Listing 22-11 shows how to write an object to an object stream that uses a
handle. The <handle-object-stream> object is created. It is then written to the
stream and the handle is updated to reflect the change.
AddResource(stream.stream-handle,
resource-type, resource-id, "streamed window");
WriteResource(stream.stream-handle);
UpdateResFile(file.rsrc-ref-num);
end method;
Listing 22-12 shows reading a window from an object stream that uses a
handle. The <handle-object-stream> object is created. The next object, which in
the example is also the first object, is read from the stream.
Streams
IMPORTANT
You typically do not need to define read-from-stream and
write-to-stream functions; the Framework handles most
cases for you. You only need to define an implementation
to read and write primitive data types or collections that
are not already handled by the Framework. ▲
The Framework provides read-from-stream and write-to-stream functions for
objects as well as primitive data types for which slots are not defined. For
example, the Framework provides read-object and write-object methods that
are specialized for booleans because they can exist in the stream without
information that identifies its class or slot.
The read-from-stream and write-to-stream functions implement reading and
writing to the stream in a way that matches the make-class-spec specification.
Thus, the functions must know the order of the data and its structure.
Listing 22-13 shows the read-from-stream method for the <boolean> class. It
returns a true value (#t) if the next byte in the stream is non-null.
Streams
read-byte(stream) ~= 0;
end method;
Listing 22-14 shows the write-to-stream function for the <boolean> class. It
writes a 1 if the value is true (#t) or a 0 if it is false (#f).
Streams
Initialization
No initialize method is defined for <stream> objects.
Slot descriptions
file The file object associated with this stream. You must use
the file: keyword to specify a file object.
buffer The buffer that holds the stream’s contents in memory. The
Framework sets up the buffer for you.
buffer-size The size of the buffer. Use the buffer: keyword to specify
the size; otherwise the buffer size is 1,024 bytes.
bytes-in-buffer The current number of bytes in the buffer. The Framework
maintains this slot for you. You can call bytes-in-buffer if
Streams
Initialization
The initialize method for <file-stream> objects allocates a buffer in memory.
The initialize method’s parameters are defined as follows:
Streams
init-value: 16,
init-keyword: allocation-size:;
end class;
Slot descriptions
stream-handle The handle associated with this stream. Use the handle:
keyword to specify the handle. For more information, see
the “Initialization” section, below.
handle-size The size of the handle. If the handle exists, the size is its
actual size; if it is a new handle, the size is its allocation
size. You can call handle-size to determine the current size
of a handle associated with a stream; you can call
reallocate to change the size.
stream-position The current location to read from or write to in the stream.
The Framework maintains this slot for you. You can call
stream-position if you want to know the position.
own-handle? Specifies whether or not the stream owns the handle and,
thus, can dispose of the handle on termination (#t) or not
(#f). Use the owns-handle: keyword to specify that the
stream owns its handle (#t); otherwise, the slot’s value is
(#f), meaning that the stream is being created for a handle
that it cannot dispose of itself.
allocation-size The size by which to increment the handle when more
space is needed. Use the allocation-size: keyword to
specify the size in bytes; otherwise, the size of the handle
will be increased 16 bytes each time more space is needed.
You can also call the getter and setter to access this slot.
Initialization
The initialize method for <handle-stream> objects creates a new handle, if
needed, and sets up the handle size. The initialize method’s parameters are
defined as follows:
Streams
the-handle The handle associated with the stream. Use the handle:
keyword to specify the handle; otherwise a new handle is
created.
Slot descriptions
symbol-cache Internal.
Initialization
No initialize method is defined for <object-stream> objects.
Streams
Listing 22-15 shows the class definition for the <class-spec> class.
slot ws-template,
init-value: #f;
slot shareable-instance,
init-value: #f,
init-keyword: shareable-instance:;
end class;
Slot descriptions
the-class The name of the class. You must use the class: keyword to
provide the name.
Streams
class-symbol The identifying symbol of the class. You must use the
class-symbol: keyword to provide the symbol.
ws-template Internal.
local-slots The slots defined in the class. You must use the slots:
keyword and provide a list that contains a <slot-spec>
object for each slot you wish to stream or clone.
all-slots All slots for this class. The Framework maintains this list
for you.
shareable-instance An object from this class that can be shared. Use the
shareable-instance: keyword to specify the object to use;
otherwise, the Framework will use one created from this
<class-spec> object.
Initialization
No initialize method is defined for <class-spec> objects.
Streams
slot ws-template,
init-value: #f;
Slot descriptions
slot-symbol The initial keyword used to set the value of the slot; for
example, foo: or #"foo", which are equivalent. You must
use the slot-symbol: keyword to specify the initial
keyword.
getter-function The function that obtains the value to write to a stream.
You must use the slot-getter: keyword to specify the
function.
setter-function A function that the Framework uses internally. You must
use the slot-getter: keyword to specify the function. You
should specify $no-setter if you do not want to allow
setting the value from the Apple Dylan User Interface
Builder property editor.
ws-template Internal.
cloning-getter The function that obtains the value of the slot when
making a clone of an object. Use the cloning-getter:
keyword to specify the function; otherwise, the
Framework uses the function specified in the
Streams
Initialization
No initialize method is defined for <slot-spec> objects.
Streams
Streams
Streams
The following functions can be used with class and slot specifications.
23 Commands
Contents
About Commands 531
Using Commands 534
Defining a Command Class 534
Doing a Command 535
Undoing and Redoing a Command 535
Committing a Command 536
Completing a Command 537
Performing a Command 537
Command Objects Reference 539
The <command-context> Class 539
The <command> Class 540
Text Command Classes 541
The <typing-command> Class 542
The <text-style-command> Class 544
The Font Command Classes 545
Functions for Commands and Command Contexts 547
Contents 529
530 Contents
C H A P T E R 2 3
Commands 23
This chapter discusses commands, which allow you to package actions into a
single operation. Typically commands are used to implement undo and redo
for an operation, such as changing data in your application. Undo and redo are
implemented within a context, called a command context, that limits the scope
of the undo or redo operation. For example, a document might be the context
in which a change can be made, undone, and redone.
About Commands 23
Commands allow you to specify how to perform a unit of work, called an
operation, within an application. A command may be undoable, meaning that
it can be undone or redone. By default commands are undoable; however, they
are not required to be undoable.
Note
The Framework provides commands that handle changes
to the clipboard and text for you automatically. For
information about clipboard commands, see “Clipboard
Command Classes” on page 596. Information about text
commands, including information about commands for
changing fonts and styles, is discussed in this chapter. ◆
For example, the user may draw a rectangle in a drawing application. Rather
than drawing the rectangle directly, you can implement a command class to
handle the operation. In this example, the operation may be a single line of
code; however, it could also perform related tasks, such as drawing handles on
the rectangle, as well.
An undoable command allows you to specify how to undo the operation, and
how to redo it after it is undone. In the drawing example, undoing the
command may simply involve invalidating the area in which the rectangle and
its handles were drawn. It might also involve removing the data that specifies
where to draw it from the document. Redoing the command may be as simple
as preforming the original operation over again.
You specialize methods of your command class to specify the actions to take:
■ to do or perform the operation
■ to undo the operation
Commands
The classes shown in Figure 23-1 represent the following kinds of objects:
<command> Represents a command that implements undo and
redo operations.
<clipboard-command> Represents a command that implements undo and
redo operations for the clipboard.
Commands
Commands
The classes shown in Figure 23-2 represent the following kinds of objects:
<command-context> Represents objects whose state can be undone or
redone.
<window-context> Represents an event handler that manages one or
more windows.
<window> Represents a Macintosh window that allows changes
to its contents to be undone or redone.
<document> Represents the data in a view or file to which
changes may be undone or redone.
<main-handler> Represents an event handler of last resort, which can
support undo and redo.
Using Commands 23
You can create commands that are not undoable simply by specifying false (#f)
for the undoable? slot in your command subclass and specializing the doit
method on the subclass. You can also specialize a completed method, if you
wish.
The examples in the following sections show how to implement undoable
commands. The following sections show how to:
■ define a command class
■ specify the actions to execute the command
■ specify the actions to undo and redo the command
■ specify how to commit the command
■ perform a command
Commands
not use the draw method, it is necessary to maintain information about the
view in addition to information about the shape to be drawn. (To see how this
state information is used, see Listing 23-2.)
Doing a Command 23
The doit method specifies the actions to take when the command is executed. If
drawing occurs while the command is being performed, you must focus the
view being drawn. Listing 23-2 shows an example of a doit method.
Commands
The redoit method specifies the actions to take when the command is redone.
In this example, the undo state is left so that the doit method can be executed
without alteration. Listing 23-3 shows an example of an unoit method.
Committing a Command 23
When a new command is executed, the Framework commits the last command.
The command’s commit method is executed to make the effects of the command
“permanent” in the sense that the command can no longer be undone or
redone via the Edit menu’s Undo and Redo items.
Listing 23-5 shows an example of the commit method that places the data in the
data structure after it can no longer be undone.
Commands
Note
Because this data structure is in memory, it could have
easily been manipulated by the doit, undoit, and redoit
methods. If the data structure was expensive to
manipulate, such as if it requires data base accesses, the
commit method is the preferred way to handle the situation.
Completing a Command 23
You can use the completed method to specify actions to take after an undoable
command has been committed or after a non-undoable command has been
executed. Listing 23-6 shows and example of a completed method.
Performing a Command 23
To perform a command, you must create the command object and then execute
the post-command method. After executing the post-command method, the
Framework automatically handles the Undo and Redo menu items until the
next command is posted. Listing 23-7 shows the creation and posting of a
command object, which occur after mouse tracking completes for a shape.
Commands
post-command(*main-handler*, command);
end method;
Commands
Slot descriptions
children Event handlers that are affected by undo and redo
operations on the context object.
last-command The last command that was done and can be undone.
Initialization
No initialize method is defined for <command-context> objects.
Commands
Commands
Slot descriptions
context The context to which the command applies.
causes-change? Whether the command causes a change (#t) or not (#f). For
example, you can specify false (#f) if you do not want the
Save dialog to appear after a command changes the
appearance of a document, such as its display
magnification, but not its content.
done? Whether the command has been performed (#t) or not (#f).
undone? Whether the command has been performed and then
undone (#t) or not (#f).
undo-name The string displayed in the Edit menu when the command
can be undone.
redo-name The string displayed in the Edit menu when the command
can be redone.
recurring? Whether the command should be kept on the queue of
commands to execute (#t) or not (#f).
undoable? Whether the command can be undone (#t) or not (#f).
Initialization
No initialize method is defined for <command> objects.
Commands
Commands
Slot descriptions
text-view The view that receives keystrokes while typing.
old-style The previous text style.
new-style The current text style.
undo-name The string displayed in the Edit menu when the command
can be undone.
redo-name The string displayed in the Edit menu when the command
can be redone.
old-selection-start
The beginning of the previous set of characters, which are
used to undo or redo the command.
old-selection-stop
The end of the previous set of characters, which are used
to undo or redo the command.
new-selection-start
The beginning of the current set of characters that can be
undone and redone.
new-selection-stop
The end of the current set of characters that can be undone
and redone.
new-text The text added while processing the command.
Commands
text-changed? Whether the text changed (#t) or not (#f) while typing.
selected-entire-contents?
Whether all the text in the view is selected (#t) or not (#f).
Initialization
The initialize method for <typing-command> objects determines the current
state of the selection within the text view before typing occurs so that the
command can be undone. The initialize method’s parameters are defined as
follows:
Commands
Slot descriptions
text-view The view to which the command applies.
old-style The previous text style.
new-style The current text style.
selection-start The beginning of the current set of characters whose style
can be undone and redone.
selection-stop The end of the current set of characters whose style can be
undone and redone.
style-action The function that specifies how to change the style.
Initialization
The initialize method for <text-style-command> objects determines the
current state of the selection within the text view so that the command can be
undone. The initialize method’s parameters are defined as follows:
The Framework provides command classes that represent a change to the font,
font size, or font style for selected text. Respectively, these classes are
<font-command>, <font-size-command>, and <font-style-command>. You do not
need to define subclasses from these classes. You can create objects directly
from them whenever you need to change the font characteristics of selected
text.
Listing 23-12 shows the definition of the <font-command>, <font-size-command>,
and <font-style-command> classes.
Commands
Slot descriptions
undo-name The string displayed in the Edit menu when the command
can be undone.
redo-name The string displayed in the Edit menu when the command
can be redone.
Initialization
No initialize method is defined for <font-command>, <font-size-command>, and
<font-style-command> objects.
Commands
Commands
Table 23-1 shows functions that can be used with typing commands.
24 Data Interchange
Contents
About Data Interchange 551
Using Data Interchange Classes 554
Using Typed Data 554
Using Typed Handles 554
Using Typed Pointers 555
Using Data Items 555
Using Designators 556
Creating Designator Objects 557
Defining Designator Subclasses 557
Data Interchange Objects Reference 558
The <typed-data> Class 558
The <typed-pointer> Class 559
The <typed-handle> Class 560
The <data-item> Class 560
Designator Classes 561
The <designator> class 561
The <selection-designator> class 562
The <text-designator> class 563
The <character-designator> class 563
The <range-designator> Class 564
The <offset-designator> Class 564
Functions for Data Interchange 566
Contents 549
550 Contents
C H A P T E R 2 4
Data Interchange 24
This chapter describes the classes that represent in-memory data structures
supported by the Framework. This chapter also describes how to reference
subsets of data through the use of designators. The classes representing data
structures and designators are used by the Framework to implement data
interchange between the application and the clipboard, data interchange via
drag and drop, as well as data interchange via Apple events.
Data Interchange
The classes shown in Figure 24-1 represent the following kinds of objects:
<typed-data> Represents data in which the data type is specified.
For more information about the <typed-data> class,
see “The <typed-data> Class” on page 558.
<clipboard-flavor> Represents data in the clipboard. For more
information about the <clipboard-flavor> class, see
“The <clipboard-flavor> Class” on page 595.
<drag-flavor> Represents data being dragged. For more
information about the <drag-flavor> class, see “The
<drag-flavor> Class” on page 579.
<typed-handle> Represents typed data that resides in memory and is
accessible via a handle. For more information about
the <typed-data> class, see “The <typed-handle>
Class” on page 560.
<typed-pointer> Represents typed data that resides in memory and is
accessible via a pointer. For more information about
the <typed-data> class, see “The <typed-pointer>
Class” on page 559.
Figure 24-2 shows the data item classes.
Data Interchange
The classes shown in Figure 24-2 represent the following kinds of objects:
<data-item> Represents data in one or more data type formats
called flavors. A flavor is typically represented by a
subclass of <typed-data>. For more information
about the <data-item> class, see “The <data-item>
Class” on page 560.
<clipboard> Represents the flavors of data associated with the
clipboard. For more information about the
<clipboard> class, see “The <clipboard> Class” on
page 594.
<drag-item> Represents an item in a drag operation. For more
information about the <drag-item> class, see “The
<drag-item> Class” on page 578.
Figure 24-3 show the designator classes.
The classes shown in Figure 24-3 represent the following kinds of objects:
<designator> Represents a designation of a subset of data.
<offset-designator> Represents a subset of data by offset from the
beginning of the data.
<property> Represents a subset of data by its Apple event
property. For more information about the <property>
class, see “The <property> Class” on page 616.
<range-designator> Represents a subset of data that is a range of bytes.
<text-range-designator> Represents a subset of text that is a range of bytes.
Data Interchange
Typed handle objects are used to refer to data that is accessible by a handle.
Listing 24-1 shows part of a Framework method that writes an object to a
handle stream and then creates a <typed-handle> object so that the data can be
referenced as a drag flavor.
Data Interchange
Typed pointer objects are used to refer to data that is accessible by a pointer.
Listing 24-2 shows a Framework method that creates a typed pointer object for
a reference to an element of an array whose address is specified in index.
index;
end method;
A data item object is a list of typed data objects. For example, the clipboard can
hold many kinds of data, each of which is represented by a typed data object.
When data is pasted from the clipboard, the Framework builds a data item that
includes only the data which is allowed to be pasted. Listing 24-3 shows how
the Framework creates a <data-item> object from the flavors of data stored in
the clipboard. The get-flavors method is called to locate the allowable data
types.
Data Interchange
command.redo-selection := get-selection(command.target);
command.undo-selection := set-selection-data(command.target,
command.data-item);
end method;
Using Designators 24
You can use the Framework provided designator subclasses to designate data
in the following ways:
■ as a range of bytes
■ as an offset from the start of data
■ as a selection
■ as a piece of text
■ as characters
There are other ways to designate data, which are only used with Apple events.
For information about Apple event-related designator subclasses, see “Property
Designator Classes” on page 615. You can also define your own designator
subclasses.
The following sections show examples of creating a designator object and
defining a designator subclass.
Data Interchange
The designator can then be used, for example to create a typed data object, as
shown in Listing 24-5.
Data Interchange
When you define a subclass of <designator>, you may need to specialize the
is-empty? method on your subclass. You may also need to specialize the
class-type method. Listing 24-7 shows a specialization of the is-empty?
method.
Data Interchange
Slot descriptions
data-type The kind of data represented by the object, such as
ostype(“PICT”).
Initialization
No initialize method is defined for <typed-data> objects.
Slot descriptions
data-pointer The beginning of the data associated with the object.
data-length The length of the data.
Data Interchange
Initialization
No initialize method is defined for <typed-pointer> objects.
Slot descriptions
data-handle The beginning of the data associated with the object.
Initialization
The parameters of the initialize method for <typed-handle> objects are
defined as follows:
Data Interchange
Slot descriptions
flavors A list of <typed-data> objects that identifies the various
representations of the data item and, possibly, the data
item’s content in each representation.
Initialization
No initialize method is defined for <data-item> objects.
Designator Classes 24
Designator classes are used to mark or designate a subset of data. They are
commonly used as a temporary reference to data associated with Apple events
and can also be used more generally to designate any subset of data, including
typed data.
The following sections describe the classes that designate data.
The <designator> class is an abstract class from which subclasses that designate
a subset of data are defined. The Framework provides subclasses of the
<designator> class for use with data associated with Apple events. Many of
these subclasses can also be used with other kinds of data, too.
You can define your own subclasses from the <designator> class and create
objects from your subclasses, or you can use objects created from subclasses
provided by the Framework. You should define a class-type method for each
of your subclasses.
Data Interchange
Slot descriptions
container The object in which the designated data resides. You must
use the container: and specify a container.
Initialization
No initialize method is defined for <designator> objects.
Initialization
No initialize method is defined for <selection-designator> objects.
Data Interchange
The <text-designator> class represents textual data. You do not need to define
subclasses from the <text-designator> class, you can create a
<text-designator> object when you need to designate textual data. The
class-type method for this class returns $cText.
Initialization
No initialize method is defined for <text-designator> objects.
Initialization
No initialize method is defined for <character-designator> objects.
Data Interchange
Slot descriptions
range-start The start of a range.
range-stop The end of a range.
Initialization
The initialize method for <range-designator> objects sets the start and stop
bytes of a range if the range-specifier: keyword is specified; otherwise the
method does nothing. The initialize method’s parameters are defined as
follows:
The <offset-designator> class represents data offset from its starting location.
You do not need to define subclasses from the <offset-designator> class, you
Data Interchange
Slot descriptions
offset An offset within an object.
Initialization
The initialize method for <offset-designator> objects sets the offset from the
object associated with the offset-specifier: keyword. The initialize
method’s parameters are defined as follows:
Data Interchange
Table 24-2 shows additional functions that can be used with typed handles.
Data Interchange
Table 24-3 shows functions that can be used with data items.
Table 24-4 shows functions that can be used to access data for exchange.
Data Interchange
Contents
About Drag and Drop 571
Using Drag and Drop Classes 572
Setting up a Drag 572
Setting up a Promise Function 574
Accepting a Drag 575
Receiving a Drop 576
Drag and Drop Objects Reference 576
The <drag> Class 577
The <drag-item> Class 578
The <drag-flavor> Class 579
Drag Event Classes 580
Functions for Drag and Drop 582
Contents 569
570 Contents
C H A P T E R 2 5
The Framework provides drag and drop support, which typically allows you to
move data within or between windows. This chapter discusses the classes that
support drag and drop and shows how to use them.
The classes shown in Figure 25-1 represent the following kinds of objects:
<drag> Represents a drag operation.
<drag-flavor> Represents the kind of data being dragged.
Setting up a Drag 25
To set up a drag, execute, and terminate a drag operation, you need to take the
following steps:
1. Create a <drag> object
2. Create a <drag-item> object for each item you want to drag
3. Create a <drag-flavor> object for each flavor of data associated with an item.
The data associated with the flavor is either provided when the object is
created or a function, called a promise function, is provided to retrieve the
data when the drop is received. For information about promise functions,
see “Setting up a Promise Function” on page 574.
4. Optionally, call make-object-reference-flavor for each flavor associated
with each item. This is a convenience function used for dragging within the
application’s windows; for dragging out of the application, you must create
<drag-flavor> objects.
8. Call dispose to release any other resources associated with the drag.
Listing 25-1 shows sample code that performs these steps.
if (promise-function)
make(<drag-flavor>, item: item,
promise: promise-function,
data-type: ostype("dvew"));
else
let stream = make(<handle-object-stream>);
write-object(stream, view);
let stream-data = make(<typed-handle>, data-type:
ostype("dvew"),
data-handle: stream.stream-handle);
end block;
end;
end method promise-function;
Accepting a Drag 25
If your view can respond to a drag over it, you can specialize the accept-drag?
method on your view, or you can implement a behavior and specialize the
behavior-accept-drag? method. Listing 25-3 shows a behavior-accept-drag?
method that allows the views to which the behavior is attached to accept local
drags if the type of the flavor is "mine".
if ( accept )
view;
else
next-method ();
end if;
Receiving a Drop 25
If your view can accept a drag over it, it should also be able to receive a drop.
To receive a drop, you can specialize the receive-drop method on your view, or
you can implement a behavior and specialize the behavior-receive-drop
method. Listing 25-3 shows a behavior-receive-drop method that allows the
views to which the behavior is attached to receive the data if the type of the
flavor is "mine".
// For the sake of legibility we will base the flavor on the first
// item in the drag item list
let firstItem = first ( drag.item-list );
let additionFlavor = get-flavor ( firstItem, ostype ( "mine" ));
Slot descriptions
drag-reference The drag reference used internally in calls to the Drag
Manager. You do not need to set this slot.
item-list The list of distinct items that can be dragged by this object.
local? Whether the drag was initiated by this application (#t) or
not (#f). If true (#t), the drag terminates when it enters a
window that is not handled by the current drag handler. If
false (#f), the drag is allowed to enter a window that is not
handled by the current drag handler.
originating-view The view from which the drag started.
current-view The view over which the drag is currently tracked or false
(#f) if the view cannot receive a drag.
hilite-region The part of the current view to highlight when a drag
occurs over the view.
Initialization
The initialize method for <drag> objects sets up the drag reference and drag
items. The initialize method’s parameters are defined as follows:
Slot descriptions
item-reference The item reference number of the item being dragged.
Initialization
The initialize method for <drag-item> objects creates a <drag-flavor> object is
for each of the item’s flavors if the drag is a receiving drag. The initialize
method’s parameters are defined as follows:
Slot descriptions
drag-item The item associated with the flavor of data.
flavor-index The flavor index that identifies the flavor.
flavor-flags The flavor flags, as defined in Inside Macintosh. You can use
the values $flavorSenderOnly, $flavorSenderTranslated,
$flavorNotSaved, and $flavorSystemTranslated.
Initialization
The initialize method for <drag-flavor> objects sets the flavor flags and adds
the flavor (or its promise) to the drag. The initialize method’s parameters are
defined as follows:
Slot descriptions
drag The drag object associated with the event.
track-drag-message The status message from the Drag Manager.
Initialization
No initialize method is defined for <drag-event>, <track-drag-event>, or
<receive-drag-event> objects.
Table 25-2 shows functions that can be used to support drag and drop
operations for views and windows.
Table 25-2 Functions that support drag and drop for views and windows
Table 25-2 Functions that support drag and drop for views and windows
26 Clipboard
Contents
About the Clipboard 587
Using the Clipboard 588
Setting Up the Clipboard Behavior 589
Specifying the Kind of Data to Paste 589
Setting up a Designator for Selected Data 590
Retrieving Data Specified by a Designator 591
Associating Clipboard Data with a View 591
Specifying the Selection 593
Specifying How to Delete Specified Data 593
Clipboard Objects Reference 594
The <clipboard-behavior> Class 594
The <clipboard> Class 594
The <clipboard-flavor> Class 595
Clipboard Command Classes 596
Functions for Clipboard Support 598
Contents 585
586 Contents
C H A P T E R 2 6
Clipboard 26
The classes shown in Figure 26-1 represent the following kinds of objects:
<clipboard-behavior> Represents a behavior that handles clipboard
operations of copy, cut, paste, and clear.
<clipboard> Represents the clipboard.
<clipboard-flavor> Represents the kind of data in the clipboard.
Clipboard
An Apple event may be sent to the application, or the Framework may create
an event when a cut, paste, or clear menu item is selected. The Framework
responds to the Apple event by creating a command object. The commands
allow the operations to be undone and redone. Figure 26-2 shows the clipboard
commands that the Framework creates in response to Apple events.
The classes shown in Figure 26-2 represent the following kinds of objects:
<clipboard-command> An abstract class that represents a command that
handles a clipboard operation.
<clear-command> Represents a command that clears the clipboard.
<cut-command> Represents a command that cuts selected data from
the clipboard.
<paste-command> An abstract class that represents a command that
pastes selected data into the clipboard.
Note
The Framework supports copying to the clipboard without
creating a command object because this operation is not
undoable. ◆
Clipboard
Clipboard
For example, the Framework allows styled or non-styled text to be pasted into
text views. Listing 26-2 shows how these flavors are specified.
Clipboard
Clipboard
currently selected data after making the association. Listing 26-5 shows the
set-selection-data method for text views.
let style-flavor =
if (view.use-styles?)
get-flavor(data, ostype("styl"));
end if;
adjust-extent(view);
make(<range-designator>,
container: view,
start: old-start,
stop: old-start + text-flavor.data-length);
end method;
Clipboard
This example is a special case due to the text being stored in a Macintosh text
edit record, which makes it more efficient to specialize the delete-selection
method instead of the delete-data method.
Clipboard
Slot descriptions
record-clipboard-commands
Specifies whether you what to Cut, Paste, and Clear
commands to be recordable (#t), or not (#f).
Initialization
No initialize method is defined for <clipboard-behavior> objects.
Clipboard
<clipboard>object for you and associates it with the *clipboard* variable. You
seldom need to access this variable.
Listing 26-8 shows the class definition for the <clipboard-behavior> class.
Slot descriptions
clip-change-count The clipboard scrap count. The framework sets this slot for
you. Do not change the value of this slot.
Initialization
No initialize method is defined for <clipboard> objects.
Slot descriptions
data-length The length of this flavor of data.
Clipboard
Initialization
No initialize method is defined for <clipboard-flavor> objects.
Clipboard
Slot descriptions
target The event handler, such as a view, whose contents are
affected by a clipboard command.
undo-selection The designated data that is used to undo the command.
redo-selection The designated data that is used to redo the command.
data-item The clipboard contents.
undo-name The name to appear when the Undo menu item is enabled.
redo-name The name to appear when the Redo menu item is enabled.
Initialization
No initialize method is defined for clipboard command objects.
Clipboard
27 Scripting Support
Contents
About Scripting Support 601
Apple Events 602
Data Structures 602
Properties, Object Specifiers, and Descriptors 603
Using Scripting Support Classes 604
Getting and Setting Property Values 604
Responding to Apple Events 605
Scripting Support Objects Reference 607
The Apple Event Classes 607
The <ae-desc> class 607
The <ae-list> class 608
The <ae-record> class 609
The <apple-event> class 610
The <object-specifier> class 610
Descriptor Classes 611
The <token> class 612
Scripting Event Classes 612
Property Designator Classes 615
The <property> Class 616
The <document-property> Class 616
The <file-property> Class 617
The <text-view-property> Class 617
The <text-view-selection-property> Class 618
The <window-property> Class 618
Scripting Support Functions 619
Contents 599
600 Contents
C H A P T E R 2 7
Scripting Support 27
This chapter describes the scripting support available from the Framework’s
implementation of the Open Scripting Architecture (OSA). To use the scripting
support, you must be familiar with OSA and Apple events as described in
Inside Macintosh: Interapplication Communication. Apple event suites are
described in the Apple Event Registry.
Scripting Support
Apple Events 27
Your application can support any of the Apple events defined by the
Framework and it can implement other Apple events or suites as well. Table
27-1 shows the events that are defined in the Framework.
Delete Revert
Data Structures 27
Many of the Framework’s scripting support objects represent data structures in
the Macintosh toolbox for locating data within a running application, such as
Scripting Support
AEDescList <ae-list>
AERecord <ae-record>
AppleEvent <apple-event>
Scripting Support
Scripting Support
Listing 27-1 Converting between Dylan objects and Apple event descriptor records
make-descriptor(property.text-view.text);
end method;
property.text-view.text := as-string(data);
invalidate-all(property.text-view);
end method;
Note
The property’s container is also invalidated in the
set-property-value method so that the contents will be
redrawn. ◆
Scripting Support
Listing 27-3 shows the get-property method that is executed when a get or set
Apple event occurs and the window associated with the scripting object is in
the target chain. This method creates the property object that specifies how the
Apple event descriptor record is converted and handled.
Scripting Support
window.scripting-object := make(<hello-scripting-object>,
text-view: static-text);
open(window);
end method;
Scripting Support
Slot descriptions
desc-type The kind of data.
desc-handle A handle to the data itself.
Initialization
The initialize method for <ae-desc> objects allows Dylan to garbage collect
the object as soon as it is no longer needed. The initialize method’s
parameters are defined as follows:
The <ae-list> class represents a list of Apple event descriptor records, such as
those that specify the names to be opened by an Open Documents Apple event.
You do not need to define subclasses from the <ae-list> class. You can create
<ae-list> objects. You use <ae-list> objects in the same way that you use
AEDescList data type in the Toolbox.
Scripting Support
Initialization
The initialize method for <ae-list> objects creates an Apple event descriptor
list. The initialize method’s parameters are defined as follows:
The <ae-record> class represents a list of Apple event descriptor records that
you want to refer to as a single object. You do not need to define subclasses
from the <ae-record> class. You can create <ae-record> objects. You use
<ae-record> objects in the same way that you use AERecord data type in the
Toolbox.
Listing 27-7 shows the <ae-record> class definition.
Initialization
No initialize method is defined for <ae-record> objects.
Scripting Support
The <apple-event> class represents a full-fledged Apple event. You do not need
to define subclasses from the <apple-event> class. You can create <apple-event>
objects. You use <apple-event> objects in the same way that you use AppleEvent
data type in the Toolbox. The Framework creates and dispatches Apple Event
objects that are received by the application automatically.
Listing 27-8 shows the <apple-event> class definition.
Initialization
No initialize method is defined for <apple-event> objects.
Initialization
No initialize method is defined for <object-specifier> objects.
Scripting Support
Descriptor Classes 27
The descriptor classes represent the form of the data within a container. You do
not need to define subclasses from these descriptor classes. You can create
objects. Typically, you one of the functions that create a descriptor object, such
as create-offset-descriptor or create-logical-descriptor. For a complete list
of these functions, see Table 27-6 on page 621.
Listing 27-10 shows the class definitions for the descriptor classes.
Initialization
No initialize method is defined for these descriptor objects.
Scripting Support
The <token> class represents an Apple event descriptor record that identifies
either an element in a container or a property of an Apple event object. You do
not need to define subclasses from the <token> class. You can create <token>
objects. Typically, you call make-token from your specialization of the
get-element function to return a <token> object.
Initialization
The initialize method for <token> objects sets up an entry in a table to track
the token’s external reference. The initialize method’s parameters are defined
as follows:
Scripting Support
Slot descriptions
message The data, representing a message, in an Apple event
descriptor record.
reply The data, representing a reply to a message, in an Apple
event descriptor record.
Initialization
The initialize method for <scripting-event> objects creates an Apple event
that corresponds to the <scripting-event> object. It also creates an <ae-desc>
object for the target application if the target is not this application. The
initialize method’s parameters are defined as follows:
target-psn The process serial number of the target machine’s process. Use
the target: serial number to specify the process; otherwise, the
scripting event is directed towards this application.
direct-object A direct parameter containing information for use by the server
application.
Scripting Support
3. The event ID
Listing 27-13 shows the definitions for the scripting event subclasses provided
by the Framework.
define-scripting-event(<open-application-event>,
$kCoreEventClass, $kAEOpenApplication)
define-scripting-event(<quit-event>,
$kCoreEventClass, $kAEQuitApplication)
define-scripting-event(<count-elements-event>,
$kAECoreSuite, $kAECountElements)
define-scripting-event(<create-element-event>,
$kAECoreSuite, $kAECreateElement)
define-scripting-event(<do-objects-exist-event>,
$kAECoreSuite, $kAEDoObjectsExist)
define-scripting-event(<get-class-info-event>,
$kAECoreSuite, $kAEGetClassInfo)
define-scripting-event(<get-data-size-event>,
$kAECoreSuite, $kAEGetDataSize)
Scripting Support
define-scripting-event(<get-event-info-event>,
$kAECoreSuite, $kAEGetEventInfo)
define-scripting-event(<get-suite-info-event>,
$kAECoreSuite, $kAEGetSuiteInfo)
define-scripting-event(<make-objects-visible-event>,
$kAEMiscStandards, $kAEMakeObjectsVisible)
Scripting Support
■ text view
■ text view selection
■ window
The following sections describe the property classes provided by the
Framework.
The <property> class represents a property of an Apple event element. You can
define subclasses from the <property> class and create objects from your
subclass when you need to designate a property that is not handled by the
Framework. The class-type method for this class returns $cProperty.
Listing 27-14 shows the definition of the <property> class.
Slot descriptions
property-type A property of an Apple event class, such as $pFont for the
font property of a $cParagraph class.
Initialization
No initialize method is defined for <property> objects.
Scripting Support
Initialization
No initialize method is defined for <document-property> objects.
Initialization
No initialize method is defined for <file-property> objects.
Scripting Support
Initialization
No initialize method is defined for <text-view-property> objects.
Initialization
No initialize method is defined for <text-view-selection-property> objects.
Scripting Support
Initialization
No initialize method is defined for <window-property> objects.
Scripting Support
Table 27-4 shows functions that can be used with scripting events.
Table 27-5 shows functions that can be used with Apple event descriptor
objects.
Scripting Support
Table 27-6 shows functions that can be used with Apple event descriptor list
objects and Apple event record objects.
Scripting Support
Table 27-7 shows functions that can be used with Apple event descriptor list
objects and Apple event record objects.
Scripting Support
Table 27-6 shows functions that can be used with token objects.
Scripting Support
Contents
About Environment and Utility Classes 627
About Region Classes 628
About String Classes 628
About Condition Classes 628
About the Busy Cursor Class 629
About the Framework Library Class 629
About External Reference Tables 630
Using Environment and Utility Classes 630
Using Rectangles 630
Using String Classes 631
Using Handle Strings 631
Using Resource Strings 631
Using Condition Classes 632
Using Framework Error Conditions 632
Using OS Error Conditions 632
Using the Busy Cursor Class 633
Using the Framework Library Class 633
Using the External Reference Table Class 634
Geometry Objects Reference 635
The <region> Class 635
The <rect> Class 635
Geometry Functions 637
String Objects Reference 639
The <handle-string> Class 639
The <resource-string> Class 640
String Resource Functions 641
Contents 625
626 Contents
C H A P T E R 2 8
This chapter discusses several kinds of classes that are utilitarian or related to
the operating environment. Utility classes augment classes provided by the
Dylan language. The kinds of Framework utility classes are as follows:
■ geometry-related classes that represent regions and rectangles
■ string classes that represent strings stored in handles or resources
■ condition classes for reporting application-related or operating
system-reported errors
Environment-related classes allow you to determine the state of the
environment and control it. The kinds of Framework environment classes are
as follows:
■ a class that supports cursor animation when the application cannot respond
to an event
■ a class that represents code or other resources that can be used by the
application
■ a class that represents a debugger
■ a class that maps Framework objects inside the application to resources or
events in the operating environment
This chapter also identifies some functions provided by the Framework that
fall into the category of miscellaneous utilities.
the message, the reason string, operation string, and recovery string. The
Framework substitutes the reason string, operation string, and recovery string
into the message string when the message is reported.
The Framework provides a subclass of the <framework-error> class to handle
operating system-related errors. This class, called <os-error>, typically is the
class that you will use to report error codes returned from calls to the
Macintosh toolbox.
For examples that use the Framework’s condition classes, see “Using Condition
Classes” on page 632. For information about the <framework-error> class, see
“The <framework-error> Class” on page 642. For information about the
<os-error> class, see “The <os-error> Class” on page 643.
Using Rectangles 28
The <rect> class represents a rectangle with four slots: top, bottom, left, and
right. You can create a rectangle as follows:
The function call creates an empty rectangle and is equivalent to the following
function calls:
There are many functions that operate on rectangles and convert between
<rect> objects and QuickDraw rectangle objects. For a list of functions
associated with rectangles, see the tables “Point functions” on page 637 and
“Rectangle functions” on page 637. For information about QuickDraw
rectangle objects, see “The QuickDraw Region Class” on page 324.
handle-string;
end method;
You use resource strings when you call the get-string or get-indexed-string
macros. The macros call get-string-from-library and
get-indexed-string-from-library, respectively, which you can use if you want
to specify the library. If you use these macros and functions, it is not necessary
to explicitly create a <resource-string> object. The string is not actually loaded
until you access an element of the string or you explicitly call load-string.
The fail-os-error function creates an <os-error> object and calls the Dylan
error function unless FSWrite returns $noErr.
Note
You can specify the keyword parameter dont-break to be
true (dont-break: #t) if you want to debug the application
before calling error. The call to error occurs, however, as
soon as execution resumes. ◆
The Framework provides a variety of functions for specialized errors, such as
fail-mem-error to detect memory errors. For a list of these functions, see Table
28-1 on page 637.
without-busy-cursor()
StandardGetFile(as(<FileFilterUPP>, 0), type-count, type-list, reply);
end;
define-framework-library("hello-app");
You can specify how to initialize and reset the library with the
set-library-init-function and set-library-reset-function macros,
respectively.
Listing 28-3 shows an example that uses the set-library-init-function macro
to initialize the hello-app library with the init-hello function.
set-library-init-function(init-hello)
■ <rect>
Initialization
No initialize method is defined for <region> objects.
Listing 28-5 shows the class definition for the <rect> class.
Slot descriptions
top The coordinate that specifies the top of the rectangle.
left The coordinate that specifies the left-most side of the
rectangle.
bottom The coordinate that specifies the bottom of the rectangle.
right The coordinate that specifies the right-most side of the
rectangle.
Initialization
No initialize method is defined for <rect> objects.
Geometry Functions 28
Table 28-1 shows functions that you can use with points.
Table 28-2 shows functions that you can use with <rect> objects.
Table 28-3 shows functions that you can use with <rect> objects or <region>
objects.
■ <resource-string>
Slot descriptions
string-handle The handle that contains the characters.
string-offset The start of the string in the handle.
Initialization
No initialize method is defined for <handle-string> objects.
end class;
Slot descriptions
string-library The library that contains the string resource.
string-id The resource ID.
string-index The index within the ID.
Initialization
No initialize method is defined for <resource-string> objects.
■ <os-error>
Slot descriptions
message-string The message, such as “Could not ... because ...”.
reason-string The reason (because clause).
operation-string The action, for example “complete your request”.
recovery-string Suggestions for recovery.
Initialization
No initialize method is defined for <framework-error> objects.
Slot descriptions
error-number The Macintosh OSErr number.
Initialization
The initialize method for <os-error> objects sets the reason and recovery
strings to correspond to the error number. The initialize method’s parameters
are defined as follows:
Table 28-6 shows functions that you can use to manipulate error strings.
read-error-list Internal.
-resource
read-error-lists Internal.
Table 28-7 shows functions that you can use with <os-error> objects.
Initialization
There is no initialize method for <debugger-behavior> objects.
Slot descriptions
busy? Whether the busy cursor is active (#t), or not (#f).
use-color? Whether the busy cursor is a color cursor (#t), or not (#f).
disable-count The number of times the busy cursor has been disabled.
Initialization
The initialize method for <busy-cursor> objects sets up the unique cursor
appearances that display during animation. The initialize method’s
parameters are defined as follows:
slot init-function,
init-value: #f,
init-keyword: init-function:;
slot reset-function,
init-value: #f,
init-keyword: reset-function:;
Slot descriptions
library-name A library associated with the application.
init-function The function the specifies how to set up the library.
reset-function The reset function associated with the library.
library-resource-files
The resource files associated with the application.
library-initialized
True (#t) if the library is initialized; otherwise false (#f).
Initialization
The initialize method for <framework-library> objects adds the library to the
Framework’s list of libraries. The initialize method’s parameters are defined
as follows:
Slot descriptions
object-array Internal.
free-list Internal.
Initialization
The initialize method for <external-reference-table> objects. The initialize
method’s parameters are defined as follows:
657
658
I N D E X
659
I N D E X
660
I N D E X
661
I N D E X
662
I N D E X
663
I N D E X
664
I N D E X
665
I N D E X
666
I N D E X
input-output-argument options 34 K
inset-bounds method 359
inset-region method 328, 638 key-character slot 270
inset slot 359, 377
*install-debug-menu* variable 646
installed? slot 299
installed-menus method 299, 302 L
install-menu method 299, 302
interface definition clauses 11, 39 language file option 122
interface definition options 11 language options 21
interface definitions 11, 18 large-object spaces 196
interface importation 11 last-antimate slot 648
last-clear slot 648
intersect-region method 329, 638
last-command slot 539
intersect-with-region method 329, 639
last-user-item slot 300
invalidate-all method 366
left slot 636
invalidate-all-on-resize? slot 359, 440, 448
invalidate-caches method 367
library, framework 629, 633
library-name slot 650
invalidate-cell method 398
library-resource-files slot 650
invalidate-cursor-region method 367
invalidate-extent-changed-all method 364
list views 387
load-string method 641
invalidate-extent-changed method 364
local? slot 577
invalidate-item method 398
local-bounds method 313, 326, 359
invalidate-location-changed method 364
invalidate method 366
local coordinates 313
local-mouse slot 274
invert-region method 329
local-slots slot 523
is-empty? method 558, 568
local-to-global method 326
is-slot-editable? method 527, 528
local-to-root method 364
is-sub-view-of? method 365
local-to-super method 326
italic? method 330
item-bounds method 398
location 311, 317
location-changed method 366
item-list slot 577
location slot 319
item-reference method 582
lock-buffer method 327
item-reference slot 578
lock-count slot 322
items slot 298
locked? slot 358
low-level value 94
low-level values 101
J
justification method 381, 439
justification-setter method 439 M
machine pointers 138, 146, 152
main-file-creator slot 486
main-file slot 486
667
I N D E X
668
I N D E X
P
O page-increment slot 445
paint-region method 329
object-array slot 652 parent-menu slot 293
object generations 194 part-code slot 274
object-index method 623 Pascal-string-at method 170
object model support classes 226 Pascal-string-at-setter method 170
object streams 514 paste data 589
offset-in-super method 326 peek-byte method 525
offset-region method 328, 638 perform-command method 547
offset slot 565 pixels slot 322
offset-to-column method 397 pix-map slot 322
offset-to-row method 397 pointer-at method 165
old-selection-start slot 543 pointer-at-setter method 166
old-selection-stop slot 543 pointers, typed 555
old-style slot 543, 545 pointer-to-function types 77, 99
old-target slot 275 pointer-to-structure types 98
on? method 442 point-in-region? method 328, 638
on?-setter method 442 point method 637
open? slot 486 point-to-cell method 397
open-data-fork method 500 poll-busy-cursor method 649
open-files method 488, 502 poll-event method 279
opening documents 479, 482 popup menus 431
open-initially? slot 411 popup-style slot 453
open method 276, 364, 415, 487, 500 port-is-window? slot 321
open-resource-fork method 500 pose-modally method 415, 432
Open Scripting Architecture support, see post-command method 537, 548
scripting support post-draw method 367
669
I N D E X
670
I N D E X
671
I N D E X
672
I N D E X
673
I N D E X
674
I N D E X
X
xor-region method 329, 639
Y
youngest generation 194
Z
zoomable? slot 410
675
T H E A P P L E P U B L I S H I N G S Y S T E M
PROJECT MANAGER
Trish Eastman
LEAD WRITER
Linda Kyrnitszke
WRITERS
Marq Laube, Gary McCue
ILLUSTRATOR
Sandee Karr
PRODUCTION EDITOR
Lorraine Findlay
SPECIAL THANKS TO
Kim Barrett, Bob Cassels, Phil Kania,
Ross Knights, Mike Lockwood, David
Moon, Andrew Shalit, David Sotkowitz,
Steve Strassman