Macintosh Common Lisp Reference For Version 2.0
Macintosh Common Lisp Reference For Version 2.0
030-1959-A
Developer Technical Publications
© Apple Computer, Inc. 1992
APPLE COMPUTER, INC.
trademarks of Apple Computer, Even though Apple has
© 1992, Apple Computer, Inc. All
Inc. reviewed this manual, APPLE
rights reserved.
Adobe Illustrator and PostScript MAKES NO WARRANTY
No part of this publication or
are registered trademarks of OR REPRESENTATION,
the software described in it may
Adobe Systems Incorporated. EITHER EXPRESS OR
be reproduced, stored in a
AGFA is a trademark of IMPLIED, WITH RESPECT
retrieval system, or transmitted,
Agfa-Gevaert TO THIS MANUAL, ITS
in any form or by any means,
CompuServe is a registered QUALITY, ACCURACY,
mechanical, electronic,
trademark of CompuServe, Inc. MERCHANTABILITY, OR
photocopying, recording, or
Helvetica, Palatino, and Times FITNESS FOR A
otherwise, without prior
are registered trademarks of PARTICULAR PURPOSE.
written permission of Apple
Linotype Company. AS A RESULT, THIS
Computer, Inc., except in the
HyperCard is a registered MANUAL IS SOLD “AS IS,”
normal use of the software or to
trademark of Claris Corporation. AND YOU, THE
make a backup copy of the
PURCHASER, ARE
software. The same proprietary Internet is a trademark of Digital
ASSUMING THE ENTIRE
and copyright notices must be Equipment Corporation.
RISK AS TO ITS QUALITY
affixed to any permitted copies ITC Zapf Dingbats is a registered
AND ACCURACY.
as were affixed to the original. trademark of International
This exception does not allow Typeface Corporation. IN NO EVENT WILL APPLE
copies to be made for others, BE LIABLE FOR DIRECT,
MacPaint and MacWrite are
whether or not sold, but all of INDIRECT, SPECIAL,
registered trademarks of Claris
the material purchased (with all INCIDENTAL, OR
Corporation.
backup copies) may be sold, CONSEQUENTIAL
Microsoft is a registered
given, or loaned to another DAMAGES RESULTING
trademark of Microsoft
person. Under the law, copying FROM ANY DEFECT OR
Corporation.
includes translating into another INACCURACY IN THIS
UNIX is a registered trademark MANUAL, even if advised of
language or format. You may use
of UNIX System Laboratories, the possibility of such damages.
the software on any computer
Inc.
owned by you, but extra copies THE WARRANTY AND
Simultaneously published in the REMEDIES SET FORTH
cannot be made for this purpose.
United States and Canada. ABOVE ARE EXCLUSIVE
Printed in the United States of
America. L IMITED WARRANTY ON MEDIA AND IN LIEU OF ALL
The Apple logo is a registered AND R EPLACEMENT OTHERS, ORAL OR
trademark of Apple Computer, If you discover physical defects WRITTEN, EXPRESS OR
Inc. Use of the “keyboard” in the manual or in the media IMPLIED. No Apple dealer,
Apple logo (Option-Shift-K) for on which a software product is agent, or employee is
commercial purposes without the distributed, APDA will replace authorized to make any
prior written consent of Apple the media or manual at no modification, extension, or
may constitute trademark charge to you provided you addition to this warranty.
infringement and unfair return the item to be replaced Some states do not allow the
competition in violation of with proof of purchase to exclusion or limitation of
federal and state laws. APDA. implied warranties or liability
Apple Computer, Inc. ALL IMPLIED WARRANTIES for incidental or consequential
20525 Mariani Avenue ON THIS MANUAL, damages, so the above
Cupertino, CA 95014-6299 INCLUDING IMPLIED limitation or exclusion may not
408-996-1010 WARRANTIES OF apply to you. This warranty
Apple, the Apple logo, APDA, MERCHANTABILITY AND gives you specific legal rights,
AppleLink, A/UX, Chicago, FITNESS FOR A and you may also have other
LaserWriter, Macintosh, PARTICULAR PURPOSE, rights which vary from state to
Monaco, MPW, MultiFinder, ARE LIMITED IN DURATION state.
New York, and SANE are TO NINETY (90) DAYS FROM
trademarks of Apple Computer, THE DATE OF THE
Inc., registered in the United ORIGINAL RETAIL
States and other countries. PURCHASE OF THIS
Balloon Help, Finder, PRODUCT.
QuickDraw, and ToolServer are
Contents
iii
The programming procedure in Macintosh Common Lisp / 9
Editing files / 9
Evaluating files / 10
Compiling files / 10
Loading files / 11
Multitasking / 11
Automatic memory management (“garbage collection”) / 12
Ephemeral garbage collection / 12
Full garbage collection / 12
The MCL menus / 13
Apple menu / 14
File menu / 15
Edit menu / 16
Eval menu / 17
Tools menu / 18
Windows menu / 19
Customizing your work space / 20
Global variables in Print Options and Environment / 20
Print Options global variables / 21
Environment global variables / 21
The init file / 24
4 Menus / 85
How menus are created / 87
A sample menu file / 87
The menu-element class / 88
Contents v
The menu bar / 88
Menu bar forms / 88
Menu bar colors / 91
Menus / 93
MCL forms relating to menus / 93
MCL forms relating to elements in menus / 98
MCL forms relating to colors of menu elements / 101
Advanced menu features / 103
Menu items / 105
MCL forms relating to menu items / 106
MCL forms relating to menu item colors / 114
Window menu items / 115
Window menu item functions / 116
Window menu item class / 117
Updating the menu bar / 119
The Apple menu / 119
Example: A font menu / 120
7 Color / 261
Color encoding in Macintosh Common Lisp / 262
MCL expressions governing color / 263
Operations on color windows / 270
Coloring user interface objects / 272
Part keywords / 274
Menu bar / 274
Menus / 274
Menu items / 275
Windows / 275
Dialog items / 275
Table dialog items / 276
Contents vii
8 The Interface Toolkit / 277
The Interface Toolkit / 279
Loading the Interface Toolkit / 279
Editing menus with the Interface Toolkit / 280
Using the menu editing functionality / 280
Creating a new menu bar: Add New Menubar / 282
Getting back to the default menu bar: Rotate Menubars / 282
Deleting a menu bar: Delete Menubar / 283
Creating and editing menus: Add Menu / 283
Creating menu items / 283
Editing menu items / 284
Saving a menu bar / 285
Editing menu bar source code / 285
Editing dialogs with the Interface Toolkit / 286
Using the dialog-designing functionality / 287
Dialog-designing menu items / 287
Creating dialog boxes / 288
Adding dialog items / 290
Editing dialog items / 291
11 Events / 375
Implementation of events in Macintosh Common Lisp / 376
How an event is handled / 376
MCL built-in event handlers / 377
Functions for redrawing windows / 387
Event information functions / 391
The event management system / 393
The cursor and the event system / 401
Event handlers for the Macintosh Clipboard / 405
MCL expressions relating to scrap handlers and scrap types / 406
Contents ix
12 Apple Events / 411
Implementation of Apple events / 412
Receiving Apple events / 412
How to write an Apple event handler / 413
Forms associated with Apple events / 414
Installing Apple event handlers / 417
Installing handlers for queued Apple event replies / 418
Standard Apple event handlers / 420
Sending Apple events / 423
13 Streams / 425
Implementation of streams / 426
MCL expressions relating to streams / 426
Obsolete functions / 439
Contents xi
17 Higher-Level Operating System Interface / 563
Traps and records / 565
Changes from previous versions of Macintosh Common
Lisp / 565
Traps / 566
Loading trap definitions / 567
Defining a trap / 569
Examples of calling traps / 570
Determining record types and record field types / 571
Records / 574
Installing record definitions / 575
The structure of records / 575
Defining record types / 576
Variant fields / 579
Creating records / 580
Creating temporary records withrlet / 580
Creating records with indefinite extent / 582
Using records / 584
Getting information about records / 593
Trap calls usingstack-trap andregister-trap / 594
Low-level stack trap calls / 595
Low-level register trap calls / 597
Lisp macros for calling Macintosh traps / 598
Notes on trap calls / 603
32-bit immediate quantities / 603
Boolean values: Pascal true and false / 604
Contents xiii
Classes and instances / 662
Creating a class with the macro defclass / 662
Creating an instance and giving its slots values / 664
Redefining a class / 665
Allocating the value of a slot in a class / 666
Classes as prototypes of other classes / 667
Methods / 667
Defining a method and creating a generic function / 668
Congruent lambda lists / 669
Documentation of methods / 669
Defining methods on instances / 670
Creating and using accessor methods / 670
Customizing initialization with initialize-instance / 672
Creating subclasses and specializing their methods / 673
Method combination / 674
The primary method / 674
The primary method and the class precedence list / 674
Examples of classes with multiple superclasses / 675
When there is a conflict: Choosing between methods / 676
Choosing between methods associated with direct and with
more distant superclasses / 677
Creating auxiliary methods and using method qualifiers / 678
Mixin classes and auxiliary methods / 680
Extended example / 680
Contents xv
If you’d like to communicate with other MCL programmers / 767
Communicating through Internet / 767
Communicating through Usenet / 768
Communicating through AppleLink / 768
Communicating through CompuServe / 768
Communicating through other services / 768
Bugs and bug fixes / 768
Infrequent announcements of general interest / 769
If you’re a developer: APDA / 769
Index / 771
4 Menus / 85
Table 4-1 Window menu items / 116
Contents
About Macintosh Common Lisp / xxii
Macintosh tools / xxiii
Documentation / xxiii
Documentation conventions / xxv
Courier font / xxv
Italics / xxv
Definition formats / xxvi
Definition formats of CLOS generic functions / xxviii
The generic functioninitialize-instance / xxviii
Argument list punctuation / xxix
Lisp syntax / xxx
Running Macintosh Common Lisp / xxxi
Hardware requirements / xxxi
System software / xxxi
Installing Macintosh Common Lisp / xxxii
Starting a Macintosh Common Lisp session / xxxii
Ending a Macintosh Common Lisp session / xxxii
xxi
About Macintosh Common Lisp
Macintosh Common Lisp (MCL) provides a fluid and flexible environment for
developing software tools and applications. Originally designed to handle the
intricacies of artificial intelligence, Lisp is ideal for the complexities of
programming the Macintosh computer.
Thirty years of evolution have made Lisp both efficient and rich in programmer-
oriented features. Lisp compiles down to code that can be as fast as C code, and its
object-oriented features are better integrated and allow dynamic creation and
destruction of objects more naturally than C or Pascal.
Macintosh Common Lisp also provides a full range of tools and programming aids.
These include an editable Inspector, a source code stepper, a trace facility, a fast
Lisp-oriented editor, and tools that give you quick access to the definitions of
functions and variables.
Code written in other languages can be accessed through MCL’s Foreign Function
Interface.
Macintosh Common Lisp implements Common Lisp and the Common Lisp Object
System as described in the second edition of Common Lisp: The Language , by Guy
Steele, Jr., and others (Digital Press, 1990). It provides partial implementation of
the Metaobject Protocol (MOP) as described in The Art of the Metaobject Protocol, by
Gregor Kiczales and others (MIT Press, 1991). Future updates of Macintosh Common
Lisp will provide expanded MOP support.
For details on Macintosh Common Lisp’s implementation of Common Lisp and the
MOP and the MCL approach to situations not clearly defined by Common Lisp, see
Appendix A, “Implementation Notes.”
In addition, Macintosh Common Lisp provides additional tools for programming and
for interacting with the Macintosh interface.
Macintosh Common Lisp provides major portions of the Macintosh Toolbox as high -
level Lisp objects. This design makes it easy to write programs that use the resources
of the Macintosh interface. With Macintosh Common Lisp, it takes only minutes to
create customized menus and dialog boxes. Specialized types of windows that build
on these standard ones can be created as new system objects. These tools make
programming the Macintosh computer easy.
Macintosh Common Lisp provides complete low-level access to all Macintosh traps
and data structures. In Macintosh Common Lisp version 2, these interfaces have been
completely rewritten for ease of use and robustness.
Macintosh Common Lisp handles the four standard Apple events and provides
facilities for creating and sending Apple events.
Documentation
For documentation of the Common Lisp language and the Common Lisp Object System,
you should also have access to a Common Lisp reference such as the second edition of
Common Lisp: The Language .
This manual is intended for programmers who are familiar with both the Macintosh
interface and Lisp. It doesn’t assume experience programming the Macintosh
computer, just experience using it.
If you’re new to Macintosh Common Lisp, read the manual Getting Started With
Macintosh Common Lisp . It takes you through a short programming session,
gives you tips and shortcuts, and shows you Macintosh Common Lisp’s online
documentation, help, and debugging features, as well as introducing you to some
of the supplied source code.
If you need to learn Lisp, good Common Lisp tutorials are available in Timothy
Koschmann’sA Common Lisp Companion, in Winston and Horn’sLisp, third edition,
in David Touretzky’sCommon Lisp, and in other introductory books on
the language. For a list of these and other useful books, see Appendix F of this
manual, “For More Information.”
If you are new to the Common Lisp Object System, and especially if you are upgrading
from version 1.3 or earlier of Macintosh Common Lisp, read Appendix C of this book,
“The Common Lisp Object System,” and Appendix D, “Converting Your Files to
CLOS.” The fullest description of CLOS appears in Common Lisp: The Language ,
Chapter 28; you should be familiar with that information. An extended CLOS
tutorial is available in Sonya E. Keene’s Object-Oriented Programming in Common
Lisp: A Programmer’s Guide to CLOS (Addison-Wesley, 1989), and Koschmann’s A
Common Lisp Companion also covers CLOS in some detail. See Appendix F of this
manual, “For More Information.”
As you program, you should consult this reference, the online documentation, the
supplied source code, and the examples provided in the MCL directory Examples.
(The Library directory also contains useful code.) Macintosh Common Lisp provides
continuing technical help for programmers via an online bulletin board. On this
board,info-mcl , available from several sources, programmers can consult with one
another and with MCL developers about solving applications problems. Many files
of code are available oninfo-mcl , and you can contribute your own code to it. See
Appendix F, “For More Information.”
This manual follows specific conventions for fonts, notational conventions, Lisp
syntax, and definition formats.
Courier font
In this manual, all MCL code appears in Courier font. When an MCL interaction is
shown, what you type appears in boldface Courier and what Macintosh Common
Lisp responds with is shown in regular Courier.
Courier font always represents exactly what is typed into and returned by the
program, with one exception. In the syntax of definitions, words in Courier beginning
with an ampersand (lambda list keywords) indicate certain standard parts of the
body of a definition. For example,&key indicates that the items following it are
keywords,&optional indicates that all arguments past that point are optional,
and so on.
See Common Lisp: The Language for a full description of this syntax.
Italics
Italics indicate parameter names and place holders (words that you replace on the
screen with an actual value). For example, when using the functionmy-function ,
you see the definition
Type the wordsmy-function and:test as they appear, but substitute some value
for my-arg and more-info .
The same definition format is used for functions, methods, variables, named
constants, classes, macros, and special forms.
The header indicates the name and type of the definition. In the case of a function,
for example, the first line indicates the name of the function and the fact that it is a
function. Its syntax appears below its name and type; it is described; its parameters
are defined; finally, in many cases, it is used in an example.
A definition format always includes a description of the thing being defined; where
appropriate, it also shows its syntax, includes a description of its arguments, and
gives an example of its use. Here are some abridged examples of definition formats.
*fred-default-font-spec* [Variable ]
Example
find-window [Function ]
Description The find-window function returns the frontmost window of the class
class for which a prefix of the window’s title isstring-equal to
title . If no window hastitle as its title, nil is returned.
Like a function, a Common Lisp Object System generic function specifies a procedure,
but the generic function is specialized on the class of the instance to which it is
applied. Thus a generic function may have more than one primary method. The
provided methods of generic functions are listed in the “Syntax” section of the
definition. Their syntax includes a procedure for matching the instance to a class.
Example
This code sets the position ofcheckbox , a checkbox dialog item, in the view ed.
? (setf checkbox (make-instance 'check-box-dialog-item))
#<CHECK-BOX-DIALOG-ITEM #x4CF721>
? (set-view-position ed #@(20 20))
1310740
Macintosh Common Lisp follows the syntactic conventions of Common Lisp; the
complete Common Lisp syntax is described in Chapter 22 of the second edition of
Common Lisp: The Language.
This section explains the hardware and operating system requirements of Macintosh
Common Lisp, the installation process, and the methods for running Macintosh
Common Lisp.
Hardware requirements
Macintosh Common Lisp version 2 requires approximately 4.5 MB of disk space. (The
release notes distributed with Macintosh Common Lisp give exact figures for both
the basic system and options such as the Toolbox interfaces.)
You may wish to turn off the RAM cache and remove memory-hungry system
extension files before starting Macintosh Common Lisp.
Under the limit imposed by Macintosh System 6, Macintosh Common Lisp can access
no more than 8 MB of RAM. This limitation does not exist in System 7.
System software
Macintosh Common Lisp version 2 has been designed to run with either version 6.0.4
and above or version 7.0 of the Macintosh system software. If you have versions older
than 6.0.4, you should upgrade.
To install Macintosh Common Lisp, see the release notes distributed with your
Macintosh Common Lisp package.
To run Macintosh Common Lisp, double-click the Macintosh Common Lisp icon. This
action loads the kernel, initializes the Lisp system, and loads the file init .lisp or
init.fasl (if one of these is present in the same directory as Macintosh Common
Lisp). After this, you will see the MCL main menu, a Listener window, and a
welcome message.
To end an MCL session, choose Quit from the File menu or use the Quit function that
follows. If you have any unsaved files, Macintosh Common Lisp will ask you if you
want to save them before it quits.
quit [Function ]
Syntax quit
Contents
Introducing the MCL environment / 3
The Lisp Listener, an interactive evaluation window / 3
Variables associated with the Listener / 5
Evaluation / 6
Compilation / 7
The MCL editor, Fred / 7
Features of the editor / 8
Standard Macintosh commands and Fred commands / 8
Manipulating windows / 9
The programming procedure in Macintosh Common Lisp / 9
Editing files / 9
Evaluating files / 10
Compiling files / 10
Loading files / 11
Multitasking / 11
Automatic memory management (“garbage collection”) / 12
Ephemeral garbage collection / 12
Full garbage collection / 12
The MCL menus / 13
Apple menu / 14
File menu / 15
Edit menu / 16
Eval menu / 17
Tools menu / 18
Windows menu / 19
Customizing your work space / 20
Global variables in Print Options and Environment / 20
Print Options global variables / 21
Environment global variables / 21
The init file / 24
1
This chapter describes the basic components of the Macintosh
Common Lisp programming environment. It introduces the basics of
the Lisp Listener, the editor, evaluation, compilation (which is
handled incrementally), window manipulation, and the
programming procedure in Macintosh Common Lisp. It briefly
discusses multitasking and MCL memory management. It describes
the MCL tools available from the menu bar. It also provides some
suggestions about customizing your work space.
The sections that follow describe the Lisp environment of Macintosh Common Lisp.
The Lisp Listener(or just the Listener for short) is a special window designed for
interactive Lisp programming (see Figure 1-1). Interaction between the programmer
and Lisp takes place in this special window. You send forms to the Listener, or type
them into the Listener directly, and Macintosh Common Lisp evaluates them and
prints the result in the Listener.
n Text you enter into the Listener appears in boldface. Text that Macintosh Common
Lisp generates does not.
In ordinary use, there is only one Listener window at a time. Like any other window,
the Listener may be closed. If there is no Listener, any attempt to write to
*terminal-io* creates a new Listener. When the Listener is closed, all its text is
lost, but any symbol defined in the Listener remains defined for the duration of the
session.
The following four variables govern the behavior of the Lisp Listener.
*top-listener* [Variable ]
*listener-default-font-spec* [Variable ]
*listener-window-position* [Variable ]
Example
Evaluation
Lisp expressions are easily evaluated from within the Listener or from elsewhere in
Macintosh Common Lisp.
If the last line of text in the Listener is a complete expression, press Return to
evaluate the expression. If the expression is not complete (for example, if there are
unclosed parentheses or quotation marks), then a carriage return is inserted, just as in
a normal editor window.
Lisp expressions can be evaluated from any editor window; it is not necessary to copy
them to the Listener.
Macintosh Common Lisp includes a powerful text editor called Fred (Fred Resembles
Emacs Deliberately), which is an implementation of Emacs, the powerful
programmable editor that is standard in most implementations of Lisp.
Fred includes the usual Macintosh editor features, such as multiple windows, mouse
-
based cut and paste operations, and so on. If you are an experienced Macintosh user,
you can get started with Fred simply by using the editing commands you already
know.
Fred also includes a set of commands designed specifically for Lisp programming.
These commands are described in detail in Chapter 2, “Editing in Macintosh Common
Lisp,” and summarized below. They include commands for manipulating Lisp,
dealing with windows, inspecting functions, and getting help, as well as many
specialized editing commands. As you work with Macintosh Common Lisp, you
should familiarize yourself with them.
Fred commands use two modifier keys, called Control and Meta.
n To type Control modifiers, use the Control key if your Macintosh keyboard has
one. If your Macintosh does not have a Control key, use Command or Command-
Shift, depending on the value of the variable *emacs-mode* . See Chapter 2,
“Editing in Macintosh Common Lisp.”
n To type Meta modifiers on the Macintosh keyboard, use the Option key.
Here are some of the features of the editor. They all work in the Listener window, as
do almost all Fred commands.
n Placing the insertion point after a close parenthesis, or before an open
parenthesis, causes the matching parenthesis to blink. For example, placing the
insertion point after a close parenthesis causes the matching open parenthesis to
blink. This feature is very helpful in balancing parentheses.
n Double-clicking after a close parenthesis, or before an open parenthesis,
highlights to the matching parenthesis. For example, double-clicking before an
open parenthesis highlights forward to the matching close parenthesis. This is
another quick way to check the balance of your parentheses.
n Pressing Tab after a Return indents the new line appropriately.
n Pressing Control-Meta-Q reindents the current expression in a readable way.
n Pressing Meta–close parenthesis moves the cursor into position for typing the next
expression.
n Pressing Enter on the numeric keypad evaluates the selection or the form within
which the insertion point is located.
These features are available to all user-designed windows. You can use them,
suppress them, or use Macintosh Common Lisp to customize any special behavior your
application requires.
Fred, like the Listener, has online documentation. Choose Fred Commands from the
Tools menu to see a window of all Fred commands.
All standard Macintosh editing commands work in the Listener and in Fred windows.
In most circumstances, Macintosh Common Lisp does not care whether you use
Macintosh editing commands, Fred commands, or a combination. The significant
exception is that Fred commands can work more powerfully than their Macintosh
equivalents; for example, the Fred Copy command is more powerful than the
Macintosh Clipboard, and so certain items copied in Fred cannot be retrieved from
the Clipboard. That exception is discussed in more detail in Chapter 2, “Editing in
Macintosh Common Lisp.”
When you edit Lisp code, Macintosh Common Lisp lets you work with multiple
windows on screen. For the most part these are worked with, resized, and closed just
like other Macintosh windows. Three features make it especially easy to move
among Macintosh Common Lisp windows:
n Pressing Command-L makes the Listener the frontmost window.
n Pressing the Option key and clicking the title bar of any window except a modal
dialog makes that window the rearmost window.
n Holding down the Option key when closing a window closes all the windows of
that class.
n Holding down the Command key when closing a window hides the window. Its
title appears in italics in the Windows menu.
This section describes how to use the editor to write programs and how to compile
and load files of Lisp source code.
Editing files
When you begin learning Lisp, you may simply want to type expressions into the
Listener to see what happens. Soon, however, you want to start saving your work.
You do this by editing definitions and other Lisp forms in an editor window, rather
than in the Listener.
To open a file, choose the standard Macintosh Open command from the File menu.
The editor opens and saves files in text-only format, so that they can be shared with
other Macintosh editors, such as QUED and MPW. If you use a word processor as your
editor—for example, Microsoft Word or MacWrite—be sure to save the files in text -
only format with line breaks . This allows Macintosh Common Lisp to read them.
u Note: If you use another editor on a Fred file containing multiple fonts, the Fred
font information is corrupted.
To save files, choose Save or Save As from the File menu and give your file a name.
Evaluating files
To evaluate the contents of an entire file, open the file and choose Eval Buffer from
the Eval menu. The effect is the same as typing every expression in the file into the
Listener; all the definitions in the file are available to Macintosh Common Lisp for
the duration of the session.
Compiling files
When you save Lisp code in editable files, it is saved as simple text. That is, the text
of the definitions and other expressions is saved. The compiled forms of the
expressions are not saved. This means that when you restart Lisp and open the file,
you need to recompile the functions in the file before you can use them. Although the
Macintosh Common Lisp compiler is fast, this can take some time, especially when
you are working on a large project.
To avoid the need to recompile functions every time you restart Lisp, Macintosh
Common Lisp provides file a compiler . The file compiler takes a source code file
(that is, a text file of Lisp forms, including definitions), compiles all the forms in the
file, and saves the compiled versions in another disk file. This file of compiled
forms, called afasl file, can then be quickly loaded into Lisp. (Loading is described
in the next section.)
You can also compile files with the Common Lisp function
compile-file .
Loading files
Loading a file is like opening the file and evaluating all the forms in it. One
difference is that you can load both source files and compiled files. Macintosh
Common Lisp loadsfasl files quickly because the loaded information is already
compiled. Loading source files can take somewhat longer because the compiler
is invoked.
You can load files by choosing Load from the Eval menu or by using the Common Lisp
functionload.
Multitasking
Macintosh Common Lisp has a pseudo-multitasking system that allows editing and
other operations to occur while Lisp code is running (for instance, during evaluation
and compilation). It also means that events are still processed when your main
program is running.
You can stop Lisp operations—except those that cannot be interrupted—by pressing
Command-period or by choosing Abort from the Eval menu. This returns control to the
main Listener loop. You can suspend an operation by choosing Break from the Eval
menu or by pressing Command-comma.
Certain MCL tasks (for instance, garbage collection, described in the next section)
cannot be interrupted. During these operations no other tasks can be performed.
Macintosh Common Lisp has two kinds of automatic memory management, called
ephemeral garbage collection and full garbage collection.
In general, most heap-allocated objects become inaccessible soon after they are
created. The ephemeral garbage collector exploits this by concentrating its efforts on
reclaiming memory allocated to newly created objects.
Only when all three sets are full is a full garbage collection invoked.
Full garbage collection reclaims memory throughout the system. During full garbage
collection, Lisp operation pauses and the cursor turns into the letters
GC. Garbage
collection typically takes between 1 and 10 seconds, depending on the microprocessor
and amount of RAM. During a full garbage collection no other tasks can be performed.
For full details on both kinds of garbage collection, see “Garbage Collection” in
Appendix A, “Implementation Notes.”
This section summarizes the menus and menu items available from the MCL menu
bar. Many of the individual menu commands are described in more detail in other
sections of this manual. For example, the command New, which creates a new editor
window, is described in Chapter 2, “Editing in Macintosh Common Lisp.”
The MCL menu bar is created completely by Lisp code, using the Common Lisp Object
System. You can customize the menu bar and create alternative menu bars; this
process is described in Chapter 4, “Menus,” and in Chapter 3Getting
of Started With
Macintosh Common Lisp .
This section describes the menu bar that appears when you start up an unmodified
version of Macintosh Common Lisp (see Figure 1-2). Keyboard equivalents for
commands are noted after the command names.
The remainder of this section describes the menus in the menu bar.
Apple menu
One menu item on the Apple menu applies to Macintosh Common Lisp. This menu
item, About Macintosh Common Lisp, displays a dialog box showing the version
number of Macintosh Common Lisp.
New ( -N) Creates a new editor window, not initially associated with
any file.
Open… ( -O) Allows you to select a text file and creates a new editor window
for the file.
Open Selected File ( -D) Enabled only when there is a selection in the top editor buffer.
Attempts to parse this selection as a pathname. If successful,
creates an editor window for the pathname’s file. The title of this
menu item changes to reflect the contents of the current selection.
For information on MCL pathname parsing, see the section
“Pathname Structure” in Chapter 9, “File System Interface.”
Close ( -W) Closes the current window. If the contents of the window have
been edited since the last time it was saved, a dialog box asks you
if you want to save or throw away the changes.
Save ( -S) Saves the contents of the active window into the file named in the
title bar of the window. If the window is not associated with a
disk file, Save As is invoked.
Save As... Allows you to specify a directory and filename, and saves the
contents of the active window to that directory/filename.
Save Copy As... Allows you to specify a directory and filename, and saves a copy
of the contents of the active window to that directory/filename.
Revert... ( -R) Reverts to the version of the window contents last saved to disk.
Before the reversion occurs, you are asked to verify whether you
really want to revert to the last version saved.
Page Setup... Allows you to set printing options for the current printer.
Print... ( -P) Brings up the Print File dialog box.
Quit ( -Q) Closes all windows and exits the Lisp environment. If any window
contains revisions that have not been saved to disk, you are given
the option to save them. If you use the keyboard equivalent of
this command, Macintosh Common Lisp asks you to confirm that
you wish to exit.
Table 1-2 shows the menu items that control editing in the Macintosh Common Lisp
environment. The file font-menus.lisp in your MCL Examples folder supplements
these standard commands with a set of font menus.
Undo ( -Z) Undoes the last editor command, if possible. The Undo command
applies to changes to the text, such as cutting, copying, pasting,
and clearing, but does not undo movement of the insertion point.
When the last command cannot be undone, Undo is disabled.
When it is enabled, it usually indicates what it can undo by
changing its name.
Undo More Undoes in order editor commands before the last editor command,
if possible. The same restrictions apply as
with Undo.
Cut ( -X) Deletes the selected text and places it in the Clipboard and on the
kill ring.
Copy ( -C) Copies the selected text to the Clipboard and to the kill ring.
Paste ( -V) Replaces the selected text with the text from the Clipboard. If
there is no current selection, the text is simply inserted at the
cursor location.
Clear Deletes the current selection. The deleted text is not copied to the
Clipboard. (However, like all deleted text, it is pushed onto the
MCL kill ring.)
Select All ( -A) Selects the entire contents of the buffer associated with the active
window.
Search... ( -F) Brings up the String Search dialog box with several options,
including search-and-replace and replace-all. When a search
causes the window to scroll (that is, when the found text isn’t
currently visible in the window), the found text is placed near the
top of the window. The number of lines between the top of the
window and the found text is determined by the global variable
*next-screen-context-lines* .
Eval menu
The Eval menu contains eight menu items, described in Table 1-3.
Eval Selection ( -E) Evaluates the current selection in the top editor window. If there
is no selection and the insertion point is next to a parenthesis, the
expression bounded by the parentheses is evaluated.
Eval Buffer ( -H) Evaluates the entire contents of the top editor buffer. This is
equivalent to Select All followed by Eval Selection.
Load... ( -Y) Presents the standard file dialog box and allows you to select a
file to be loaded into Macintosh Common Lisp. You may load both
.lisp and.fasl files (respectively, uncompiled and compiled
Lisp files).
Compile File... Allows you to select a file for compilation. You are asked to
specify both the source and destination files, using the standard
file dialog box.
Abort ( -period) Cancels the current computation and returns to the read-eval
-
print loop. If Macintosh Common Lisp was in a break loop, it
leaves the loop. A canceled computation cannot be resumed.
(continued)
Break ( -comma) Suspends the current computation and enters a break loop. The
state of the machine can be examined in the break loop (see
Chapter 10, “Debugging and Error Handling”).You can resume the
computation by choosing Continue or by calling the function
continue .
Continue ( -/) Continues the last operation halted by a break or by a continuable
error. This command is disabled when it is not applicable.
Restarts ( -\) Provides a list of possible ways to restart the current operation.
This command is disabled when it is not applicable.
Tools menu
Windows menu
The titles of all visible windows appear as items in this menu. The menu is ordered
by window layer. (That is, the front window—the window currently in use—is the
first menu item and the back window is the last menu item.) To activate a window,
select its menu item.
If you’re not in the Listener window, you can select it by pressing Command-L.
To move the currently selected window to the back, hold down the Option key, then
click the window’s title bar.
To hide a window, click its close box while holding down the Command key. Its title
will appear in italics in the Windows menu.
Macintosh Common Lisp allows you to customize your environment in several ways.
n Several global variables control aspects of the programming environment. You can
set many of these in the dialog boxes available through the Print Options and
Environment commands in the Tools menu. You can predefine all global variables
in your init file (the file init.lisp ).
n It is easy to customize your menu bar to include operations you perform frequently,
or commands that are part of an application environment. The book Getting
Started With Macintosh Common Lisp gives an extended example of creating
commands and adding them to your menu bar; see the section “Making a Menu” in
Chapter 3, “Prototyping.” You can set your menu bar to the state you prefer in your
init file.
n Finally, you can save snapshots of a particular MCL system state, including all of
the above and all the states from files you have loaded. This environment loads
more quickly than loading all the source andfasl files that were used to create
it, and gives you the benefits of a completely known Lisp environment. For details
see Appendix B, “Snapshots and Application Versions of Macintosh Common
Lisp.”
Macintosh Common Lisp provides a number of global variables defining the behavior
of your system. You can customize the most frequently used ones by choosing Print
Options and Environment from the Tools menu.
The options in the Print Options dialog box implement Common Lisp printing
functions as described in Chapter 22, “Input/Output,”Common
of Lisp: The Language .
(See in particular Section 22.1.6.) For example, clicking*PRINT-PRETTY* in the
Print Options dialog box sets the value of the Common Lisp *print-pretty* global
variable to true.
The options in the Environment dialog box set some frequently used MCL variables.
Table 1-5 lists these variables and what they do. A checked variable has the value
true; an unchecked one, the valuenil.
Variable Purpose
Variable Purpose
Variable Purpose
Variable Purpose
When you double-click the Macintosh Common Lisp icon, Macintosh Common Lisp
attempts to load a file called init.lisp or init.fasl from its home folder (that
is, the folder containing Macintosh Common Lisp). The file with the.fasl
extension is a compiled file; the other is a source code file. If both files are found, the
more recent one is loaded.
You can use theinit file to create a default initial environment, for example, to set
the state of various system parameters, load utility files, and so on.
You may want to customize some additional global variables in your
init file. A
possible variable is described next.
If the value is true (the default), the lists are printed specially.
You can also set up Macintosh Common Lisp to install new menus, set up new logical
hosts, and load and open files.
When you start Macintosh Common Lisp by double-clicking a file, the file is loaded
but the init file is not.
If you find you are developing a very complexinit file, you should investigate
creating a heap image instead. See Appendix B, “Snapshots and Application
Versions of Macintosh Common Lisp.”
Contents
The MCL editor / 29
The editing window / 30
Working with the editor / 31
Creating new windows and opening files / 31
Adding text to a file / 31
Saving buffers to files / 31
The minibuffer / 32
The kill ring and the Macintosh Clipboard / 32
Multiple fonts / 33
Packages / 34
Mode lines / 34
An in-package expression / 35
A set-window-package expression / 35
Finding a window’s package / 35
Fred parameters / 36
Normalizing *next-screen-context-lines* / 37
Editing in Macintosh style / 38
Editing in Emacs style / 39
The Control and Meta modifier keys / 39
Disabling dead keys / 40
Fred commands / 41
Help, documentation, and inspection functions / 42
Movement / 43
Selection / 46
Insertion / 49
Deletion / 52
Lisp operations / 54
Window and file operations / 56
Undo commands / 56
Numeric arguments / 57
27
Incremental searching in Fred / 57
Performing an incremental search / 58
Making additional searches / 58
Backing up with the Delete key / 58
Terminating an incremental search / 59
Doing another incremental search / 59
Special incremental search keystrokes / 60
Boyer-Moore search / 61
This chapter discusses the MCL editor, Fred (Fred Resembles Emacs
Deliberately), which combines the standard Macintosh multiple-
window text editor with Emacs, the fully programmable editor that
is a feature of most Lisp implementations.
If you are familiar with other Macintosh editors, you can begin
editing in Macintosh Common Lisp immediately. However, Fred is
much more powerful than most Macintosh editors. This chapter
describes basic Fred concepts and keyboard editing shortcuts.
If you are familiar with other Macintosh editors, you can begin editing in Macintosh
Common Lisp immediately. However, Fred has many more, and more powerful,
features than the general run of Macintosh editors, and it has special features for
programming Lisp.
n Fred includes many specialized Lisp manipulation commands. For example, you
can select complete or partial symbolic expressions, move from level to level of a
symbolic expression, reindent them, get their documentation and argument list,
and inspect them, all with simple keyboard commands.
n Lisp expressions can be evaluated from Fred windows by pressing Enter (that
is, the Enter key on the numeric keypad, not the Return key) with the cursor
position at either end of a top-level expression. You can also highlight an
expression and press Command-E.
n Placing the insertion point after a close parenthesis, or before an open
parenthesis, causes the matching parenthesis to blink. For example, placing
the insertion point after a close parenthesis causes the matching open
parenthesis to blink. This feature is very helpful in balancing parentheses.
n Double-clicking after a close parenthesis, or before an open parenthesis,
highlights to the matching parenthesis. For example, double-clicking before
an open parenthesis highlights forward to the matching close parenthesis.
This is another quick way to check the balance of your parentheses.
n Pressing Tab after a Return indents the new line appropriately.
n Pressing Control-Meta-Q reindents the current expression in a readable way.
n Pressing Meta–close parenthesis moves the cursor into position for typing the
next expression.
n Other Fred commands get information on the argument list of a function or its
documentation, inspect it, and edit its source file. Most of these are available
both on the Tools menu and as keyboard commands.
Figure 2-1 describes the parts of an editor window. At the top, in the title bar, is the
pathname of the file contained in the window. The larger editing area contains text,
which is in a buffer (a copy of the contents of a file). In this case, all of the window’s
contents are visible; however, the window always contains the whole buffer,
whether or not all the contents are currently visible.
At the bottom of the window, the minibuffer displays the name of the window’s
package and other information.
To create a new file, press Command-N or choose New from the File menu. To open an
already existing file, press Command-O or choose Open from the File menu.
Fred works with a mouse and the keyboard, just like other Macintosh text editors
such as MacWrite. However, it understands Lisp and Lisp formatting better than
those text editors. For example:
n Placing the insertion point after a close parenthesis causes the matching open
parenthesis to blink.
n Double-clicking after a close parenthesis highlights backward to the matching
open parenthesis.
n Highlighting one or more expressions and pressing Command-E, or choosing Eval
Selection from the Eval menu, evaluates the selection.
n Pressing Tab after a Return indents the line appropriately.
n Pressing Control-Meta-Q reindents the current expression in a readable way.
n Pressing Meta–close parenthesis moves the cursor into position for typing the next
expression.
See the sections “Editing in Emacs Style” and “Fred Commands” later in this
chapter.
To save the contents of a window, you can use the Command-S command or choose
Save from the File menu. To save the contents under another name, choose Save As
from the File menu.
The Windows menu also displays a small cross to the left of the name of any window
whose contents have been modified and not saved.
The minibuffer
Each Fred window contains a minibuffer for conveying current information to the user.
The minibuffer is at the bottom of the window, to the left of the horizontal scroll
bar. (See Figure 2-1.) Information displayed in the minibuffer includes the package
information for the window. This is the name of the window’s package, if the
window has one, or the value of the variable*package* .
In addition, you can set the text of the minibuffer yourself, as described in Chapter
14, “Programming the Editor.”
Macintosh Common Lisp supports both the standard Macintosh Clipboard and an
Emacs-style kill ring.
Only the traditional Macintosh commands Cut and Copy move text to the Clipboard.
Only the Macintosh command Paste moves text from the Clipboard. The Clipboard
contains only one edit at a time.
In contrast, the Fred kill ring is a circular list that stores and retrieves multiple
pieces of text. Fred’s kill-ring mechanism guarantees that important text is not
permanently lost through accidental deletion. It is a far more powerful mechanism
than the Clipboard.
The kill ring is stored as a circular list in the variable *killed-strings* . You can
retrieve any item from this list using the Fred command keystrokes Control-Y and
Meta-Y, described among the Insertion commands in this chapter.
Fred commands that delete text do not place the text in the Clipboard, and Fred text
retrieval commands do not retrieve text from the Clipboard. When you are cutting
and pasting between Macintosh Common Lisp and another Macintosh application,
you should use the Clipboard editing commands—Command-X, Command-C, and
Command-V—rather than the Fred commands.
Multiple fonts
When you set the font of a Fred window (either programmatically or through a menu),
the resulting behavior depends on whether or not text has been selected. If text is
selected, all the text in the selection is displayed in the new font, and the current
insertion font does not change. If no text is selected, the current insertion font changes to
the new font.
Fred does not automatically reset the insertion font when you move the insertion
point. If the insertion font is 9-point Monaco, typed characters will appear in that
font even if you place the insertion point between two characters displayed in Times
bold. You must always set the insertion font explicitly by setting the window font
when no text is selected.
Font information is retained during cut, copy, and paste operations. You can disable
this feature by setting the variable *paste-with-styles* to nil.
Packages
Any Fred window can have an associated package. Expressions read from the
window are read in the window’s package. If the window doesn’t have a package,
then the value of the variable *package* is used.
The package may be set in three ways: through a mode line at the start of the buffer
that is contained in the window, through anin-package statement, and through
the generic functionset-window-package . These three methods are not
interchangeable. The circumstances under which each method can be used are
described in this section.
Mode lines
To give a new, empty Fred window a package, you can add a prototype mode line by
giving the Fred command Control-Meta-M. Then edit it to suit and use the Fred
command Control-Meta-Shift-M to reparse the mode line and set the window
package.
If present, the mode line must be the first nonempty line in the window’s contents. It
begins with one or more semicolons, followed by -*- (and often byMode: LISP and a
semicolon), followed by the package declaration.
For example, the following mode line causes expressions in the window to be read in
the CCL package:
;-*- Mode: Lisp; Package: CCL -*-
Here are possible package specifications and the forms to which they are
equivalent.
n Package: FOO is equivalent to (in-package "FOO") .
n Package: (FOO) is equivalent to (make-package "FOO").
n Package: (FOO (bar baz)) is equivalent to (make-package "FOO" :USE
'("BAR" "BAZ"))).
n Package: (FOO &rest x) is equivalent to (apply #'make-package "FOO" x).
The first time the package is needed to read an expression in the buffer, the package
is created from the mode line specification, and the window’s package is set to the
created package.
Anin-package expression
If there is no mode line, Fred looks for anin-package form at the beginning of the
file. This form must be either the first form in the file or the second form when the
first form defines a package withdefpackage .
If there is an in-package form but the package does not exist, the window’s
package is set tonil and expressions read from the contents of the window are read
in the package that is the value of *package* . If the package is being created with
defpackage , you must make sure that the value of*package* either is or uses the
package "COMMON-LISP" .
Once the package exists, use the Fred command Control-Meta-Shift-M to parse the
mode line and set the window package.
u Note: The search for the in-package form does not account for the read-time
conditionals #+ and #-.
A set-window-package expression
If you don’t use either of the above methods, you can use the generic function
set-
window-package . The method for Fred windows takes two arguments, a Fred
window and a package or a symbol that names a package.
You can find the package associated with a Fred window by calling the generic
functionwindow-package , with the window as the argument, or by looking in the
minibuffer.
The parameters in Table 2-1 can be used to control some of the behavior of Fred.
Variable Purpose
Variable Purpose
Normalizing *next-screen-context-lines*
Example
Fred supports the standard set of Macintosh editing features and conforms to
Macintosh standards.The basic Macintosh editing commands are available on the
Edit menu, and their keyboard equivalents are supported.
You can cut, copy, and paste text between different windows (including the Listener)
using Macintosh commands.
You can use almost any combination of MCL editing commands and Macintosh
commands; Macintosh Common Lisp does not usually care how you combine them. The
exception is that the MCL kill ring is more powerful than the Macintosh Clipboard,
so the kill ring may overwrite the Clipboard information when you do not initially
expect it.
Fred supports a full suite of keyboard commands for manipulating text. Fred
commands have been defined with care to conform to Emacs conventions. The
exceptions are primarily due to the Macintosh standards and keyboard limitations.
Emacs relies on two modifier keys to indicate command keystrokes. In Emacs, these
modifiers are called Control and Meta. In Macintosh Common Lisp, various
keystrokes may be used to invoke Control and Meta sequences.
n The Emacs Control modifier is accessible through the Macintosh Control key or
through the Command key (on Macintosh keyboards that don’t have a Control
key). In all MCL documentation, whichever key you are using to indicate Control
is referred to as the Control key.
n If the value of *emacs-mode* is nil and your Macintosh does not have a
Control key, press Command-Shift to indicate the Control key and Command
to choose a menu item.
n If the value of *emacs-mode* is true and your Macintosh does not have a
Control key, press the Command key to indicate the Control key and
Command-Shift to choose a menu item.
To issue a Control command, hold down the Control key or the Command key
while you press the letter of the command. For example, to enter Control-X, hold
down the Control key and press X. To enter Control-X Control-S (the Emacs Save
command), hold down the Control key and press X, then continue to hold down the
Control key and press S. To enter Control-X H (the Emacs Select Entire Buffer
command), hold down the Control key and press X, then release the Control key
and press H.
n The Emacs Meta modifier is accessed through the Macintosh Option key. You can
rebind it to the Escape key or another key; see the note in this section. In all MCL
documentation, the key you are using to indicate Meta is referred to as the Meta
key.
To issue a Meta command, hold down the Meta key while you press the letter of
the command. For example, to enter Meta-X, hold down the Meta key and press X.
This differs from some other implementations of Emacs, in which you press and
release the Meta key before pressing the command letter.
You do not need the Macintosh Option character set in ordinary MCL programming.
You can insert a Macintosh Option character into Macintosh Common Lisp by quoting
it; press Control-Q, then the character. For instance, you can insert the bullet sign,
normally the Option-8 keystroke, by pressing Control-Q, then Option-8.
Control-Q works only on the next character typed; if you want to type a second
Option character, press Control-Q again.
The dead-key mechanism can interfere with the use of the Option key as the Meta
key modifier. You can get around this in any of several ways:
n You can install a second keyboard layout that does not support dead keys. A
number of freeware and shareware keyboard layouts are available for this
purpose. You can also make your own keyboard layout by copying and editing the
'KCHR' resource. This resource type is documented in
Inside Macintosh .
If you install a keyboard layout that does not support dead keys, you can insert a
dead-key keystroke in Macintosh Common Lisp by quoting it. For example, you
can generate the character ã by pressing Control-Q Control-N A.
n You can use the Escape key as a Meta key, as described in the previous section. If
you do this regularly, load escape-key.lisp as part of yourinit file.
Fred commands
The following Fred commands are defined in the initial MCL environment. Files in
the Examples folder include additional Fred commands, and you can also write your
own (as described in the section “Defining Fred Commands” in Chapter 14,
“Programming the Editor”). Many commands are case insensitive; that is, you can
press either Control-D or Control-Shift-D.
On the Apple Extended Keyboard, MCL editing uses the six named keys—Help,
Forward Delete, Home, End, Page Up, and Page Down—in addition to the commands
listed here.
Macintosh Common Lisp also uses the mouse for editing, both in the standard
Macintosh way and in a few extended commands. For example, Macintosh Common
Lisp recognizes up to a quadruple mouse click; it also recognizes mouse clicks in
combination with Control and Meta keys. These commands are documented below.
The term current expression, used in the following documentation, denotes the text
currently selected, if any. If no text is selected and the insertion point is next to a
parenthesis, the current expression is between that parenthesis and the matching
parenthesis—for example, between a close parenthesis and the matching open
parenthesis, or between an open parenthesis and the matching close parenthesis. If
no text is selected and the insertion point is inside a symbol, the symbol is the current
expression. In other cases, there is no current expression.
The keystrokes and functions in Table 2-2 give information about Macintosh Common
Lisp and its components.
Movement
During editing, use the functions and keystrokes in Table 2-3 to move the insertion
point. Most of these movement commands can be modified by the Shift key to
establish or extend a selection; see Table 2-4.
The keystrokes in Table 2-4 are used to select text. You can modify most motion
commands with the Shift key to select the region between the original insertion
point and the new insertion point.
In addition, you can use the mouse to select text. If the value of the variable
*multi-click-count* is non-nil (the default), then Macintosh Common Lisp
counts multiple clicks:
n Two clicks select a word.
n Three clicks select a line.
n Four clicks select the entire buffer.
The keystrokes in Table 2-5 are used to insert text and space.
The keystrokes and functions in Table 2-6 are used to delete text and spaces.
The functions and keystrokes in Table 2-7 perform Lisp operations on the current
expression.
The functions and keystrokes in Table 2-8 are used to save and select text
manipulated in windows.
Control-X window-save Saves the contents of the active Fred window to its
Control-S associated disk file. If no file is associated with the
window, the user is requested to supply a filename.
Control-X window-save-as Saves the contents of the active Fred window to a file
Control-W specified by the user.
Control-X edit-select-file Allows the user to select a text file and opens a Fred
Control-V window for editing that file.
Undo commands
The Undo command undoes the effect of previous commands. Functions and keystrokes
associated with Undo are listed in Table 2-9. Successive insertions or deletions, or
multiple replacements via the Search dialog, are considered a single command.
The keystrokes in Table 2-10 multiply the effect of any command to which they can
be applied. (They can always be applied to motion and selection commands.)
When you first press Control-S in a Fred window, Fred displays the prompt
i-search in the window’s minibuffer (ori-search reverse for Control-R).
At this point, you can start typing the characters in your search string.
If you typef, Fred immediately searches for the next occurrence of f after the
insertion point and selects it, scrolling through the text if necessary to make it
visible.
If you then typeo, Fred starts with the currently selectedf and searches forfo. You
can continue typing characters to add to the search string. With each addition, Fred
immediately searches for the next occurrence of the string and selects the found text.
The next occurrence may be a simple extension of the previously found text, or it may
occur later in the buffer.
Suppose you typefoo and Fred finds the string in the buffer, but it is not the right
one. You want a later occurrence of
foo. Press Control-S a second time to search for
the next occurrence offoo. You can continue pressing Control-S to search for
subsequent occurrences of the string.
When a search fails, you hear a beep, and thei-search prompt changes to
Failing i-search. A search may fail because there are no more occurrences of the
string or because you add a character to the search string and that new string cannot
be found in the buffer. In either case, pressing Control-S again at this point causes the
search to begin again at the beginning of the buffer.
The behavior of Control-R is identical to that of Control-S except that the search
proceeds backward from the insertion point to the beginning. When no further
occurrences are found and you press Control-R again, the search begins anew from the
end of the buffer.
Sometimes you may want to change the search string. For example, you may
mistakenly type foot instead offool. Pressing the Delete key has the effect of
undoing the last keystroke in the search string. This deletes the last character of the
search string and, if necessary, resumes the search at the buffer location where the
insertion point was when you typed the last character of the search string. Pressing
Delete several times removes additional characters from the search string and
“moves back” the search further.
If the last keystroke added a block of characters to the search string, pressing Delete
removes the entire block. (See Control-Q, Control-W, and Control-Y in “Special
Incremental Search Keystrokes” later in this chapter.)
Fred keeps track of the last string used in an incremental search. When you do
another incremental search, this string appears in the minibuffer as the default
search string. This feature makes it easy to search several windows for the same
string.
Macintosh Common Lisp now optionally supports the Boyer-Moore search algorithm,
which is faster than the built-in algorithm. If you prefer to use this, load the file
boyer-moore.lisp in your Examples folder.
Contents
Points / 64
How Macintosh Common Lisp encodes points / 64
How Macintosh Common Lisp version 2 stores points / 64
MCL functions relating to points / 65
Fonts / 69
Implementation of font specifications / 69
Implementation of font codes / 70
Functions related to font specifications / 71
Functions related to font codes / 75
System data / 82
Some allied MCL functions give useful data about your Macintosh
system. They are also described in this chapter.
You should read this if you are not already familiar with the MCL
and Macintosh implementations of these concepts.
63
Points
Many Lisp functions that take a point as an argument can accept it as two coordinates
(h andv ) or as a single integer holding both coordinates. If a function takes more
than one point, or has optional arguments, the points must all be passed in encoded
form.
The reader macro#@ converts the subsequent list of two integers into a point. This can
be used for clarity in source code. For example,
#@(30 -100) expands into
-6553570 , an integer that represents the point with a horizontal coordinate of 30
and a vertical coordinate of –100.
In Macintosh Common Lisp version 2, the integer that encodes the x and y coordinates
of a point is automatically converted to a bignum if a fixnum cannot accommodate it.
(For definitions of bignum and fixnum, seeCommon Lisp: The Language.)
In version 1.3, this integer was always a fixnum. There was no provision for
overflowing into a bignum; if the integer became too big, it was simply truncated,
leading to obscure bugs. Because points were always fixnums, they could be compared
with eq.
point-string [Function ]
Example
? (point-string 4194336)
"#@(32 64)"
? (view-position (front-window))
14417924
? (point-string (view-position (front-window)))
"#@(4 220)"
Example
? (point-h 4194336)
32
point-v [Function ]
Example
? (point-v 4194336)
64
point<= [Function ]
Examples
? (make-point 32 64)
4194336
? (make-point 32 nil)
32
? (make-point 32)
32
You can passmake-point the two coordinates of a point, or you can pass it a point as
a single argument. In either case, it returns a point. This makesmake-point very
useful in processing optional argument sets.
? (make-point 40 50)
3276840
? (make-point 3276840)
3276840
? (point-string 3276840)
"#@(40 50) "
? (defun show-point
(h &optional v)
(point-string (make-point h v)))
show-point
? (show-point 32 32)
"#@(32 32)"
? (show-point 3276840)
"#@(40 50)"
Description The add-points function returns a point that is the result of adding
point-1 andpoint-2.
Example
? (point-string (add-points #@(10 10) #@(50 100)))
"#@(60 110)"
subtract-points [Function ]
Example
? (point-string (subtract-points #@(10 10)
#@(3 4)))
"#@(7 6)"
There are two ways of representing fonts in Macintosh Common Lisp, font
specifications and font codes.
Font codes represent font information in a way that accesses the Macintosh Font
Manager directly. Since they don’t need to be interpreted, they are significantly
faster than font specifications. They can be translated into font specifications
explicitly through the function font-spec .
The font name should be a string. It should correspond to a font available in the
System file. You can find out which fonts are available by examining the *font-
list* variable, described in the section “System Data” later in this chapter. Font
names are not case sensitive.
The font size should be an integer, which is always in the range from 1 to 127.
Because of an idiosyncrasy in the Macintosh Operating System, a point size of 0 may
appear to be the same value as a point size of 12.
The font style should be one or more of the following style keywords. Multiple font
styles are allowed. A :plain font style implies the absence of other font styles.
The transfer mode should be one of the following transfer-mode keywords. These
transfer modes are described in Appendix E, “QuickDraw Graphics.”
An error is signaled if more than one name, size, or transfer mode is given in a single
font specification.
real-font [Function ]
font-spec [Function ]
Example
? (string-width "Hi there" '("Monaco" 9 :PLAIN))
48
grafport-write-string [Macro ]
Example
Description The font-info function returns four values that represent (in
pixels) the ascent, descent, maximum width, and leading of
font -spec .
The ascent is the distance from the baseline to the highest ascender
of the font, the descent is the distance from the baseline to the
lowest descender of the font, the maximum width is that of the
widest character in the font, and the leading is the suggested spacing
between lines. Only the font and font-size aspects of font-spec are
used in the calculation. The font styles and transfer mode are not
significant.
Example
? (defun line-height (font-name font-size)
(multiple-value-bind (ascent descent maxwidth leading)
(font-info (list font-name
font-size))
(declare (ignore maxwidth)) ;We don't use this value.
(+ ascent descent leading)))
LINE-HEIGHT
? (line-height "new york" 12)
16
? (line-height "new york" 24)
32
? (line-height "times" 10)
12
Description The view-font generic function returns the font specification used
for drawing text in the window. Due to an idiosyncrasy of the
Macintosh computer, a font size of 0 points may appear as a font size
of 12 points.
font-codes [Function ]
Examples
Here is an example of using old font codes to modify the returned font code:
? (font-codes '("Monaco" 12 :BOLD))
262400
65548
-65280
65535
? (font-codes '("Times" 15))
1310720
65551
-65536
65535
? (font-codes '("Times" 15) 262400 65548)
1310976
65551
-65536
65535
? (font-spec 1310976 65551)
("Times" 15 :SRCOR :BOLD)
font-codes-info [Function ]
Syntax font-codes-info ff ms
The ascent is the distance from the baseline to the highest ascender
of the font, the descent is the distance from the baseline to the
lowest descender of the font, the maximum width is that of the
widest character in the font, and the leading is the suggested spacing
between lines. Only the font and font-size aspects of font-spec are
used in the calculation. The font styles and transfer mode are not
significant.
Example
? (setq w (make-instance 'window
:view-font '("New York" 10 :bold)))
#<WINDOW "Untitled" #xDB5B39>
? (view-font w)
("New York" 10 :SRCOR :BOLD)
? (view-font-codes w)
131328
65546
? (font-spec 131328 65546)
("New York" 10 :SRCOR :BOLD)
grafport-font-codes [Function ]
Syntax grafport-font-codes
set-grafport-font-codes [Function ]
set-wptr-font-codes [Function ]
merge-font-codes [Function ]
Examples
System data
*font-list* [Variable ]
Description The *font-list* variable contains a list of all the fonts installed
in the current Macintosh Operating System, sorted alphabetically.
*pen-modes* [Variable ]
Example
Macintosh traps (and pen-state records) encode pen modes as integers. These integers
match the zero-based numeric position of the keyword in the
*pen-modes* list. So,
for example, the number of:srcor pen mode could be coded (position
as :srcor
*pen-modes*) . The inverse operation (turning a pen-mode integer into a keyword)
can be performed with the Common Lisp function elt.
? *pen-modes*
(:srccopy :srcor :srcxor :srcbic :notsrccopy :notsrcor :notsrcxor
:notsrcbic :patcopy :pator :patxor :patbic :notpatcopy :notpator
:notpatxor :notpatbic)
? (position :srcor *pen-modes*)
1
Example
? *style-alist*
((:plain . 0) (:bold . 1)
(:italic . 2) (:underline . 4)
(:outline . 8) (:shadow . 16)
(:condense . 32) (:extend . 64))
*white-pattern* [Variable ]
*black-pattern* [Variable ]
*gray-pattern* [Variable ]
*light-gray-pattern* [Variable ]
*dark-gray-pattern* [Variable ]
Description These variables hold Macintosh pen patterns. The patterns may be
passed to traps or used with QuickDraw
calls.
*screen-width* [Variable ]
*screen-height* [Variable ]
Description These variables contain the width and height, in pixels, of the
current screen. On a Macintosh Plus or Macintosh SE computer, the
width is 512 pixels and the height is 342 pixels. On a Macintosh II
computer with multiple screens, the values refer to the main screen.
Description These variables contain the number of pixels per inch on the
Macintosh computer screen in the horizontal and vertical directions.
On a Macintosh Plus or Macintosh SE computer, both values are 72.
On other Macintosh computers, the values vary according to the
screen used. On a computer with multiple screens, the values refer to
the main screen.
*menubar-bottom* [Variable ]
Contents
How menus are created / 87
A sample menu file / 87
The menu-element class / 88
The menu bar / 88
Menu bar forms / 88
Menu bar colors / 91
Menus / 93
MCL forms relating to menus / 93
MCL forms relating to elements in menus / 98
MCL forms relating to colors of menu elements / 101
Advanced menu features / 103
Menu items / 105
MCL forms relating to menu items / 106
MCL forms relating to menu item colors / 114
Window menu items / 115
Window menu item functions / 116
Window menu item class / 117
Updating the menu bar / 119
The Apple menu / 119
Example: A font menu / 120
This chapter discusses how menus and menu items are created in
Macintosh Common Lisp, how they are installed, and how you can
customize them.
This chapter first discusses the class structure of menus and menu
items, then discusses the associated MCL functions in detail. It
describes how to add colors to menus and menu items, and discusses a
specialized class, window menu items.
If you are creating your own menus or customizing the MCL menus, you
should read this chapter.
85
A simple MCL application for editing menus, the Interface Toolkit,
is documented in Chapter 8 of this manual and in Chapter 3,
“Prototyping,” ofGetting Started With Macintosh Common Lisp .
You can use the Interface Toolkit without knowing any of the
information here. Before reading this chapter, especially if you are
new to Macintosh Common Lisp, you might try out the Interface
Toolkit to see how MCL menus work.
In Macintosh Common Lisp, menus and menu items are instances of CLOS classes. A
menu is created from the classmenu. A menu item is created from the classmenu-
item. Both menus and menu items inherit from a direct superclass,
menu-element ,
which is an abstract class; it isn’t instantiated directly.
Menus appear in the menu bar, the list of menus visible at the top of the screen. A
menu is not visible until you usemenu–install to add it to the menu bar.
A menu is a list of menu items (which may themselves be menus). Menus can be
installed at the top level of the menu bar or as items on other menus, for
implementing hierarchical menus.
Menus and menu items can be created at any time. They can exist, and you can perform
operations on them, without being installed on the menu bar. For example, menu
items can be added to and removed from menus, whether or not the menus are
installed in the menu bar.
Because of the requirements of the Macintosh Operating System, the Apple menu is a
special case; not all items can be removed from it, and it cannot be removed from the
menu bar.
It is often desirable to separate items in a menu into groups by placing a dotted line
between the groups. A menu item whose title is the string"-" appears as a dotted
line and cannot be selected.
In the Examples folder distributed with your copy of Macintosh Common Lisp, look
at font-menus.lisp for an annotated example of how a typical menu is created.
Loadfont-menus.lisp to see the font menu in action.
Chapter 4 Menus 87
The menu-element class
The general behavior of menus and menu items is defined by the class
menu-
element . Both menu andmenu-item inherit from menu-element , so any method
defined formenu-element is applicable to menus and menu items.
Description This is the class of menu elements, on which menus and menu items
are built. This class is not instantiated directly.
At any given point, a set of menu titles is displayed across the top of the screen. This
group forms themenu bar.
At any time, only one menu bar can be displayed. Other menu bars can be defined,
however, and you can rotate among them.
Description The value of the *menubar* variable is the single instance of the
menubar class.
menubar [Function ]
Syntax menubar
Description The menubar function returns a list of the menus currently installed
in the menu bar.
Example
? (menubar)
(#<APPLE-MENU " "> #<MENU "File"> #<MENU "Edit"> #<MENU "Eval"> #<MENU
"Tools"> #<MENU "Windows">)
set-menubar [Function ]
Description The set-menubar function installs a new set of menus in the current
menu bar.
You can never remove the Apple menu. Even if you call
(set-menubar nil) , the Apple menu remains in the menu bar.
Chapter 4 Menus 89
Example
? (setq foo (menubar))
(#<Apple-Menu " "> ;No Apple character in this font.
#<Menu "File">
#<Menu "Edit">
#<Menu "Eval">
#<Menu "Tools">
#<Menu "Windows">)
;Assume a menu, MY-FROGS-MENU, whose title is "Tree Frogs":
? (set-menubar (list (car foo) my-frogs-menu))
(#<Apple-Menu " ">
#<Menu "Tree Frogs">)
? (menubar)
(#<Apple-Menu " ">
#<Menu "Tree Frogs">)
*default-menubar* [Variable ]
Example
Description The find-menu function returns the first menu in the menu bar that
has string as its title. If no matching menu is found, it
returns nil.
Example
? (find-menu "Edit")
#<MENU "Edit">
Menu titles in the menu bar can be colored. You can set the background color of the
menu bar, give menus and menu items a default color, and specify a default
background color for pull-down menus.
Description The part-color generic function returns the color ofpart , a part
of the menu bar. See Chapter 7, “Color,” for a description of color
encoding.
Chapter 4 Menus 91
Arguments menubar The current menu bar, the only instance of the class
menubar .
part A keyword specifying which part of the menu bar
should be set. The four possible keywords have the
following effects:
:default-menu-title
The default color used for the titles of menus in the
menu bar.
:default-menu-background
The default color used for the background of the pull
-
down menus accessed from the menu bar.
:default-menu-item-title
The default color used for the titles of menu items.
:menubar The background color of the menu bar itself.
Example
? (part-color *menubar* :menubar)
16777215
Arguments menubar The current menu bar, the only instance of the class
menubar .
part A keyword specifying which part of the menu bar
should be set. The keywords are the same as for
part-color .
color The new color, encoded as an integer. (See Chapter 7,
“Color.”)
Example
? (set-part-color *menubar* :menubar *red-color*)
14485510
Argument menubar The current menu bar, the only instance of the class
menubar .
Example
? (part-color-list *menubar*)
(:MENUBAR 14485510 :DEFAULT-ITEM-TITLE 0 :DEFAULT-MENU-BACKGROUND
16777215 :DEFAULT-MENU-TITLE 0)
Menus
Menus contain sets of menu items. Menus can be added to the menu bar, or they can be
added to other menus. When they are added to other menus, they are treated as
menu items; hierarchical menus are implemented in this way.
Chapter 4 Menus 93
initialize-instance [Generic function ]
Description This generic function initializes the menu so that you can add menu
items to it and install it. (When instances are actually made, the
function used ismake-instance , which calls initialize -
instance ; see the example that follows.)
Description The menu-title generic function returns the title of the menu as
a string.
Example
? (menu-title food-menu)
"Food"
? (set-menu-title food-menu "Chinese Menu")
"Chinese Menu"
? (menu-title food-menu)
"Chinese Menu"
Chapter 4 Menus 95
menu-install [Generic function ]
Example
? (menu-deinstall food-menu)
NIL
Example
? (menu-installed-p food-menu)
NIL
Description The menu-disable generic function disables a menu. Its items may
still be viewed, but they cannot be chosen. The menu and its items
appear dimmed. This function has no effect if the menu is already
disabled.
Menus can be enabled and disabled at any time. The effects are
visible only when the menu is installed in the current menubar.
Menus can be enabled and disabled at any time. The effects are
visible only when the menu is installed in the current menubar.
Chapter 4 Menus 97
menu-style [Generic function ]
Description The menu-style generic function returns the font style in which the
menu appears.
The following generic functions are used to add elements to menus, remove elements
from menus, find an element in a menu, and return the elements in a menu. The
element may be either a menu or a menu item.
Example
? (apply #'remove-menu-items food-menu
(menu-items food-menu))
NIL
Chapter 4 Menus 99
menu-items [Generic function ]
Description The menu-items generic function returns a list of the menu items
installed in the menu.
The menu items are listed in the order in which they appear in the
menu.
Example
? (menu-items food-menu)
(#<MENU-ITEM "Stir-Fried Beep">
#<MENU-ITEM "Egg Foo Bar">)
Description The find-menu-item generic function returns the first menu item in
the menu whose name istitle , which should be a string. If no menu
item is titled title , nil is returned.
Example
? (find-menu-item food-menu "Beep")
NIL
? (find-menu-item food-menu "Stir-Fried Beep")
#<MENU-ITEM "Stir-Fried Beep">
Description The help-spec generic function returns the text of the Balloon Help
associated with menu-element . If it has none,nil is returned.
Like the menu bar, menus and parts of menus can be colored.
Description The part-color generic function returns the color ofpart , a part of
the menu. See Chapter 7, “Color,” for a description of color encoding.
Example
? (part-color food-menu :menu-title)
14485510
Description The set-part-color generic function sets the color of part , a part
of the menu specified by the arguments, and returns
color .
Example
? (set-part-color food-menu :menu-title #.*orange-color*)
16737282
Example
? (part-color-list food-menu)
(:MENU-TITLE 17630104)
The advanced menu programmer may find the following MCL forms useful.
Description The menu-update generic function is called whenever the user clicks
in the menu bar or presses a command-key equivalent. The menu -
update method for menus calls the menu’smenu-update -
function on menu if it has one; otherwise it calls menu-item -
update on each item in the menu. This facility is provided so that
menus and menu items can be adjusted to the current program context
before they are displayed. (For example, an item may be checked or
unchecked, enabled or disabled, added, removed, or reordered.)
Example
? (menu-handle food-menu)
#<A Mac Handle, Unlocked, Size 34 #x6118EC>
Description If the menu is installed, the menu-id generic function returns the
unique numeric ID of the menu, used by the Macintosh Operating
System. If the menu is not installed, this function returnsnil. If a
menu is removed from the menu bar and later reinstalled, it may be
given a different ID.
Example
? (menu-id food-menu)
12
*menu-id-object-alist* [Variable ]
*menubar-frozen* [Variable ]
If the value of this variable is nil, the menu bar will be redrawn.
Syntax draw-menubar-if
Description The draw-menubar-if function redraws the menu bar (by calling
the trap #_DrawMenuBar ) if the value of *menubar-frozen* is
nil. If the value of *menubar-frozen* is notnil, no action is
taken.
Menu items
Menu items form the bodies of menus. They are instances of the class
menu-item ,
which is a subclass ofmenu-element . Every menu item is associated with some
action, or occasionally with nil, which means the menu item does nothing.
When you create an instance of a menu item, you include a value for the
:menu -
item-action initialization argument; that value should be a function of no
arguments. You can get that value with the accessor function
menu-item-action -
function and change it with set-menu-item-action-function .
Whenever the user chooses a menu item (by either clicking it or pressing a key
equivalent), the current program is interrupted and the menu item’s definition of the
generic function menu-item-action is run. The defaultmenu-item-action calls
(menu-item-action-function menu-item ) and applies the result to no
arguments.
You can specialize this behavior for your own menu items.
Here is an example of a menu item definition with a simple value for the:menu -
item-action initialization argument.
(MAKE-INSTANCE 'MENU-ITEM
:MENU-ITEM-TITLE "Beep three times"
:MENU-ITEM-ACTION
#'(LAMBDA NIL
(ED-BEEP)
(ED-BEEP)
(ED-BEEP)))
The following MCL forms are provided for programming menu items.
Description The menu-item-title generic function returns the title of the menu
item as a string.
Example
? (menu-item-title hot-machine-item)
"Hunan Lambda"
? (set-menu-item-title hot-machine-item "Szechuan Mac")
"Szechuan Mac"
? (menu-item-title hot-machine-item)
"Szechuan Mac"
Example
Note that when you use this keyboard command, you do not need to type the R as an
uppercase letter; that is, you press Command-R, not Command-Shift-R.
Example
? (menu-item-style yu-shiang-kitty-paws)
:PLAIN
Description The part-color generic function returns the color of the part of the
menu item specified bypart . See Chapter 7, “Color,” for a
description of color encoding.
Description The set-part-color generic function sets the color ofpart tocolor
and returnscolor .
Macintosh Common Lisp provides a special class of menu items for operating on the active
window. These arewindow menu items. Many menu items act only on the active window.
Any window menu item that does not apply to the active window should be disabled (for
example, Save should be disabled when the active window is the Search dialog box).
Window menu items provide an easy way to create menu items that act on the active
window. Window menu items are automatically disabled when the active window is of
the wrong type.
The menu items and their corresponding functions are given in Table 4-1.
Close window-close
Save window-save
Save As… window-save-as
Save Copy As… window-save-copy-as
Revert window-revert
Print… window-hardcopy
Undo undo
Undo More undo-more
Cut cut
Copy copy
Paste paste
Clear clear
Select All select-all
Eval Selection window-eval-selection
Eval Buffer window-eval-whole-buffer
List Definitions window-defs-dialog
Arguments window-menu-item
A window menu item.
initargs The initialization arguments for the window menu
item. They are the same as for menu items:
:menu-item-title
The title of the window menu item.
:command-key
If the value of :command-key is nil, then the
window menu item has no keyboard equivalent. If
the value of :command-key is a character, then
that character key is the equivalent.
Macintosh Common Lisp provides a convenient mechanism for updating the menu bar
to reflect the program state. The update routine is run whenever the user clicks a
menu title in the menu bar or presses a keyboard equivalent. The routine is run
before
a pull-down menu or a menu item is chosen. In this way, the menus and menu items can
be changed before the user sees them.
The update routine is very simple: the generic functionmenu-update is run on every
installed menu. The default version ofmenu-update runsmenu-item-update on
each of its menu items. You can specialize update behavior for a menu or menu item
by defining auxiliary methods of menu-update or menu-item-update .
The Apple menu is treated differently from other menus. In particular, the Apple
menu can never be removed. Callingmenu-deinstall on the Apple menu does
nothing. One implication of this is that the Apple menu remains in the menu bar
even after you call (set-menubar nil) .
If you wish to create an application with its own About menu item in the Apple
menu, first remove all the menu items from the Apple menu and then install your
own. You begin with the expression
(apply #'remove-menu-items *apple-menu* (menu-items *apple-menu*))
Don’t worry: the desk accessories won’t be removed! Once you have done this, you can
add your own menu items to the Apple menu. Any menu items added are
automatically placed above the desk accessories. Normally, an application has one
About menu item and one blank line.
Contents
The implementation of views and windows: The confusing
part / 122
What simple views do / 122
What views do / 123
What windows do / 124
Class hierarchy of views / 124
Summary / 125
For more information / 126
MCL expressions relating to simple views and views / 126
Windows / 152
MCL functions for programming windows / 153
Advanced window features / 175
Supporting standard menu items / 181
Floating windows / 183
121
The implementation of views and windows–The confusing part
The Macintosh Operating System draws and displays by means views. of Views and
their subclasses provide generalized drawing rectangles, store information about
them, and display them.
n The most generalized drawing and display class issimple-view , the class used
for all views that do not have subviews.
n A subclass ofsimple-view is view, which includes all the views that contain
subviews.
n The subclasses ofview include window and its subclasses.
Windowsgovern the relationship of views to the screen. Before a view can draw
itself, it must be contained in a window—a screen display mechanism. Windows
cannot be contained within windows.
Until you are used to it, this relationship can be confusing. In Macintosh Common
Lisp, the classwindow is a subclass ofview, but instances of views are contained
within instances of windows.
Views and windows are implemented this way because views provide a more
generalized behavior than windows. Views know how to draw themselves inside
any coordinate system. Windows know how to draw themselves inside a specialized
coordinate system defined by the screen. Windows also have additional behavior to
perform event handling.
Because windows have the more specialized behavior, they are a subclass
of views.
For many purposes the relationship between views and windows is transparent;
window simply calls the method for its superclass,view.
(Because dialog items have many specialized subclasses and methods, they are
described in a separate place, Chapter 6, “Dialog Items and Dialogs.”)
What views do
Most graphics operations are defined on views. Views and the generic functions
associated with them determine the position of the view in its coordinate system, its
font, its relationship to mouse activity, and whether or not the view is currently
being drawn in.
Views have other views contained within them: for instance, a view can contain
simple views such as radio buttons or checkboxes.
Views draw their contents relative to their own coordinate system. Each view has
its own coordinate system, with the point(0,0) in the upper-left corner of its
content area. The position of all the view’s subviews is defined by this coordinate
system.
For this reason, a view’s subviews are drawn after the view. For example, a static
-
text item in a dialog box is drawn after the dialog box.
When a view draws itself inside its container, it uses the container’s coordinate
system and is clipped to the boundaries of its container. For example, if a static-text
item is too large to fit inside the boundaries of a dialog box, only the part of the item
that fits inside the dialog box is drawn.
Because windows are built on views, the distinction between a view and a window is
transparent for many purposes. You can simply work withwindow , using both
window and the view operations it inherits.
Events (such as keystrokes, presses of the mouse button, and activation events) are
usually handled by the top window and its views. Views and windows can be
redrawn, resized, activated, and so on, in response to events.
Summary
To summarize:
n Simple views have no subviews.
n Views have subviews.
n Views define graphics operations within other views.
n Windows define screen operations.
n Dialogs are windows with slightly different default values, good for
dialog boxes.
Dialog items and dialogs are described in Chapter 6, “Dialog Items and Dialogs.”
For information on the size, resolution, and other physical characteristics of the
display, see Chapter 3, “Points and Fonts.”
The following MCL forms are used to define and program simple views and views.
Description The class simple-view is the basic class of views, from which all
views inherit. A simple view does not have subviews and thus can be
drawn more easily. Views and dialog items are built on simple
views.
Description The view class is the class of views that can include subviews. It is
built on simple-view .
Example
*current-view* [Variable ]
*mouse-view* [Variable ]
Description The *mouse-view* variable is bound to the view that the mouse is
over. This variable is updated by the window-update-cursor
generic function.
Example
with-font-focused-view [Macro ]
Example
Description For each subview ofview of the given subview-type , the macro do-
subviews executesform with subview-var bound to the subview.
Example
Description For each subview ofview of the given subview-type , the generic
functionmap-subviews calls function with the subview as its single
argument.
Example
Example
Examples
The following code adds a checkbox to a window, then checks to see whether it’s
there:
? (setf bim (make-instance 'window))
#<WINDOW "Untitled" #x4E42A9>
? (setf boxy (make-instance 'check-box-dialog-item))
#<CHECK-BOX-DIALOG-ITEM #x4E5249>
? (add-subviews bim boxy)
NIL
? (subviews bim)
(#<CHECK-BOX-DIALOG-ITEM #x4E5249>)
Example
? (view-corners (make-instance 'view
:view-position #@(10 20)
:view-size #@(30 40)))
1310730
3932200
? (point-string 1310730)
"#@(10 20)"
? (point-string 3932200)
"#@(40 60)"
Example
For examples of the use ofinvalidate-view , see in your MCL Examples folder the
files view-example.lisp and text-edit-dialog-item.lisp .
Description The wptr generic function holds the pointer to a window record on
the Macintosh heap. This record can be examined or the pointer
passed to Macintosh traps that require a window pointer.
Examples
Example
This code checks to determine that a simple view (a checkbox dialog item) is
contained in a window:
? (setf checkbox (make-instance 'check-box-dialog-item))
#<CHECK-BOX-DIALOG-ITEM #x4CF721>
? (setf win (make-instance 'window))
#<WINDOW "Untitled" #x4CFBE9>
? (add-subviews win checkbox)
NIL
? (view-window checkbox)
#<WINDOW "Untitled" #x4CFBE9>
Example
Description The view-size generic function returns the size of the view.
Example
Description The set-view-size generic function sets the size of the view.
Example
? (setq foo (make-instance 'fred-window))
#<FRED-WINDOW "New" #x438D21>
? (view-scroll-position foo)
0
? (set-view-scroll-position foo 20 20)
NIL
The null method searches all windows for a view that contains the
point. The null class and its use are documented Common
in Lisp:
The Language, pages 780–783.
Examples
This code determines the subview of the windowwin that contains the
point #@(21 21) .
? (find-view-containing-point win #@(21 21))
#<CHECK-BOX-DIALOG-ITEM #x4CF721>
The following code returns the view that contains the mouse, when you don’t know
which window it’s over:
(find-view-containing-point nil (view-mouse-position nil))
Example
This function might be defined as follows, except that it does not do any consing:
? (defmethod view-click-event-handler-1 ((view view) where)
(dolist (subview (nreverse (subviews view)) view)
(if (point-in-click-region-p subview where)
(return
(view-convert-coordinates-and-click
subview where view)))))
#<STANDARD-METHOD VIEW-CLICK-EVENT-HANDLER-1 (VIEW T)>
Example
convert-coordinates [Function ]
The source view and destination view should be in the same view
hierarchy (that is, they should have a common container, or one
should be contained in the other).
Example
Windows
Windows are a subclass of view. Their behavior is specialized on that of view, and
they inherit slots from view. Windows may contain subviews, but a window cannot
be a subview. (If they could, windows would attempt to display inside windows, and
that is wrong: windows display views.)
Windows are used to display information on the screen. Because windows are views,
graphics operations can also be performed on them. For many applications, the
distinction between a window and a view is insignificant and you don’t need to worry
about views at all. You can simply work with windows, using both window and view
operations.
The following MCL functions are used for creating, reporting on, and modifying
windows.
Example
Here is an example of instantiating a window.
? (setq baz (make-instance 'window
:window-title "Bazwin"
:view-position #@(200 300)
:window-type :tool
:color-p t))
#<WINDOW "Bazwin" #x5DB8C9>
windows [Function ]
Examples
front-window [Function ]
Example
? (front-window)
#<LISTENER "Listener" #x5204C9>
target [Function ]
Syntax target
Description The target function returns the second window on the list of
windows; it is equivalent to(second (windows)) .
Example
? (windows)
(#<LISTENER "Listener" #x49EB31>
#<APROPOS-DIALOG "Apropos" #x532EF1>
#<FRED-WINDOW "New" #x51CC61>)
? (target)
#<APROPOS-DIALOG "Apropos" #x532EF1>
Example
Description The find-window function returns the frontmost window of the class
class for which a prefix of the window’s title isstring-equal to
title . If no window hastitle as its title, nil is returned. (The cross
that appears in the title bar of modified Fred windows is ignored
when comparing the title.)
Example
? (find-window "Listener")
#<LISTENER "Listener" #x5204C9>
? (find-window 'listener)
#<LISTENER "Listener" #x5204C9>
? (find-window "lis")
#<LISTENER "Listener" #x5204C9>
? (find-window "ist")
NIL
For windows with title bars, such as document windows and tool
windows, the position is not the upper-left corner of the title bar but
the upper-left corner of the content area of the window.
Examples
? (setq bim (make-instance 'window
:view-position #@(50 50)))
#<WINDOW "Untitled" #x506829>
? (point-string (view-position bim))
"#@(50 50)"
? (set-view-position bim #@(100 100))
6553700
? (point-string (view-position bim))
"#@(100 100)"
Description The view-size generic function returns returns the size of the
window as a point.
Description The set-view-size generic function sets the size of the window.
*window-default-position* [Variable ]
Description The default position of a newly opened window. The initial value is
#@(6 44) .
*window-default-size* [Variable ]
Description The default size of a newly opened window. The initial value is
#@(502 150) .
Description The view-font generic function returns the font spec used for
drawing text in the window. Due to an idiosyncrasy of the Macintosh
computer, a font size of 0 points may appear as a font size of 12
points.
Description The view-font-codes generic function returns two values, the font -
face code and mode-size code forview ’s font. (Font codes are a more
efficient way of encoding font specs; they are described in
Inside
Macintosh .)
Example
? (setq w (make-instance 'window
:view-font '("New York" 10 :bold)))
#<WINDOW "Untitled" #xDB5B39>
? (view-font w)
("New York" 10 :SRCOR :BOLD)
? (view-font-codes w)
131328
65546
? (font-spec 131328 65546)
("New York" 10 :SRCOR :BOLD)
Description The part-color generic function returns the color of the part of the
window indicated bypart.
Description The set-part-color generic function sets the part of the window
indicated by part to color and returnscolor , encoded as an integer. If
color is nil, the default color is restored.
Example
? (setf fred (make-instance 'fred-window))
#<FRED-WINDOW "New" #x4B4C79>
? (set-part-color fred :content *red-color*)
14485510
? (set-part-color fred :frame 2078484)
2078484
Example
? (part-color-list fred)
(:FRAME 2078484 :CONTENT 14485510)
If you hold down the shift key while selecting a window from the
Windows menu,window-ensure-on-screen is called on it.
The following operations are useful for advanced programmers working with
windows.
Example
*window-default-zoom-position* [Variable ]
The window can still assume other sizes when the user clicks the
zoom box, and other sizes can be set with the function
set-view -
size.
*arrow-cursor*
The standard north-northwest arrow cursor.
*i-beam-cursor*
The I-beam shape used when the cursor is over an
area of editable text.
window-object [Function ]
Example
? (window-object (wptr (target)))
#<FRED-WINDOW "New" #x454909>
with-port [Macro ]
Many of the menu items in the default MCL menu bar operate on the top window.
These menu items are instances of the class
window-menu-item . (See Chapter 4,
“Menus.”) These commands can work in any window if the class of the window has an
appropriate method.
Close window-close
Save window-save
Save As… window-save-as
Save Copy As… window-save-copy-as
Revert window-revert
Print… window-hardcopy
Undo undo
Undo More undo-more
Cut cut
Copy copy
Paste paste
Clear clear
Select All select-all
Eval Selection window-eval-selection
Eval Buffer window-eval-buffer
List Definitions window-defs-dialog
If the class of the active window has a method definition for one of these functions,
then the corresponding menu item is enabled. If the user chooses the menu item, the
function is called on the active window. Enabling of items on the Edit menu is
controlled by the generic functionwindow-can-do-operation , described later in
this section.
The Save menu item is enabled if the class of the active window has
a method definition for window-save , unless the window has a
method definition for window-needs-saving-p and a call to
window-needs-saving-p returns nil. If the window has a method
definition for window-needs-saving-p , then Save is enabled only
if a call to window-needs-saving-p returns true.
Example
? (window-can-do-operation *top-listener* 'paste)
T
Floating windows
Floating windows are a subclass of windows that appear frontmost on the screen.
(That is, they always “float to the top.”) Floating windows are generally used for
creating tool palettes.
Description The class windoid is the class of floating windows, built onwindow .
Floating windows may be mixed in with other window classes, such
as dialog boxes. In this case,windoid should appear first in the
inheritance path.
*windoid-count* [Variable ]
Contents
The dialog functionality in Macintosh Common Lisp / 187
Dialog items / 187
Dialog boxes / 187
A simple way to design dialogs and program dialog
items / 188
Changes to dialogs in Macintosh Common Lisp version 2 / 188
Dialog items / 190
MCL forms relating to dialog items / 190
Advanced dialog item functions / 201
Specialized dialog items / 206
Buttons / 206
Default buttons / 207
Static text / 209
Editable text / 210
Checkboxes / 216
Radio buttons / 218
Table dialog items / 221
Pop-up menu dialog items / 234
Scroll-bar dialog items / 236
Sequence dialog items / 243
User-defined dialog items / 245
Dialogs / 246
Modal dialogs / 247
Modeless dialogs / 248
Simple turnkey dialog boxes / 248
MCL forms relating to dialogs / 256
185
The dialog functionality is very flexible in Macintosh Common Lisp.
Dialog items display information and may initiate an
action when clicked by the user. In Macintosh Common Lisp,
dialog items can appear in any window. They are built from the class
dialog-item , which is not used directly; you specialize it and use
the subclasses. In turn,dialog-item is built from the classsimple -
view, since dialog items have no subviews. Built-in subclasses of
dialog-item include radio buttons, checkboxes, and editable-text
fields, as well as pop-up menus, scroll bars, and tables in dialog
boxes.
Before reading this chapter, you should be familiar with the MCL
implementation of views and windows, described in Chapter 5,
“Views and Windows.” The subclass of dialog-item that supports
editable text is fred-dialog-item , documented in Chapter 14,
“Programming the Editor.”
In the standard Macintosh interface, actions are performed by dialog items within
dialog boxes. Macintosh Common Lisp supports this functionality and makes it more
generalized.
Dialog items
Instead of setting up a specialized class for dialog boxes and alerts, Macintosh
Common Lisp defines any structured communication as simply a collection of dialog
items in a window. You can add dialog items to any view or window, or you can write
specialized classes based onwindow , in which dialog items may appear.
Built-in MCL dialog items include buttons, radio buttons, checkboxes, tables,
editable text, scroll bars, pop-up menus, and static text. They are discussed in the
“Dialog Items” section later in this chapter.
In addition, the sample files in the Examples and Library folders contain code
for kinds of dialog items. Of course, you can also define your own classes of
dialog items.
Dialog boxes
Dialog boxes initiate and control well-defined actions in a structured way. You use
them whenever you want the user to do something complex in which the range of
response is predictable or needs to be controlled. The Print Options dialog box is a
good example; it includes text fields, which the user fills in, and a defined set of
choices that are represented by radio buttons and checkboxes.
Alerts query an action, displaying a message such as “Are you sure you want to
reformat your hard disk?” They request the user to confirm explicitly before
proceeding, or to cancel.
You can write standard Macintosh dialog boxes quite easily, while the same
functionality also adapts well to other uses. For example, you can create a hypertext
system that includes text, graphics, and dialog items, or an interactive forms
manager, or a spreadsheet, all using largely the same code.
Macintosh Common Lisp version 2 contains a dialog design tool, part of the Interface
Toolkit, that works like a simple paint system. You can choose buttons and fields
from a palette and move them into a new dialog. You can set their default states and
actions. This tool is supplied as source code so it can be customized; you’ll find it in
the Interface Tools folder supplied with your copy of Macintosh Common Lisp. Its
operation is described in Chapter 8, “The Interface Toolkit,” and in Chapter 3 of
Getting Started With Macintosh Common Lisp .
If you have used an earlier version of Macintosh Common Lisp, you will find that the
implementation of dialogs has changed substantially, making them more flexible to
use and easier to program.
n The dialog class, which is a subclass ofwindow , exists only for compatibility.
No methods are specialized on it and it adds no slots.
n Dialog items may now be added to all views.
n Some functions have changed to reflect the new definition ofdialog .
n All new functions are CLOS generic functions.
Old New
add-dialog-items add-subviews
add-self-to-dialog install-view-in-window
buffer-char-font buffer-char-font-spec
buffer-replace-font buffer-replace-font-spec
buffer-set-font buffer-set-font-spec
catch-abort use restart-case
catch-error use handler-case
catch-error-quietly ignore-errors
color-window-mixin :color-p initialization argument
:dialog-item-colors :part-color-list intialization argument
dialog-item-default-size view-default-size
dialog-item-dialog view-container
(set-)dialog-item-font (set-)view-font
dialog-item-nick-name view-nick-name
(set-)dialog-item-size (set-)view-size
(set-)dialog-item-position (set-)view-position
ed-skip-fwd-wsp&comments buffer-skip-fwd-wsp&comments
find-named-dialog-items view-named, find-named-sibling
item-named view-named
markp buffer-mark-p
:parent keyword to windows, etc. :class keyword
remove-dialog-items remove-subviews
remove-self-from-dialog remove-view-from-window
window-(de)activate-event-handler view-(de)activate-event-handler
window-buffer fred-buffer
window-click-event-handler view-click-event-handler
window-font view-font
window-hpos fred-hpos
window-line-vpos fred-line-vpos
window-mouse-position view-mouse-position
(set-)window-position (set-)view-position
(set-)window-size (set-)view-size
window-start-mark fred-display-start-mark
window-update fred-update
window-vpos fred-vpos
Dialog items do two things: appear within a view, and perform actions. Generally
speaking, a dialog item inherits its display behavior from simple-view or from its
class; its default methods are also determined at the class level. You can add specific
action at the instance level.
The base class from which all other dialog items inherit is dialog–item . This class
is not meant to be instantiated directly. Instead, it is the superclass from which more
specific classes of dialog items are built.
In addition, you can use sample files in your MCL Examples and Library folders to
make several other kinds of dialog items, including scroll bars, icons, and pop-up
menus, and of course you can create your own subclasses of
dialog-item .
Description The dialog-items generic function returns a list of the dialog items
in view .
make-dialog-item [Function ]
The text of a dialog item has a different meaning for each class of
dialog item. It is the text of static-text and editable-dialog text
items. It is the label displayed inside buttons and to the right of
radio buttons and checkboxes.
If you prefer to put text in a different location, set the text to the
empty string and use a separate static-text item to place the text
where you would like it.
Description The generic functionview-font returns, as a font spec, the font used
by item , or nil if item does not have its own font. (Ifitem does not
have its own font, it uses its container’s font.)
Description The generic functionset-view-font sets the font of the dialog item
to new -font .
If you create a new class of dialog items, you may want to define
view-draw-contents to pay attention to these values.
The following functions can be defined for user-created classes of dialog items. They
can also be shadowed in specialized classes of the predefined dialog items. For
general use of dialog items, you do not need to use the following functions.
Several sample files demonstrate the use of dialog items. In your MCL Examples
folder, text-edit-dialog-item.lisp shows how to implement dialog items if
you do not want to make Fred a part of your implementation. In the Library folder,
graphic-items.lisp , scroll-bar-dialog-items.lisp , andscrolling -
fred-dialog-item.lisp implement several specialized types of dialog items.
The default method sets the size of the dialog item if it does not
already have one, and finds an empty position for the dialog item if
it does not already have a position.
with-focused-dialog-item [Macro ]
Examples
The macrowith-font-focused-view could be defined as follows.
(defmacro with-font-focused-view (view &body body)
(let ((view-sym (gensym)))
`(let ((,view-sym ,view))
(with-focused-dialog-item (view view) ,@body))))
Button, static text, editable text, checkboxes, radio button, tables, sequences, and
user-defined dialog items fall into the category of specialized dialog items.
Buttons
Button dialog items are rounded rectangles that contain text. The following MCL
expressions operate on button dialog items.
Description This is the class used to make buttons. Clicking a button usually has
an immediate result. Buttons are generally given a function for
dialog-item-action-function via the :dialog-item -
action initialization argument.
Example
? (setq pearl (make-instance 'button-dialog-item
:default-button t))
#<BUTTON-DIALOG-ITEM #x42C699>
Default buttons
Default buttons are a convenient subclass of button dialog items; they serve as the
default button. A dialog may have one default button. This button has a bold border
and usually may be selected by one of the keystrokes Return or Enter.
Static text
The next two entries define and initialize the class of static-text dialog items.
Description This is the class of static-text dialog items. Static text may be
positioned anywhere in a dialog window to supply additional
information to the user. The text appears in the window’s font unless
otherwise specified. Clicking text does not generally initiate an
action, but it may.
Depending on the amount of text and the size of the item, the text
may wrap to fit in its area. If the size is not specified, a size that
accommodates the text without wrapping is used.
Editable text
The user can give standard Macintosh commands to edit the text of
such items. For instance, the user can select, cut, copy, and paste the
text of editable-text dialog items.
Description The class key-handler-mixin should be mixed into any class that
handles key events. The classfred-dialog-item includeskey-
handler-mixin .
Example
Here is an example of entering and exiting fields by polling through the key
handlers enter-key-handler andexit-key-handler . The dialog foo contains
two editable-text dialog items, Changing andChecking . Checking is a simple
instance ofeditable-text-dialog-item . Changing is an instance of a subclass,
changer-text-item , which has methods for enter-key-handler andexit-
key-handler . These methods do all the work.
(defmethod enter-key-handler
((changer-text-item changer-text-item) old-text)
(unless (equalp (dialog-item-text Checking)
"Click here to check")
(set-current-key-handler
(view-window changer-text-item) old-text)))
Description The allow-tabs-p generic function returns true if tabs are allowed
in the editable-text dialog item. Otherwise, it returns false.
Description These generic functions are each specialized on thewindow class (as
well as on fred-mixin ; see Chapter 14, “Programming the Editor”).
Each generic function calls the same generic function on the current
key handler of window, if there is one. The methods applicable to
fred-mixin perform the operation.
Checkboxes
Checkboxes are small squares that toggle an X mark on and off when clicked. The
following class and functions govern the behavior of checkboxes.
Radio buttons
Radio buttons are small circles that contain a black dot when they are selected
(“pushed”). Radio buttons occur in clusters, and only one button in a cluster may be
pushed at a time. Clicking a radio button unpushes the previously pushed one. The
following class and functions govern the behavior of radio buttons.
Table dialog items are tables within a window. They allow the user to view a set of
items and select items from the set. These tables may be one- or two-dimensional (see
Figure 6-1). Two-dimensional tables look like spreadsheets. One-dimensional tables
look like the file selection boxes displayed after a user chooses the Save as command.
Each item in a table takes up one cell, and there is an 8 KB limit on the total number of
cells a table may have.
Table dialog items are implemented using the Macintosh List Manager (but are not
called “lists” to avoid confusion with Lisp lists).
All the functions used with other dialog items (such asview-size andview-
position ) work for tables, except that the text of table dialog items is not shown.
Table dialog items are rectangles with a series of cells (see Figure 6-2). Your program
can access information about table dialog items, such as the cells that are selected,
the position of any cell, and the contents of any cell.
A cell is referenced by a point, encoding the horizontal and vertical indices of the
cell within the table.
:table-print-function
The function used bydraw-cell-contents to print
the contents of the cell. The default value is
#'princ . If given, this should be a function of two
arguments, the value to be printed and the stream.
:table-vscrollp
This keyword determines whether the table dialog
item has a vertical scroll bar. The default is to
include a scroll bar if one is needed in order to view
the entire table.
Description The cell-contents generic function returns the contents of the cell
specified by h and v. The method fortable-dialog-item returns
nil.
Description The cell-size generic function returns the size of a cell in the table
dialog item. All the cells have the same size.
Description The set-cell-size generic function sets the cell size according to
h
and v and returns the new size as a point.
Description The cell-font generic function returns the font used by a cell
(specified by h andv) or nil if the cell uses the font of the dialog
item.
Description The cell-select generic function selects the cell specified byh and
v . Previously selected cells are not affected.
Description The selected-cells generic function returns a list of all the cells
selected in the table dialog item. Each cell is represented by a point.
If no cells are selected, nil is returned.
Description The scroll-to-cell generic function causes the table dialog item
to scroll so that the cell specified byh andv is in the upper-left
corner.
Description The point-to-cell generic function returns the cell enclosing the
point represented byh and v, or nil if the point is not within a cell.
A pop-up menu dialog item is a menu within a dialog box or other view containing
dialog items. The Commands menu in Inspector windows is an example of a pop-up
menu. For other examples, look at the fileCCL:library;pop-up-menu.lisp .
Example
A scroll-bar dialog item is a dialog item that is a scroll bar. The following MCL
expressions govern the behavior of scroll-bar dialog items.
A sequence dialog item is a table dialog item that displays the elements of a
sequence, either row by row or column by column. The following class and functions
govern the behavior of sequence dialog items.
You can easily add new classes of dialog items to the classes predefined in Macintosh
Common Lisp.
New classes of dialog items may be specializations of the types of dialog items
listed in this chapter or specializations of the classdialog-item . Functions that
you may wish to define for classes inheriting fromdialog-item are listed in
“Advanced Dialog Item Functions” earlier in this chapter.
Dialogs
How the dialog is used determines whether it is modal or modeless. Instance values
do not determine its mode.
Modal dialogs
Some predefined modal dialogs are documented in “Simple Turnkey Dialog Boxes,”
later in this chapter.
A modeless dialog is available for use whenever it is visible. Like any window that
is not active, a modeless dialog becomes the active window when it is clicked. If a
modeless dialog box is the active window, then appropriate user events trigger the
actions of its items.
Unless otherwise specified, all the text in a dialog (that is, the text of all the items)
appears in the window’s current font. The desired font should be set before the dialog
is made visible (using set-view-font or the :view-font initialization
argument). A special font may be specified for certain dialog items; the rest of the
items appear in the window’s current font.
Macintosh Common Lisp provides four predesigned dialogs for use by applications.
Three of the following dialog boxes provide facilities for dynamic nonlocal exiting
(Common Lisp throwing and catching). Clicking Cancel causesthrow-cancel
a to
the nearest catch-cancel . If this throw is not caught, clicking Cancel causes a
return to the top level (or if it occurs during event processing, the execution of the
interrupted program resumes). Common Lisp throw and catch are described in
Common Lisp: The Language.
throw-cancel [Macro ]
Example
? (catch-cancel
(loop
(throw-cancel 'foo)))
FOO
Description The catch-cancel macro sets up a cancel catch and evaluates form .
It returns the value of the last form if there was no cancel throw.
Otherwise, it returns the symbol :cancel.
message-dialog [Function ]
Example
? (message-dialog "Get along, little dogies"
:ok-text "Giddyap!" :size #@(250 75))
T
y-or-n-dialog [Function ]
Typing the initial character of the text of a button activates it. For example, typing
Y activates the Yes button, whereas typingN activates the No button. In the
following example, typing R activates the Cancel button.
Example
? (y-or-n-dialog "Please turn my landlord into a frog."
:cancel-text "Ribbet")
Example
? (get-string-from-user "Enter a string."
:initial-string "A string.")
? (get-string-from-user "Enter a string."
:ok-text "Return it")
Figure 6-7 shows a dialog box that prompts the user for a string.
To make a disjoint selection, you must hold down the Command key
as you click the selections.
Example
? (select-item-from-list '(cat dog bear)
:window-title "Animals"
:selection-type :disjoint)
; Click the items CAT and BEAR
(BEAR CAT)
The following functions, variables, and macros are useful in programming dialogs
(that is, to program instances ofview or window that contain dialog items).
Remember that any view or window can contain dialog items, which simply act as
subviews within the view, and that any generic function that acts on views or
windows can act on ones containing dialog items.
Description The dialog class is included for compatibility with earlier versions
of Macintosh Common Lisp. No methods in Macintosh Common Lisp
version 2 are specialized ondialog , and it adds no slots.
Example
? (setq dialog1 (make-instance 'window
:window-type :document-with-zoom
:window-title "Button Dialog"
:view-position '(:TOP 60)
:view-size #@(300 150)
:view-font '("Chicago" 12 :SRCOR :PLAIN)
:view-nick-name 'button-dialog
:view-subviews
(list
(setq pearlbutton
(make-dialog-item 'radio-button-dialog-item
#@(15 28)
#@(118 16)
"Pearl Button"
#'(lambda (item)
item
(print "How elegant!"))
:view-nick-name 'pearlie
:view-font '("Chicago" 0 :SRCCOPY :PLAIN)))
(setq flashbutton
(make-dialog-item 'radio-button-dialog-item
return-from-modal-dialog [Macro ]
Arguments values Any values. The following two values have special
meanings:
:closed If a dialog that is used modally has a close box and
the window is closed,return-from-modal -
dialog is called with the value :closed .
:cancel If the user selects the cancel button,return-from -
modal-dialog is called returning :cancel . The
functionmodal-dialog then performs athrow-
cancel .
Contents
Color encoding in Macintosh Common Lisp / 262
MCL expressions governing color / 263
Operations on color windows / 270
Coloring user interface objects / 272
Part keywords / 274
Menu bar / 274
Menus / 274
Menu items / 275
Windows / 275
Dialog items / 275
Table dialog items / 276
You should read this chapter before programming color into your
application.
261
Color encoding in Macintosh Common Lisp
The Macintosh stores colors as 48-bit red-green-blue (RGB) values, with 16 bits each
for the red, green, and blue components. Because current hardware generally supports
a maximum of 24 bits of color, Macintosh Common Lisp encodes colors as fixnums with
8 bits each for red, green, and blue (and 5 bits unused). Therefore, creating a color
encoding does not allocate memory.
If your application requires more than 24 bits of color, you can redefine the color
encoding and decoding operations.
Although they are stored as 8-bit values when encoded in a color, decoded
components are expressed as 16-bit values. This allows compatibility with some
Macintosh tools (such as the Color Picker). Unfortunately, it also means that the low
8 bits of each color component are lost when the color is encoded and decoded. For
example, consider the following expressions, in which the red component of two
colors differs in the low 8 bits. Encoding and decoding loses information:
? (make-color 32256 14000 27323) ;;#$7E00=32256
8271466
? (eql 32256 (color-red 8271466))
T
? (make-color 32333 14000 27323) ;;#$7E4D=32333
8271466
? (equal 32333 (color-red 8271466))
NIL
To compare colors for equality as they are actually displayed on the current display
device, use the functionreal-color-equal .
? (real-color-equal (make-color 32256 14000 27323)
(make-color 32333 14000 27323))
T
*color-available* [Variable ]
make-color [Function ]
Note that the color components change value as they are encoded and decoded.
? (make-color 32333 14000 27323)
8271466
? (color-values 8271466)
32256
13824
27136
color-red [Function ]
Example
? (color-red 8271466)
32256
? (color-red *purple-color*)
17920
color-green [Function ]
Example
? (color-green 8271466)
13824
? (color-green *purple-color*)
0
Example
? (color-blue 8271466)
27136
? (color-blue *purple-color*)
42240
color-values [Function ]
Example
? (color-values 8271466)
32256
13824
27136
real-color-equal [Function ]
Example
? (real-color-equal (make-color 32256 14000 27323)
(make-color 32333 14000 27323))
T
color-to-rgb [Function ]
Example
? (color-to-rgb 8271466)
#<A Mac Zone-Pointer Size 6 #x611930>
? (print-record * :rgbcolor)
#<Record :RGBCOLOR :RED 32256 :GREEN 13824 :BLUE 27136>
rgb-to-color [Function ]
Example
? (make-record :rgbcolor
:red 1000
:green 2000
:blue 3000)
#<A Mac Zone-Pointer Size 6 #x611940>
? (rgb-to-color *) ;*=the last value returned
198411
? (color-values *)
768
1792
2816
with-rgb [Macro ]
Example
This macro is useful because it saves the trouble of having to allocate RGB records
explicitly. (Remember, RGB records are allocated on the Macintosh heap, and so
they are not subject to garbage collection.)
? (defmethod set-fore-color ((window window) color)
(when *color-available*
(with-rgb (rec color)
(with-port (wptr window)
(#_rgbforecolor :ptr rec)))))
#<Method SET-FORE-COLOR (WINDOW T)>
user-pick-color [Function ]
Arguments :color The default color to bring up in the dialog box. The
default is *black-color*.
:prompt The prompt to display in the dialog box. The default
is "Pick a color" .
:position The position of the Color Picker on screen. The
default is calculated by Macintosh Common Lisp.
*pink-color* [Variable ]
*red-color* [Variable ]
*orange-color* [Variable ]
*yellow-color* [Variable ]
*green-color* [Variable ]
*dark-green-color* [Variable ]
*light-blue-color* [Variable ]
*blue-color* [Variable ]
*purple-color* [Variable ]
*brown-color* [Variable ]
*tan-color* [Variable ]
*light-gray-color* [Variable ]
*gray-color* [Variable ]
*dark-gray-color* [Variable ]
*black-rgb* [Variable ]
*white-rgb* [Variable ]
Description These variables contain RGB records for black and white.
The following operations are used to set the foreground and background colors of
windows. If the computer display does not support colors, the colors do not appear.
However, they remain associated with the windows, and if the same window is
moved to a color monitor, they appear in the proper colors.
Windows created with an omitted or null:color-p initarg can display only eight
colors. Specify:color-p as true to use the full range of colors supported by the
hardware.
Example
? (setq mywin (make-instance 'fred-window))
#<FRED-WINDOW "New" #x4BEE99>
? (set-fore-color * *blue-color*)
NIL
Example
? (set-back-color mywin *yellow-color* t)
NIL
with-fore-color [Macro ]
This macro should be used only with a port set. That is, it should be
used within the dynamic extent of a call towith-port or with-
focused-view .
Example
? (setq my-new-win (make-instance 'fred-window))
#<FRED-WINDOW "New" #x4D1399>
? (defmethod type-in-color ((view view) color string)
(with-focused-view view
(with-fore-color color
(princ (format nil "~s" string) view))))
#<STANDARD-METHOD TYPE-IN-COLOR (VIEW T T)>
? (type-in-color my-new-win *blue-color* "Hi there")
NIL
Methods on the following functions are used for setting the colors of user interface
objects such as windows, dialog items, menus, and menu items. This section assumes
some familiarity with the use of these classes.
For each class, a set of keywords identifies the parts that can be colored. The
keywords for the different classes are given in the next section, “Part Keywords.”
Description The part-color generic function returns the color of the part of
object indicated by part.
Example
You can perform color operations on six objects: menu bars, menus, menu items,
windows, dialog items, and table dialog items. This section presents the keywords
that identify which parts of certain objects can be colored.
Menu bar
To perform color operations on the menu bar, use the value of the variable
*menubar* , which contains the one instance of the classmenubar . You can color the
menu bar’s titles and its background using the following keywords:
:default-menu-title
The default color used for the titles of menus in the menu bar.
:default-menu-background
The default color used for the background of the menus in the menu
bar.
:default-menu-item-title
The default color used for the titles of menu items in the menu bar.
Menus
:menu-title
The color used for the title of the menu.
:menu-background
The color used for the background of the menu.
:default-menu-item-title
The default color used for the titles of menu items in the menu.
:item-title
The color used for the title of the menu item.
:item-key
The color used for the command key of the menu item.
:item-mark
The color used for the check mark beside the menu item.
Windows
:frame The color used for the outline of the window and the title bar of :tool
windows.
:hilite The color used for the lines in the title bar of:document windows.
:title-bar
The color used for the background of the title bar in :document
windows and the title in :tool windows.
Dialog items
These part keywords work for built-in dialog items (although not all dialog items
have all of these features). You may wish to use the part colors in theview-draw -
contents method for dialog item classes you define .
:frame The color used for the outline of the dialog item.
:text The color used for the text of the dialog item.
:body The color used for the body of the dialog item.
:thumb The color used for the scroll box of the dialog item. (Scroll bars are
the only built-in dialog item that have a scroll box.)
The color of individual table cells can be set and accessed. Simply use the cell
coordinates as the part keyword. For example,(set-part-color my-table
#@(0 0) 212) sets the cell in the upper-left corner of the table to blue (which is
encoded as212).
Contents
The Interface Toolkit / 279
Loading the Interface Toolkit / 279
Editing menus with the Interface Toolkit / 280
Using the menu editing functionality / 280
Creating a new menu bar: Add New Menubar / 282
Getting back to the default menu bar: Rotate Menubars / 282
Deleting a menu bar: Delete Menubar / 283
Creating and editing menus: Add Menu / 283
Creating menu items / 283
Editing menu items / 284
Saving a menu bar / 285
Editing menu bar source code / 285
Editing dialogs with the Interface Toolkit / 286
Using the dialog-designing functionality / 287
Dialog-designing menu items / 287
Creating dialog boxes / 288
Adding dialog items / 290
Editing dialog items / 291
The Interface Toolkit does two things: edits menus and menu bars,
and creates and edits dialog boxes. In addition, it prints source code
for everything it creates.
277
If you are a novice user of Macintosh Common Lisp, read Chapter 3,
“Prototyping,” ofGetting Started With Macintosh Common Lisp,
which takes you through a sample session with the Interface
Toolkit.
The Interface Toolkit is supplied as source code in the Interface Tools folder. You are
free to examine and modify this source code, to use this source code in developing your
own applications, and to include it, as is or modified, within your applications.
Now your menu bar has one additional menu, the Design menu (Figure 8-1).
In the Interface Toolkit you can edit the default menu bar or another menu bar to
contain any menus you want. You can add menus to a menu bar and remove them. In
the same way, you can add menu items to a menu or remove menu items from a menu.
You can use menu items from the menus on the standard menu bar or make your own
menu items.
You edit both menus and menu items by double-clicking them and specifying their
attributes in an edit window.
More than one menu bar may be active, and you may edit more than one menu bar at
once. You can cut and paste menus among menu bars, including the default menu bar,
just as you would cut and paste text from one buffer to another.
At any time, you can generate source code for a menu or for the entire menu bar.
After you load the Interface Toolkit, choose Edit Menubar, the first menu item on the
Design menu (Figure 8-2). With this menu item you will edit menus and the menu bar.
The floating window contains the standard editor commands Cut, Copy, Paste, and
Clear. You can use this floating window to cut, copy, paste, and clear in situations
where you don’t have a working Edit menu.
The Menubar Editor window, shown in Figure 8-3, contains an editable list of the
items in the current menu bar.
The Menubar Editor window also contains the options listed in Table 8-1.
Option Effect
Add Menu Adds a new, empty menu named “Untitled” to the current menu bar
(the one visible in the Menubar Editor’s editable list and at the top
of the screen).
Rotate Menubars If more than one menu bar is active, makes the next menu bar the
current menu bar. If only one menu bar is active, this command does
nothing.
Add New Menubar Adds a new, empty menu bar named “Untitled” to the active menu
bars. The new menu bar initially contains only the Apple menu.
Delete Menubar Deletes the current menu bar. The next active menu bar becomes the
current menu bar.
Menubar Colors Sets the colors of the menu bar.
Print Menubar Source Creates a new Fred window containing the source code for the
current menu bar.
To create a new menu bar, choose Add New Menubar from the Menubar Editor
window. A new menu bar appears in the Menubar Editor window and at the top of the
screen. This new menu bar initially contains only the Apple menu.
To get to another menu bar or back to the default menu bar, choose Rotate Menubars
from the Menubar Editor window.
To delete a menu bar, choose Delete Menubar from the Menubar Editor window. This
command deletes the currently installed menu bar and removes it from the rotation.
To create a menu, choose Add Menu from the Menubar Editor. The name of the new
menu, “Untitled”, appears in the editable list and in the menu bar at the top of the
screen.
You can change the name of any menu by choosing it and editing its text. To edit a
menu, double-click its name in the list.
Double-clicking the name of a menu creates a new Menu Editor window for menu items,
as shown in Figure 8-4. This window contains an editable list of menu items, which
will be empty if the menu is new, and the options listed in Table 8-2.
Option Effect
Add Menu Item Adds a new, empty menu item named “Untitled” to the current
menu. There are three classes of menu items:menu-item , a menu
item that represents a command;menu, a menu item that opens a
menu; andwindow-menu-item , a window menu item. (See
Chapter 4, “Menus.”)
The menu-item class defaults tomenu-item . To change it, edit
the menu item source code.
You can add further classes by editing the Interface Toolkit source
code.
Menu Colors Sets the colors for parts of the menu.
Print Menu Source Opens a new Fred window and prints the source code for the menu to
it.
When you add menu items to a menu, you can edit them by double-clicking them, as in
Figure 8-5.
Double-clicking a menu item lets you set the features listed in Table 8-3.
Option Effect
Command key Specifies the command key, if any, associated with the menu item.
Disabled Specifies whether the menu item is disabled. The default is nil.
Check Mark Specifies whether the menu item has a check mark beside it. The
default is nil.
Menu Item Action Brings up a Fred window in which you can write or edit code for the
menu item action.
Menu Item Colors Sets the menu item colors.
When you are satisfied with your menu bar, choose Print Menu Source to create source
code. Edit your source code as you like, then save it to a file for future use.
The definitions of some menu items in the standard menu bar must be edited. See the
next section.
The Menu Editor is able to print source code for a menu item only if it has access to the
source code of the action function of the menu item. If it doesn’t, it puts
"Can't find
definition" in the place of the action function source code. You can then edit the
code, putting in the real action function definition.
The source code for an action function is available if it was entered directly
from the menu editor or loaded from a source file with *save-definitions*
set tot.
It is not available if the menu was loaded from afasl file unless the fasl file was
compiled with a true value for the :save-definitions argument tocompile -
file.
If you are customizing your MCL menu bar, you may also need to edit the definitions
in Table 8-4.
The Interface Toolkit includes a quick interface designer for dialogs. With it you can
create a blank dialog box with any set of attributes you want. Then, from a palette of
buttons, radio buttons, checkboxes, editable-text dialog items, tables, and static text,
you can drag in dialog items. You can edit them by double-clicking them. In an edit
window you can specify the attributes of the dialog item, such as color, font, and
associated action.
At any time you can generate source code for the dialog box and its items.
u Note: When Design Dialogs is checked on the Interface Toolkit’s special Design
menu,all dialog boxes are editable, including the Search/Replace dialog box,
the Environment dialog box, and so on. To use dialog boxes rather than edit them,
choose Use Dialogs from the Design menu. (If you are in the middle of editing a
dialog box, your edits will not disappear; the box will simply become usable.)
First load the Interface Toolkit according to the directions in the section “Loading
the Interface Toolkit” earlier in this chapter.
You see a new menu bar at the top of your screen, containing a Design menu. It should
look like the one in Figure 8-2.
The Interface Toolkit menu contains eight items, seven of which relate to dialog
design (see Table 8-5).
Option Effect
Edit Menubar Creates an editor window for the menu bar. This functionality is
discussed in the section “Editing Menus With the Interface Toolkit”
earlier in this chapter.
Use Dialogs Allows you to use dialog boxes in your MCL environment. Choosing
this menu item automatically disables Design Dialogs, discussed
next. These two menu items are the on/off stages of a single toggle.
Turning on one turns off the other. When you first load the Dialog
Designer, Use Dialogs is enabled. When you are using ordinary
MCL dialogs, make sure Use Dialogs is enabled.
(continued)
Option Effect
Design Dialogs Allows you to design dialogs in your MCL environment. Choosing
this menu item automatically disables Use Dialogs and makes all
dialogs editable, but not usable. (As long as you are in the Interface
Toolkit, you can switch back and forth between these modes at
will.)
New Dialog... Brings up a dialog box in which you can specify the type and
attributes of a new dialog box. This menu item is discussed in the
next section, “Creating Dialog Boxes.”
Add Horizontal Guide Adds a dotted horizontal guideline to the dialog box. This
guideline becomes invisible when you choose Use Dialogs. This
menu item is enabled only when you are creating or editing a dialog
box.
Add Vertical Guide Adds a dotted vertical guideline to the dialog window. This
guideline becomes invisible when you choose Use Dialogs. This
menu item is enabled only when you are creating or editing a dialog
box.
Edit Dialog Allows you to specify the title and position of the window that
contains the dialog items. This menu item is enabled only when you
are creating or editing a dialog box.
Print Dialog Source... Prints the source code of the selected dialog box to a new Fred
window. This menu item is enabled only when you are creating or
editing a dialog box.
To create a dialog box, first make sure that a check appears next to Design Dialogs.
Then choose New Dialog from the Design menu. The system displays a dialog box
(Figure 8-6) in which you select the type and attributes of the dialog box you want to
create.
Option Effect
Document This is the default. Creates a dialog box with square corners and
the title “Untitled Dialog.” By default, a document dialog box
includes a close box.
Document with Grow Creates a document dialog box with a size box.
Document with Zoom Creates a document dialog box with a size box and a zoom box.
Tool Creates a dialog box with rounded edges, a solid title bar, and the
title “Untitled Dialog.” By default, it also includes a close box.
Single Edge Box Creates a box with square corners, no title, and no close box. (You
must put a close button within a dialog of this type.) Its edge is a
single line.
Double Edge Box Creates a box with square corners, no title, and no close box. Its edge
is a double line.
Shadow Edge Box Creates a box with square corners, no title, and no close box. Its edge
is shadowed.
Option Effect
Include Close Box Includes a close box in your dialog window. The default value is
true.
Color Window Builds your dialog on top of a Macintosh
CWindowRecord record.
Whenever you change from the Use Dialogs menu item to the Design Dialogs menu
item, you open a palette of dialog items. If you don’t see this palette, choose Use
Dialogs, then choose Design Dialogs again. The palette will appear.
The palette contains one of each type of dialog item: a table, a radio button, a
checkbox, a field of editable text, some static text, and a button. In Figure 8-7, the
palette appears to the right of the new dialog box.
Add dialog items to your dialog box by dragging them from the palette. The original
dialog item will remain on the palette, and a copy with the title “Untitled” will
appear in your dialog box. Figure 8-7 shows an editable-text dialog item being
dragged from the palette to the dialog.
n Figure 8-7 Dragging an editable-text dialog item into an untitled dialog box
To help you place the dialog items, you can add vertical or horizontal guidelines to
your dialog box. Click Add Vertical Guide or Add Horizontal Guide in the Design
menu. You can select and drag a guide to place it. If you place a dialog item with an
edge near a guide, it automatically aligns with the guide.
To resize the display space of any item, first click the item once. Handles
(small
black boxes)appear around the item. Click the pointer on any of these handles, then
drag the item by its handle until you are satisfied with the size.
Edit a dialog item by double-clicking it. A dialog box opens. The dialog box varies
with the kind of dialog item being edited. Figure 8-8 shows a typical example.
Table 8-8 lists the options available for editing dialog items.
Option Effect
Most dialog item subclasses also allow you to edit special parameters associated
with the subclass (see Table 8-9).
Radio buttons
Radio Button Pushed Indicates whether or not the radio button is selected when the
dialog box is first displayed. The default isnil.
Set Item cluster Allows you to move the radio button to a new cluster. Radio button
clusters are numbered sequentially, starting with 0. To set the
button’s cluster, enter a new number.
Buttons
Default Button Indicates whether this is the default button. The default value is
nil.
Edit-text dialog items
Allow Returns Indicates whether carriage returns are allowed in the Edit Text
field. The default value is nil.
Allow Tabs Indicates whether pressing the Tab key inserts a tab in the buffer or
selects the next key handler in the dialog box. The default,nil,
selects the next key handler.
Draw Outline Indicates whether an outline is drawn around the dialog item.
Contents
Filenames, physical pathnames, logical pathnames, and
namestrings / 297
Changes from earlier versions of Macintosh Common
Lisp / 297
Printing and reading pathnames / 298
Pathname structure / 299
Macintosh physical pathnames / 300
Common Lisp logical pathnames / 300
Defining logical hosts / 301
Ambiguities in physical and logical pathnames / 301
More on namestrings and pathnames / 302
Creating and testing pathnames / 303
Parsing namestrings into pathnames / 305
The pathname escape character / 306
Loading files / 308
Macintosh default directories / 310
Structured directories / 313
Wildcards / 317
File and directory manipulation / 318
File operations / 322
Volume operations / 324
User interface / 327
Logical directory names / 330
295
You should read this chapter to familiarize yourself with the
specification of filenames in Macintosh Common Lisp. It is
particularly important if you will deal with other file systems and
must translate between them and the file system of Macintosh
Common Lisp.
The file system interface provides a way of dealing with references to file systems
when code may be running on multiple platforms. MCL code must deal with the file
system requirements of the Macintosh Operating System and, if the code is meant to
be ported, with those of any other operating system on which it is intended to run.
Macintosh Common Lisp specifies filenames by means of pathnames, which can be
specified as namestrings.
The following sections discuss Macintosh physical syntax and Common Lisp logical
pathname syntax. MCL logical directory syntax is described in the section “Logical
Directory Names” later in this chapter.
If you have used previous versions of Macintosh Common Lisp, you should note an
important change in the implementation of the file system.
If your application requires it, you can reproduce the old behavior by defining the
logical directory yourself:
? (def-logical-directory "ccl"
(full-pathname "ccl:"))
u Note: The MCL functionality previously called “logical pathnames” refers to the
MCL-specific system of logical directories and is now called “logical directory
names.” The logical pathname functionality discussed in this chapter refers to
the file system interface design described in Chapter 23 ofCommon Lisp: The
Language.
Common Lisp now specifies that pathnames be printed and read using the
#P syntax.
In Macintosh Common Lisp, pathnames are printed using the Common Lisp#P reader
macro (seeCommon Lisp: The Language, pages 537 and 556), as shown in this
example:
? (make-pathname :directory "hd" :name "foo")
#P"hd:foo"
Macintosh Common Lisp also has a numeric argument that specifies one of four
possible unusual conditions in the pathname.
#1P means that the type is :unspecific .
#2P means that the name is"".
#3P means that the type is :unspecific and the name is"".
#4P means that the namestring represents a logical pathname.
With this convention, Macintosh Common Lisp avoids the potential loss of
information when converting between a pathname and a namestring:
u Note: The numeric argument#nP is not a part of Common Lisp and may be
removed in future releases of Macintosh Common Lisp.
Pathname structure
A Macintosh physical pathname may have multiple colons. The component of the
string preceding its first delimiter does not name a logical host.
? (make-pathname :directory "Style&Design:Glossary:"
:name "frontmatter")
#P"Style&Design:Glossary:frontmatter"
In logical pathname syntax, the host and directory components are indicated by the
characters to the left of the last colon or semicolon. Logical pathnames can be
distinguished from physical pathnames by the following tests:
n The first delimiter between components is a colon.
n The first delimiter is the only colon.
n The string preceding the first delimiter names a defined logical host.
For example, the following is a Common Lisp logical pathname because the first
delimiter between pathname components is a colon, it is the only colon, and
"CCL",
the string preceding the first delimiter, names a defined logical host:
"CCL:Interface Tools;My Menus;custom-menu.lisp"
Macintosh Common Lisp will recognize a logical host only after it has been defined.
To define a logical host, you create and execute setf
a form to setlogical -
pathname-translations for the relevant host. You should do this for every file
system with which you will interact. Here is a very simple example:
? (setf (logical-pathname-translations "home")
`(("**;*.*" ,(merge-pathnames ":**:*.*"
(mac-default-directory)))))
When Macintosh Common Lisp is run, two logical hosts are set up automatically:
n The host "ccl" is set to the directory holding the MCL application.
n The host "home" is set to the directory holding the document that was launched
with Macintosh Common Lisp.
After you define a logical host, you can inspect it by clicking Inspect on the Tools
menu, then clicking Logical Hosts. This displays a list of all the logical hosts used
and generated by Macintosh Common Lisp.
In Macintosh Common Lisp, the colon is both the host delimiter in logical pathname
syntax and the device/directory delimiter in physical pathname syntax. This can
cause ambiguity. For example, in the namestring"bar:foo.lisp" , "bar" can be
either a logical host or a top-level physical directory.
If you have both a top-level physical directory and a logical host with the same
name, there is a possibility of ambiguity. For this reason it is advisable not to give a
physical device and a logical host the same name.
Types may be specified as part of the filename; for instance, you generally specify
the type of an uncompiled file of Lisp source code by giving it the type
.lisp , and
compiled source code by giving it the type.fasl.
Common Lisp provides several functions to create pathnames and to test whether an
object is a pathname. You can create a pathname directly, merge a pathname with
default components, and retrieve components of a pathname.
make-pathname [Function ]
The MCL pathname parser uses the following rules to break namestrings into their
components.
n Unspecified components are given the valuenil. Neither defaults nor logical
directory names are merged at parse time, with the exception of the:host
component of*default-pathname-defaults* . The functionmerge–
pathnames merges one pathname with another by replacingnil components of
its first argument with corresponding components of its second argument. The
function full-pathname performs the logical-to-physical pathname
translation.
n The :directory component is identified as the characters from the end of the
host component to the last colon or semicolon. The colon is the standard Macintosh
separator character for directories. The semicolon is the separator for logical
directory names. A directory name that begins with a colon is relative to the
Macintosh default directory.
n The :name component is identified as the characters that follow the directory
component until either the end of the string or the beginning of the type
component. The period between the name and the type component is only a
separator and is not part of the:name component. To make a name containing a
period, use the escape character (see the next section, “The Pathname Escape
Character”). To specify a file that has an empty string as its name, use a single
period after the directory separator character.
n The :type component is composed of the characters from the name component to
either the version component or the end of the string.
Pathname components
Namestring Host Directory Name Type
If you need to use a colon, semicolon, period, or asterisk as part of a pathname, quote
it with the special escape character, #\∂ (Option-d). This escape character works
very much like the backslash character in strings. Any character preceded by a ∂
loses any special meaning.
Pathname components
Namestring Directory Name Type
Only the needed escape characters are retained (for example, the “∂” before the “o”
in the third line is removed, but the “∂” before the period is retained). Of course, this
mechanism is meant to work only for the MCL additions; you can specify a filename
that includes a colon, but you cannot open such a file, because Macintosh computers do
not accept filenames that contain colons.
u Note: The escape characters are not part of the true name. They are included only
in the Lisp representation of the pathname, not in the Macintosh system’s
representation of the pathname.
Loading files
The following functions and variables govern the loading of files. For Common Lisp
functions governing the loading of files, see Section 23.4, “Loading Files,” starting on
page 657 ofCommon Lisp: The Language .
*.lisp-pathname* [Variable ]
Description The *.lisp-pathname* variable contains the file type for MCL
source code files. The initial value of this variable is #P".lisp" .
*.fasl-pathname* [Variable ]
Description The *.fasl-pathname* variable contains the file type for MCL
compiled files. The initial value of this variable is #P".fasl" .
require [Function ]
Description The require function was once a Common Lisp function but is now
specific to Macintosh Common Lisp. It attempts to load the files in
module if they have not already been loaded.
There are three ways to tell require how to look for a module:
n If pathname is given, it should be a pathname or a list of pathnames whose files
should be loaded in order, left to right.
n If pathname is not given,require first looks in the variable *module-file -
alist*, which is bound to an association list. In this association list, thecar of
each element should be a module name, and thecdr of each element should be a
pathname or list of pathnames making up the module. Therequire function
loads all the files listed. Initially, *module-file-alist* is empty. Here is
how to add something to*module-file-alist* .
? (push '(my-system . ("my-sys;definitions.fasl"
"my-sys;actions.fasl"))
*module-file-alist*)
n If the module is not registered in*module-file-alist* , require looks for a
file with the same name as the module name in the locations specified by the
variable *module -search-path* . The *module-search-path* variable
should be bound to a list of pathnames, each specifying the directory and possibly
a file type (the name component is ignored and replaced by the name of the
module). If no file type is given, both*.lisp-pathname* and*.fasl -
pathname* are looked for, and the more recent file is used.
Macintosh Common Lisp keeps a list of files currently being loaded. This helps
ensure that files requiring each other do not cause infinitely recursive calls to
require .
For documentation of the state ofrequire , see Common Lisp: The Language , pages
277–278.
provide [Function ]
Description The provide function was once part of Common Lisp but is now
specific to Macintosh Common Lisp. It adds a new module name to
the list of modules maintained in the variable *modules* ,
indicating that the module module has been provided.
The Macintosh Operating System maintains a default directory of its own. Any
namestring that begins with a colon or semicolon is relative. The directory component
of a relative pathname is appended to the directory component of *default -
pathname-defaults* before accessing the file system. If the resulting pathname is
still relative, then the value of mac-default-directory is used.
mac-default-directory [Function ]
Syntax mac-default-directory
Example
? (mac-default-directory)
#P"BigTowel:CCL:"
set-mac-default-directory [Function ]
Example
? (set-mac-default-directory #P"BigTowel:CCL Test:")
#P"BigTowel:CCL Test:"
mac-namestring [Function ]
Example
? (mac-namestring "ccl:examples;dialog-editor.lisp")
"hd:myccl:examples:dialog-editor.lisp"
mac-file-namestring [Function ]
Structured directories
Description The directoryp function returns the true name of the directory if
pathname names a directory,nil if it names an ordinary file;
otherwise it signals an error. (For true names, seeCommon Lisp: The
Language under the functiontruename .)
full-pathname [Function ]
Arguments pathname-or-namestring
A pathname or namestring.
:no-error If the value of :no-error is t (the default) and
there is no physical directory for a logical directory
in pathname , Macintosh Common Lisp returns nil. If
the value of :no-error is nil, Macintosh Common
Lisp signals an error.
This example creates a logical-to-physical mapping and gets its full pathname.
;Create the logical to physical mapping:
? (setf (logical-pathname-translations "misc")
'((**;**" "hd:ccl-misc:**.*.*")))
NIL
;Load the file "hd:ccl-misc:hacks.lisp":
? (load "misc:hacks.lisp")
;Loading "hd:ccl-misc:hacks.lisp"...
#P"hd:ccl-misc:hacks.lisp"
? (full-pathname "misc:hacks.lisp")
"hd:ccl-misc:hacks.lisp"
? (full-pathname "MISC:hacks.lisp")
"hd:ccl-misc:hacks.lisp" ;Note case insensitivity.
directory-pathname-p [Function ]
Example
? (directory-pathname-p "ccl:foo;")
T
? (directory-pathname-p "ccl:foo")
NIL
? (directory-pathname-p "hd:ccl:")
T
? (directory-pathname-p "hd:ccl:init.lisp")
NIL
You can also use the simpler wildcard system described here, which is compatible
with previous versions of Macintosh Common Lisp.
The following examples assume the existence of a mounted disk with the
name "hd".
n (directory "hd:*:" :files nil :directories t) returns a list of all
subdirectories directly under"hd:".
n (directory "hd:**") returns a list of files under"hd:" .
n (directory "**:**:" :directories t :files nil) returns a list of all
the subdirectories at all levels in all the devices known to the machine.
n (directory "**:**") returns a list of all the files at the top level in all the
devices known to the machine.
n (directory "hd:*.lisp") returns a list of all the files in the top level of
"hd:" that are of type "lisp" .
n (directory "**:ccl:*:*:prin*12.**") returns a list of all the files in any
device that start with the letters "prin" and end in"12" and are two levels
below a directory named"ccl:".
The functions in this section operate on both directories and files. A directory
operation is performed if the filename component is empty (that is, if the pathname
ends in a colon or semicolon); otherwise, a file operation is performed.
delete-file [Function ]
create-file [Function ]
open [Function ]
Description The Common Lisp function open opens a stream to the file specified
by filename, which may be a string, a pathname, a logical
pathname, or a stream. Two new keywords, :mac-file-creator
and :fork , distinguish the MCL implementation from Common
Lisp’s; the keyword arguments:direction and:if-exists can
each take an additional value. The additional MCL keywords and
values are documented next.
rename-file [Function ]
Example
? (rename-file "hd:doc:file system notes"
"BigTowel:misc:renamed notes")
#P"BigTowel:misc:renamed file system notes"
#1P"hd:doc:file system notes"
#1P"BigTowel:misc:renamed file system notes"
file-create-date [Function ]
file-write-date [Function ]
set-file-create-date [Function ]
set-file-write-date [Function ]
The following functions operate on files only. These functions, in conjunction with the
directory function, provide the needed flexibility for operating on directories.
copy-file [Function ]
Description The copy-file function copies the file to a file corresponding to the
pathname specified by merging new-pathname with old-pathname .
Arguments may be either strings, Lisp pathnames, or streams. If
new -
pathname does not have a filename component, then the filename of
old-pathname is used.
file-locked-p [Function ]
Description These functions allow you to manipulate the software lock that
prevents modifications to a particular file. The file-locked-p
function returnsnil if the file is not locked.
mac-file-type [Function ]
mac-file-creator [Function ]
set-mac-file-type [Function ]
set-mac-file-creator [Function ]
Description Every Macintosh file has two parameters specifying the type of the
file and the application that created the file. These parameters,
called os-type s, are specified by four-character keywords or symbols
that are case sensitive.
*open-file-streams* [Variable ]
Volume operations
volume-number [Function ]
Example
eject-disk [Function ]
eject&unmount-disk [Function ]
disk-ejected-p [Function ]
hfs-volume-p [Function ]
The HFS and MFS file systems are described inInside Macintosh.
flush-volume [Function ]
Description Some file system manipulations are buffered for execution at a later
time. The flush-volume function ensures that all buffered file
manipulations to a specified volume are performed. Theflush–
volume function returns the name of the volume affected.
drive-name [Function ]
Description The drive-name function returns the name of the drive whose drive
number or volume number is
number.
drive-number [Function ]
Description The drive-number function returns the drive number of the drive
indicated by pathname .
User interface
The following functions let the user choose or set a pathname to a file or directory.
choose-file-dialog [Function ]
choose-new-file-dialog [Function ]
Arguments :directory Specifies the directory shown when the dialog box
first appears. It defaults to the last directory shown
by the Choose File dialog box or Choose New File
dialog box.The filename component of:directory
is used as the default filename in the editable-text
item of the dialog box.
:prompt Specifies the text to display above the area in
which the user types the filename. If supplied,
:prompt should be a string. The default prompt is
As….
:button-string
Specifies the text that appears in the button that
opens the file. The default is Save.
choose-file-default-directory [Function ]
Syntax choose-file-default-directory
set-choose-file-default-directory [Function ]
If you are new to Macintosh Common Lisp, you do not need to read this section.
Unlike physical directories, which end with colons, logical directory names end with
semicolons.
Because of the use of a semicolon as the directory delimiter in MCL logical directories, a
namestring containing semicolons but no host will not parse to a Common Lisp logical
pathname. However, if it is merged with a logical pathname, the result is a logical
pathname.
? (ccl::logical-pathname-p (pathname "blotz;blitz;"))
NIL
? (ccl::logical-pathname-p
(merge-pathnames
(pathname "blotz;blitz;")
(pathname "ccl:")))
T
The following MCL functions and variables govern logical directory names.
*logical-directory-alist* [Variable ]
Arguments logical-directory-name
A logical directory name.
physical-pathname
The physical pathname associated with logical -
directory-name . It may contain logical components.
Contents
Debugging tools in Macintosh Common Lisp / 334
Compiler options / 335
Fred debugging and informational commands / 336
Debugging functions / 340
Error handling / 348
Functions extending Common Lisp error handling / 348
Break loops and error handling / 349
Functions and variables for break loops and error
handling / 353
Stack Backtrace / 355
Single-expression stepper / 358
Tracing / 359
MCL expressions associated with tracing / 363
Advising / 366
The Inspector / 369
Using the Inspector / 369
Inspector functions / 371
Other debugging macros / 372
333
Debugging tools in Macintosh Common Lisp
Macintosh Common Lisp provides several tools to help programmers examine and
debug functions, source code, and environments:
n compiler options to retain information useful for later programming
n a set of Fred commands
n debugging functions
n a set of functions for signaling errors and aborting operations (these functions may
optionally enter a break loop)
n a break-loop facility, which interrupts a program and allows you to look at the
stack and examine dynamic values before returning
n a Stack Backtrace
n a single-expression stepper
n a trace function
n an Inspector
The Tools menu contains most of these tools and the Fred Commands window; the
other tools are available through MCL expressions.
MCL debugging tools form an integrated whole, allowing you to look at your code
from a variety of perspectives. Figure 10-1 shows the MCL debugging tools and their
relationships. From each of the listed windows you can examine code in the windows
they point to.
When available, code is always the best documentation. Two keyboard commands
are often used to examine code.
n Pressing Meta-period when the insertion point is within or next to an expression in
code allows you to examine its source code. You can examine the source code of
many MCL expressions.
n Pressing Control-Meta and clicking an expression acts like pressing Meta-period
but also allows you to examine expressions within Inspector windows.
Compiler options
The MCL compiler can optionally retain information useful for later programming. It
can also provide useful debugging information at compile time. The behavior of the
compiler is regulated by the global variables listed in Table 10-1.
Variable Purpose
Variable Purpose
Several Fred command keystrokes help the programmer get information about MCL
expressions and the MCL environment.
Remember that you access Meta commands by pressing the Option key. You access
Control commands by pressing the Control key (if your keyboard has one) or by
pressing Command or Command-Shift.
Several of these commands are on the Tools menu; those menu items are listed in
Table 10-2.
Get argument list Control-X Prints the argument list of the function
information Control-A bound to the symbol surrounding the
insertion point. Argument list is
displayed in the minibuffer if the value
of *mini-buffer-help-output* is t;
otherwise, it is displayed in the
*standard-output* stream. The ed-
arglist function works for built-in
functions and macros, and for most
functions and macros defined with
*save-local-symbols* or *fasl -
save-local-symbols* set tot.
(continued)
Get documentation for Control-X Opens a dialog box displaying the symbol
current expression Control-D, surrounding the insertion point and the
Documentation documentation string of the function bound
on Tools menu to that symbol. If no documentation string
is available, displays “No documentation
available.” This function works for built-
in functions and macros and for most forms
defined with *save-doc-strings* set
to true.
Inspect current expression Control-X Inspects the current symbolic expression.
Control-I
Macroexpand current Control-X Macroexpands the current expression with
expression Control-M macroexpand and pretty-prints the
result to *standard-output* .
Macroexpand current Control-M Macroexpands the current expression
expression repeatedly repeatedly with macroexpand-1 until
the result is no longer a macro call and
pretty-prints the result to *standard -
output* .
Print information about Control–= Prints information about the current Fred
active window window to*standard-output* .
Read current expression Control-X Prints the result of reading the current
Control-R symbolic expression. This is useful for
tracking read-time bugs, particularly in
expressions containing backquotes.
Debugging functions
The following functions and variables are useful when programming. They provide
information on the MCL programming environment and aid in testing and tracking
functions.
apropos [Function ]
Description The apropos function finds all interned symbols whose print names
contain string as a substring and prints the name, function definition,
and global value of each symbol. The valuenil is returned. The
result is printed to*standard-output* .
Example
? (apropos 'bitmap)
BITMAP
$BITMAP.TOPLEFT, Value: 6
$BITMAP.TOP, Value: 6
$BITMAP.LEFT, Value: 8
_SCRNBITMAP, Def: MACRO FUNCTION, Value: 43059
$AFPBITMAPERR, Value: -5004
$ICONBITMAP, Value: 2574
:BITMAP, Value: :BITMAP
apropos-list [Function ]
Description The apropos-list function returns a list of all symbols whose print
names containstring-or-symbol as a substring.
Example
? (apropos-list 'bitmap)
(:BITMAP $ICONBITMAP $AFPBITMAPERR _SCRNBITMAP $BITMAP.LEFT $BITMAP.TOP
$BITMAP.TOPLEFT BITMAP)
? (setq make-syms (apropos-list 'bitmap))
(:BITMAP $ICONBITMAP $AFPBITMAPERR _SCRNBITMAP $BITMAP.LEFT $BITMAP.TOP
$BITMAP.TOPLEFT BITMAP)
? (setq make-syms (sort make-syms #'string<
:key #'symbol-name))
($AFPBITMAPERR $BITMAP.LEFT $BITMAP.TOP $BITMAP.TOPLEFT $ICONBITMAP
:BITMAP BITMAP _SCRNBITMAP)
? (pprint make-syms)
($AFPBITMAPERR
$BITMAP.LEFT
$BITMAP.TOP
$BITMAP.TOPLEFT
$ICONBITMAP
:BITMAP
BITMAP
_SCRNBITMAP)
arglist [Function ]
Description The arglist function returns two values, the argument list ofsymbol
and how the list was computed. The second value can be one of
:definition , :declaration , :analysis , :unknown , ornil. The
value :definition means that *save-definitions* was true
when the function was compiled; the value:declaration means
that either the argument list was found in the MCL Help file or you
declared the argument list with (setf (arglist symbol)
arglist ). The value :analysis means that the argument list was
computed from information stored with the function;:unknown means
that the symbol was bound to a function, but no argument list
information could be determined; andnil means that the symbol was
not bound to a function.
Table 10-3 lists the values ofdoc-type that should be supplied with various MCL
constructs.
Function function
Generic function function
Special form function
Macro function
Variable variable
Constant variable
defstruct structure structure
Class object type
Type specifier type
defsetf definition setf
define-setf-method definition setf
Method combination method-combination
edit-definition-p [Function ]
Example
? (edit-definition-p 'pop-up-menu)
((CLASS . "ccl:library;pop-up-menu.lisp"))
POP-UP-MENU
T
NIL
T
? (edit-definition-p 'view-draw-contents 'method '(basic -
editable-text-dialog-item) :after)
NIL
VIEW-DRAW-CONTENTS
METHOD
(BASIC-EDITABLE-TEXT-DIALOG-ITEM)
:AFTER
print-call-history [Function ]
Syntax print-call-history
select-backtrace [Function ]
Syntax select-backtrace
room [Function ]
inspect [Function ]
Example
? (inspect 'windows)
#<INSPECTOR-WINDOW "WINDOWS" #x467281>
Syntax top-inspect-form
Example
? (top-inspect-form)
WINDOWS
For full details on the Inspector, see the section “The Inspector” later in this chapter.
Error handling
Macintosh Common Lisp uses the Common Lisp condition system, which
reconceptualizes and adds to Common Lisp’s previous error-detection and error
-
handling capabilities.
A condition is an interesting situation that has been detected and announced within a
program. Anerror is a condition from which the program cannot continue normally,
but requires some sort of intervention, either by program control or from the user.
Most MCL error-handling functions now follow the definitions of those functions
given in Common Lisp: The Language, Chapter 24, “Errors,” and Chapter 29,
“Conditions.” (Note that pages 886–887 Common
of Lisp: The Language supersede the
earlier discussion oferror andcerror in Chapter 24 of the same book.) MCL
extensions to those functions are described next.
abort-break [Function ]
Syntax abort-break
cancel [Function ]
Syntax cancel
At any point during an MCL program, program execution may be suspended and
control passed to a break loop. A break loop behaves like the top-level read-eval
-
print loop. However, when you enter a break loop you do not exit your program and
return control to the top level (asabort does). Instead, a break loop suspends your
program and allows interaction on top of your program. From a break loop, you can
resume the program or return to the top level.
Figure 10-2 shows the execution stack of Macintosh Common Lisp. Newer items are
added to the bottom. The diagrams show that break loops add new areas to the
stack, butabort andcontinue remove areas from the stack. New items are added
to the bottom.
Within a break loop, the MCL question mark prompt is replaced by a number and an
angle bracket. Expressions can be evaluated, just as they are in the normal Listener
loop. Because the break loop runs on top of the interrupted program, all global
variables have the values they had when the interrupted program was suspended,
as the following code shows.
? *print-case*
:downcase
? *load-verbose*
t
? (defun show-specials ()
(let ((*print-case* :upcase)
(*load-verbose* nil))
(break)
(print "Now we have continued.")
t))
show-specials
? (show-specials)
>Break:
> While executing: SHOW-SPECIALS
> Type Command-/ to continue, Command-. to abort.
> If continued: Return from BREAK.
Break loops retain the dynamic environment of the interrupted program (that is, the
values of global variables), but they do not retain the lexical environment of the
interrupted program. For this reason, forms that you type into the break loop do not
have access to the lexical variables of the interrupted program, as shown in the
following code. (You can look at the lexical variables with the Stack Backtrace,
described later in this chapter.)
? (defun double (num)
(unless (numberp num)
(break))
(+ num num))
DOUBLE
? (double 5)
10
? (double 'ten)
>Break:
> While executing: DOUBLE
> Type Command-/ to continue, Command-. to abort.
> If continued: Return from BREAK.
See the Restarts… menu item for further choices.
1 > num
> Error: Unbound variable: NUM
> While executing: SYMBOL-VALUE
> Type Command-/ to continue, Command-. to abort.
> If continued: Retry getting the value of NUM.
See the Restarts… menu item for further choices.
2 > (abort-break)
Aborted
1 > (abort-break)
Aborted
You can enter a break loop explicitly by calling the functionbreak or cerror . In
addition, if the value of *break-on-errors* is true, Macintosh Common Lisp
enters a break loop whenever an error is signaled. If the value of*break-on -
warnings* is true, Macintosh Common Lisp enters a break loop whenever warn is
called. These functions and variables are described in the section “Functions and
Variables for Break Loops and Error Handling” later in this chapter.
There are two ways to leave a break loop: by callingcontinue and by callingabort
(see Figure 10-4). Calling continue resumes the program from the point at which it
was interrupted. Calling abort returns to the previous read loop. This may be the
top-level loop or a prior break loop. In the case ofabort, the suspended program is
not resumed.
Abort and Continue are available as commands on the Eval menu. You can also invoke
abort at any point by pressing Command-period. Within a break loop, you can
invoke continue by pressing Command-slash (Command-/).
The following functions and variables control break loops and error handling.
break [Function ]
The break function can also be invoked through the Eval menu. This
provides a convenient method for suspending a program at any point
of execution.
*break-on-errors* [Variable ]
If the value of this variable is nil, then errors simply cause a return
to the read-eval-print loop.
*break-on-warnings* [Variable ]
If the value of this variable is nil, then you must choose Backtrace
from the Tools menu to see the Stack Backtrace dialog box.
Stack Backtrace
When inside a break loop, the Stack Backtrace command lets you examine the state
of the suspended program. To see the Stack Backtrace dialog box, choose Backtrace
from the Tools menu when you are in a break loop.
The Stack Backtrace shows all the functions awaiting return values as well as the local
variables of these functions (if the functions were compiled with*save-local -
symbols* set to true). You can easily access and set the values in a stack frame. Finally,
information on the program counter and stack frame address is given.
The Stack Backtrace dialog box shows two tables. The upper table shows the
functions that are pending on the stack. The lower table is initially blank. When you
single-click any function in the upper table, the lower table displays that function’s
stack frames. You can edit values in the lower table (but do so with caution).
In the space between the tables are three pieces of information about the frame: the
number of values in the frame, the memory address of the frame, and the program
counter within the function where execution has been suspended. The memory address
is useful for low-level system debugging. You can use the program counter with
disassemble to locate the point of a break within a function.
Figure 10-5 and the code that follows it show editing in the Stack Backtrace dialog
box.
Here is the code that produced the Stack Backtrace dialog box in Figure 10-5.
? (defun foo (x y)
(let ((z 10))
(break)
(+ x y z)))
foo
? (foo 10 20)
> Break:
> Type Command-/ to continue,
Command-. to abort.
This only works if the value of*compile-definitions* was true whenfoo was
compiled. Otherwise, the result is still 40.
Double-clicking a function in the top table causes the function object to be inspected,
giving you access toedit-definition , documentation , arglist , disassemble ,
and uncompile-function .
The stack frame in the lower table shows the names of local variables, if these were
retained at compile time. If these were not retained, the parameters are listed as
required, optional, keyword, or rest. You can use the
local macro to access the values
of these frames. In addition, you can double-click a value to inspect it.
local [Macro ]
Description The macro local returns the value in the current stack frame of the
slot given by indicator . This macro can be used only when a Stack
Backtrace dialog box is visible and when a frame is selected.
set-local [Macro ]
The step macro can be used on compiled functions only if their uncompiled definitions
have been retained. If there is no uncompiled definition for a function, it is treated as an
atomic unit as it is evaluated. A compiled function call is executed as a whole rather
than being evaluated form by form. (This is how thestep macro treats built-in
functions.)
Because evaluation occurs in a null lexical environment,step is usually called only from
the top level. If it is called from within a function, it does not have access to the local
environment in which it was called. However, internal stepping can be invoked through
the trace macro, described in the section “Tracing” later in this chapter.
It is not generally possible to step through code that requires the use of
without -
interrupts or code that uses the Macintosh graphics interface.
*step-print-level* [Variable ]
*step-print-length* [Variable ]
Tracing
Tracing is useful when you want to find out why a function behaves in an unexpected
manner, perhaps because incorrect arguments are being passed.
Tracing causes actions to be taken when a function is called and when it returns. The
default tracing actions print the function name and arguments when the function is
called and print the values returned when the function returns.
Other actions can be specified. These include entering a break loop when a function is
entered or exited, or stepping the function. Trace actions may be conditional.
When a traced function is traced again, the new trace actions replace the former ones.
When a traced function is redefined by evaluation in a buffer, the trace actions are
transferred from the old definition to the new definition. When a traced function is
redefined while loading a file, the function is untraced and a warning is issued.
Macros and special forms cannot be traced. Functions that are compiled inline cannot
be traced (seeCommon Lisp: The Language , pages 229–230). Note that, by default,
self-recursive calls are compiled as inline branches. To effectively trace a function
with self-recursive calls, you should declare it not inline.
Examples
120
The following Lisp functions and variables are associated with tracing.
untrace [Macro ]
Description The untrace macro stops eachspec from being traced. Notices will
not be printed when the function enters or returns. The macro returns a
list of the functions that are no longer being traced.
*trace-level* [Variable ]
Example
*trace-max-indent* [Variable ]
trace-tab [Function ]
Syntax trace-tab
Example
? (trace fact)
nil
? (setq *trace-bar-frequency* 2)
2
? (fact 5)
Calling (fact 5)
|Calling (fact 4)
| Calling (fact 3)
| |Calling (fact 2)
| | Calling (fact 1)
| | |Calling (fact 0)
| | |fact returned 1
| | fact returned 1
| |fact returned 2
| fact returned 6
|fact returned 24
fact returned 120
120
? (setq *trace-bar-frequency* nil)
nil
? (fact 3)
Calling (fact 3)
Calling (fact 2)
Calling (fact 1)
Calling (fact 0)
fact returned 1
fact returned 1
fact returned 2
fact returned 6
6
The unique:name and the :when keyword serve to identify the piece of advice. A
later call to advise with the same values for the :name and:when keywords
replaces the existing piece of advice, but a call with different values does not.
advise [Macro ]
Description The advise macro adds a piece of advice to the function or method
specified by spec according toform.
Examples
The functionfoo, already defined, does something with a list of numbers. The
following code uses a piece of advice to make
foo return zero if any of its arguments is
not a number. Using:around advice, you can do the following:
(advise foo (if (some #'(lambda (n)
(not (numberp n)))
arglist)
0
(:do-it))
:when :around :name :zero-if-not-nums)
Description The unadvise macro removes the piece or pieces of advice for
everything matching spec, when , andname. When the value of spec is
t and the values ofwhen and name are nil, unadvise removes every
piece of advice; whenspec is t, when is nil, and name is non-nil,
unadvise removes all pieces of advice with the given name.
advisedp [Macro ]
Description The advisedp macro returns a list of existing pieces of advice that
match spec, when , and name. When the value of spec is t and the
values of when and name are nil, advisedp returns all existing pieces
of advice.
The Inspector lets you look quickly at any component of one or more data objects. For
instance, you can use it to look at the current state of the system data. Double-click
any form or component of a form in an Inspector window to bring up a window with a
definition of the form or component; double-click any item in that window to bring up
its definition, and so on.
Because objects are editable in Inspector windows, you can change the state of system
data and other components on the fly. You should be careful about doing so, however;
it is generally safe to change the value of a global variable in the Inspector, but you
should use the standard interface functions to change the values associated with
object keywords.
To see the Inspector, choose Inspect from the Tools menu.You can also call
inspect on
a Lisp object or use the keystroke command Control-X Control-I. If you have an
extended keyboard, you can also press the Help key. When you choose Apropos from
the Tools menu and double-click a symbol name, Macintosh Common Lisp creates an
Inspector window containing information about that symbol.
When you choose the Inspector from the Tools menu, you see the Inspector Central
dialog box, which contains a number of options. Clicking any of these options calls up
an Inspector window. Double-click any item in a window to inspect it.
inspect [Function ]
Example
? (defun foo (x y)
(let ((z 10))
(break)
(+ x y z)))
FOO
? (inspect 'foo)
#<INSPECT-DIALOG "Symbol: FOO" #x5DE9F9>
top-inspect-form [Function ]
Syntax top-inspect-form
*inspector-disassembly* [Variable ]
Description The @ variable is bound to the last object that was cut or copied. It is
used primarily to communicate values between an Inspector window
and the Listener.
The following macros are useful for testing and optimizing code and for tracing
program flow.
time [Macro ]
Description The time macro executesform, prints the duration of execution (with
a special note on garbage collection time, if any), and returns the
value returned byform. The time macro is useful for testing and
optimizing code.
Argument form Any Lisp form. The form should not be quoted.
Example
? (defun make-numlist (positive-number &aux result)
"returns a list of numbers between 0 and
positive-number - 1"
(dotimes (x positive-number)
(setq result (append result (list x))))
print-db [Macro ]
Description The print-db macro is equivalent toprogn , except that each form
is printed as it is evaluated. The form itself and the result of
evaluating form are both printed (unlessform is a string, in which
case it is printed only once). The value of the lastform is returned.
The print-db macro is useful for tracing program flow and for
checking the values of variables at various points in a program.
Contents
Implementation of events in Macintosh Common Lisp / 376
How an event is handled / 376
MCL built-in event handlers / 377
Functions for redrawing windows / 387
Event information functions / 391
The event management system / 393
The cursor and the event system / 401
Event handlers for the Macintosh Clipboard / 405
MCL expressions relating to scrap handlers and scrap types / 406
If you are creating handlers for Apple events, you should read this
chapter, then read Chapter 12, “Apple Events.”
375
Implementation of events in Macintosh Common Lisp
Users generate events as a way of directing program flow. Typical events are
keystrokes and mouse clicks. Events interrupt a program and often require a response.
Whenever possible, Macintosh programs should be event driven.
Many user programs do not need to handle events explicitly. For those programs that
do, several different event-handling methods are available. In order of increasing
complexity these are
n defining methods associated with specific types of events in a view
n defining all methods associated with a view
n defining a hook procedure that has first priority in processing all events
n disabling all background event processing, and handling events with an
event loop
Most programming languages for the Macintosh computer support only the last, and
most difficult, method of event handling. MCL programs rarely need to do anything
more complex than the first method.
Programs can be initiated from within an event handler; use the function
eval-enqueue , which lets an event initiate a process with event processing
enabled.
The MCL event system gets each event from the Macintosh Operating System in turn
and binds*current-event* to it. The event system then determines the type of the
event and calls the appropriate event-handling function on the relevant view. If the
event is a mouse click, the relevant view is the view in which the click occurred. If
the event is a keystroke, the relevant view is the active (frontmost) window.
Many of the default event-handling methods do nothing, although they are called
whenever an event of the appropriate type is processed. These handlers exist so that
they may be shadowed by any subclass ofview that needs to process events of that
type.
Some event handlers defined on views do nothing more than invoke the same event
handler on each subview. In this way nested views and subviews are processed.
Example
The following code displays the cursor coordinates whenever the user clicks
my-window . (As a subclass ofview, window inherits the view-click-event -
handler method for view.)
? (defclass my-window (window)())
#<STANDARD-CLASS MY-WINDOW>
? (defmethod view-click-event-handler
((window my-window) where)
(print (point-string where)))
#<Method VIEW-CLICK-EVENT-HANDLER (MY-WINDOW T)>
? (make-instance 'my-window)
#<MY-WINDOW "Untitled" #x410891>
Description The class key-handler-mixin should be mixed into any class that
handles key events. The class fred-dialog-item includeskey-
handler-mixin .
Every key pressed by the user actually generates two events: one
when the key is pressed and another when the key is released.
You should not specialize this function except to note that the
window has been updated. To get special drawing behavior, you
should instead specialize view -draw-contents .
Examples
The following code creates a window that always has a circle drawn in it:
? (require 'quickdraw)
"QUICKDRAW"
? (setq foo (make-instance 'window))
#<WINDOW "Untitled" #x4A3BD9>
? (defmethod view-draw-contents ((window (eql foo)))
(paint-oval window 10 10 100 100))
VIEW-DRAW-CONTENTS
To add an area (rectangle or region) to the invalid region, call the trap#_InvalRect or
#_InvalRgn . Calling these traps forces the posting of an update event for the window.
For this reason, calling these traps from insideview-draw-contents or window -
update-event-handler can lead to an infinite loop.
If you want to invalidate several areas before the update is performed, surround the calls
to #_InvalRect and#_InvalRgn with the special form without-interrupts , which
temporarily suspends updates.
The following call will force the redrawing of the entire window. It doesn’t need
without-interrupts because there is only one call to#_InvalRect . If there were
several calls to #_InvalRect , without-interrupts would postpone updating until
the end.
(with-port wptr
(#_invalrect :ptr (rref wptr window.portrect)))
Example
mouse-down-p [Function ]
Syntax mouse-down-p
The following example prints the mouse position in window coordinates until the
mouse is clicked.
(do () ((mouse-down-p))
(print (point-string (view-mouse-position (front-window)))))
The following example prints the mouse position in screen coordinates until the
mouse is clicked.
(do () ((mouse-down-p))
(print (point-string (view-mouse-position nil))))
double-click-p [Function ]
Syntax double-click-p
double-click-spacing-p [Function ]
control-key-p [Function ]
option-key-p [Function ]
shift-key-p [Function ]
caps-lock-key-p [Function ]
Syntax command-key-p
control-key-p
option-key-p
shift-key-p
caps-lock-key-p
This section describes the overall architecture used for implementing event handling
in Macintosh Common Lisp.
If you create a program with a loop that checks for events, you
should probably include a call toevent-dispatch inside the loop.
This improves the response time when events occur.
get-next-event [Function ]
*current-event* [Variable ]
(defrecord Event
(what integer)
(message longint)
(when longint)
(where point)
(modifiers integer))
Description The *eventhook* variable provides a user hook into the event
system. A program can store a function of no arguments in this global
variable. The stored function is given the first opportunity to handle
all event processing. If the function returns true, the event system
assumes the event has been handled and no further processing is
done. If the function returns false, the event system assumes the event
hasn’t been handled and the normal event handlers are invoked.
*idle* [Variable ]
Description The *idle* variable signals the event system that the main Lisp
process is idle. This changes the sleep time that event dispatch
gives to the trap #_WaitNextEvent . This variable is normally
bound to true by the read loop as the loop waits for input, and by
modal-dialog .
*idle-sleep-ticks* [Variable ]
*background-sleep-ticks* [Variable ]
event-ticks [Function ]
Syntax event-ticks
set-event-ticks [Function ]
Syntax set-event-ticks n
*foreground-event-ticks* [Variable ]
*background-event-ticks* [Variable ]
eval-enqueue [Function ]
Examples
The user can also useeval-enqueue in dialog boxes. The action is initiated by the
dialog box, but the user can still access other parts of the system (including other
dialog buttons) while the action is running.
In the following example, the action of the Go button is queued so that other events
can be processed while it is running. This allows the user to click the Stop button.
Note that the action of the Stop button does not call
eval-enqueue . If it did, the
queued form would never be run (because the form queued by the Go button would
never return). The Stop button communicates with the action of the Go button by
changing the value of a lexical variable.
? (let ((stop nil))
(flet ((start ()
(setq stop nil)
(loop
(if stop (return))
(print "Click stop when bored"))))
(make-instance 'window
:window-title "Stop and Go"
:view-subviews
(list
(make-instance 'button-dialog-item
:dialog-item-text "Go"
:dialog-item-action
#'(lambda (item)
(declare (ignore item))
(eval-enqueue `(funcall ,#'start))))
The cursor is the screen image whose motion is controlled by the mouse. As the user moves
the mouse on the desktop, the cursor moves correspondingly on the screen.
The cursor often changes shape as it moves over different areas of the screen. For example,
when it is on the menu bar or scroll bars, it is shaped like an arrow; when inside a text
window, the cursor is shaped like an I-beam.
When the mouse is over the front window or any floating window,
the window-update-cursor method for the window class sets the
variable *mouse-view* to the view containing the mouse, using
find-clicked-subview . The window-null-event-handler
method for the window class callsupdate-cursor , which calls
*cursorhook* . The function that is the initial value of
*cursorhook* calls window-update-cursor , which sets the
cursor using the value returned byview-cursor .
with-cursor [Macro ]
update-cursor [Function ]
set-cursor [Function ]
*arrow-cursor* [Variable ]
*watch-cursor* [Variable ]
*i-beam-cursor* [Variable ]
Data that can be cut and pasted comes in different forms, for example, ASCII text,
PICT format graphics, and stylized text. Macintosh Common Lisp provides a simple
model for accessing the Macintosh scrap, the structure that supports the Macintosh
Clipboard. The Clipboard is accessed through a simple handler, the scrap handler.
Macintosh Common Lisp uses scrap handlers, with one handler for each type of scrap
data. The scrap handlers are stored in an association list of the form
(scrap-type -
keyword . scrap-handler ).
In the initial MCL environment, scrap handlers are defined for simple text,
formatted Fred text, and Lisp code. You can add handlers for other data types.
When defining new handlers, you should look at the filepict-scrap.lisp in the
MCL Examples folder to learn how to define a scrap handler for
PICTs.
For full details on the operation of the Clipboard, you should also consult
Inside
Macintosh.
The following MCL expressions relate to defining scrap handlers and scrap types.
get-scrap [Function ]
Description The get-scrap function returns two values. The first value is the
current scrap ofscrap-type . The second value ist if some scrap is
found ornil if no scrap is found.
Example
put-scrap [Function ]
The following code puts the phrase “This is only a text” onto the scrap and retrieves
it:
? (put-scrap :text "This is only a text")
"This is only a text"
? (get-scrap :text)
"This is only a text"
T
*scrap-state* [Variable ]
*scrap-handler-alist* [Variable ]
Example
This scrap-handler association list contains entries for four scrap handlers. The
:pict scrap handler is defined inpict-scrap.lisp in the MCL Examples folder.
? *scrap-handler-alist*
((:PICT . #<PICT-SCRAP-HANDLER #x4BB4F9>) (:LISP . #<LISP-SCRAP-HANDLER
#x302CC9>) (:FRED . #<FRED-SCRAP-HANDLER #x3029E1>) (:TEXT . #<TEXT -
SCRAP-HANDLER #x3025E9>))
Contents
Implementation of Apple events / 412
Receiving Apple events / 412
How to write an Apple event handler / 413
Forms associated with Apple events / 414
Installing Apple event handlers / 417
Installing handlers for queued Apple event replies / 418
Standard Apple event handlers / 420
Sending Apple events / 423
411
Implementation of Apple events
The Finder uses Apple events to open applications and quit them, to open documents,
and to print documents. In addition, Apple events and the Apple Event Manager may
provide services to other applications and request services from them. The Apple
Event Manager is available only under System 7. To determine whether the Apple
Event Manager is available, call the Gestalt function described in the compatibility
guidelines information in Inside Macintosh .
Macintosh Common Lisp provides built-in support for receiving Apple events and
replying to them. It supports the four required Apple events: Open Application,
Open Documents, Print Documents, and Quit Application. It also provides facilities
for defining other Apple event handlers.
Creating Apple events and sending them to other applications are not directly
supported in Macintosh Common Lisp. However, in your Examples folder are
three files illustrating how to send Apple events in Macintosh Common Lisp. These
files are
n appleevent-toolkit.lisp , containing useful functions for sending Apple
events to other processes, including to HyperCard
n eval-server.lisp , which shows how to handle standarddoscript andeval
Apple events
n toolserver.lisp , an example of an Apple events interface to ToolServer
Support for receiving Apple events is built into Macintosh Common Lisp. It directly
supports the four required Apple events sent by the Finder: Open Application, Open
Documents, Print Documents, and Quit Application.
Because Macintosh Common Lisp bypasses the Apple Event Manager’s dispatch
routine and does its own dispatching, you do not need to concern yourself with how
your function is called by the Apple Event Manager. Lisp takes care of both
dispatching and run-time error checking. If no error occurs, the handler should
simply return in the normal way. The value returned by the handler is ignored.
reply Another Apple event record, provided by the Apple Event Manager.
If a reply is required, information should be copied into this record
using Apple Event Manager calls.
refcon The handler reference constant, which is any Lisp object. When the
handler is installed, you have the option of specifying some Lisp
object that serves to distinguish (for instance) two different
installations of the same handler. The reference constant is often
ignored.
The following functions and variables are associated with receiving Apple events.
*application* [Variable ]
Example
ae-error [Macro ]
ae-error-str
Syntax ae-error &body (form)+
ae-error-str error-string &body (form)+
If you have a need for anAEDesc record with indefinite extent, you
must usemake-record . When you want to dispose of the record, you
must explicitly call #_AEDisposeDesc , then dispose-record .
Example
check-required-params [Function ]
Syntax appleevent-idle
%path-from-fsspec [Function ]
install-appleevent-handler [Function ]
Some Apple events received in the event queue, specifically Apple events sent with
the #$kAEQueueReply mode, are replies to previously sent Apple events. Their
handlers are installed differently from other Apple events; the handler is installed
when the originating Apple event is sent, and is automatically deinstalled after one
use.
install-queued-reply-handler [Function ]
Arguments appleevent-or-id
Either a return ID number or the originating Apple
event from which a return ID number can be
extracted.
function A function to be called when the reply comes back.
This function should be a normal Apple event
handler as described in the section “How to Write an
Apple Event Handler” earlier in this chapter.
refcon An optional reference identifier, which can be any
MCL object; it identifies the specific installation of a
handler.
The four basic Apple event handlers are built-in functions in Macintosh Common Lisp.
There are no built-in functions to send Apple events within Macintosh Common Lisp.
However, it is easy to write your own functions for sending Apple events.
To send an Apple event from Macintosh Common Lisp, do the following four steps.
1. Create a target.
2. Create the event.
3. Put data into the Apple event.
4. Send the Apple event.
Since these functions are not part of standard Macintosh Common Lisp, load the file
appleevent-toolkit.lisp to use them.
The file eval-server.lisp , also in the Examples folder, handleseval, dosc, and
scpt Apple events. This file also contains code to communicate with HyperCard and
MPW.
Contents
Implementation of streams / 426
MCL expressions relating to streams / 426
Obsolete functions / 439
425
Implementation of streams
Macintosh Common Lisp implements all of the Common Lisp I/O (input/output)
functions by means of streams.
Macintosh Common Lisp implements streams as a simple class of objects, based on the
abstract classstream . There are only a few things a stream needs to know how to do.
Output streams need to have methods defined for character and string output.
Input streams need to have methods defined to read and “unread” characters
(unreading allows “peeking ahead”). Input streams also need to know how to tell
when they are at end of file.
You can define your own specialized stream types. The file
serial-streams.lisp in
your Examples folder defines a stream that does input and output through the Macintosh
serial port.
The following MCL classes and generic functions deal with streams.
Description The stream class is the class from which all streams inherit. It is an
abstract class. It should not be directly instantiated but instead
should be used to create new subclasses. It has one initialization
argument, :direction .
Example
Description The generic functionstream-tyi reads the next character from the
stream and returns it. If this function is at end-of-file, it returnsnil.
Input functions such asread andread-line work by making
repeated calls to stream-tyi . This function must be defined for all
input streams.
Example
Example
Example
maybe-default-stream-writer [Macro ]
Description If the stream-tyo method forstream is the same as the one for an
instance ofclass , the macro maybe-default-stream-writer
returns the value or values of the lastform. Otherwise, it returns two
values: the effective method for applying #'stream-tyo to stream ,
and stream itself.
Example
Description If the stream-tyi method forstream is the same as the one for an
instance ofclass , the macro maybe-default-stream-reader
returns the value or values of the lastform. Otherwise, it returns two
values: the effective method for applying #'stream-tyi to stream ,
and stream itself. Because maybe-default-stream-reader
returns the effective method rather than #'stream-tyi , it avoids
method-dispatch .
Example
The stream-reader method for the file-stream class is very similar to its
stream-writer method:
? (defmethod stream-reader ((stream file-stream))
(maybe-default-stream-reader (stream *file-stream-class*)
(values #'%ftyi ; low-level character output function
(fblock stream)))) ; parameter block pointer
STREAM-READER
Description The stream-peek generic function returns the last character read
into stream without removing it from the queue. The next call to
stream-tyi or stream-peek reads the same character.
The expression
(stream-write-string stream string 0 (length string))
will be faster than
(dotimes (i (length string))
(stream-tyo stream (char string i)))
Example
? (stream-write-string *terminal-io* "Hi there" 0 1)
H
NIL
Example
The following code handles deletions (“rubouts”) for a hypothetical serial I/O
stream talking to a dumb terminal:
? (defclass serial-io-stream (input-stream output-stream) ())
#<STANDARD-CLASS SERIAL-IO-STREAM>
? (defclass serial-io-stream-rubout-handler
(input-stream output-stream)
((stream :initarg :stream :reader serial-io-stream)
(buffer :initform (make-array 10
:fill-pointer 0
:adjustable t
:element-type 'character)
:reader serial-io-stream-buffer)
(mark :initform nil :accessor serial-io-stream-mark)))
#<STANDARD-CLASS SERIAL-IO-STREAM-RUBOUT-HANDLER>
? (defmethod stream-tyi ((rubout-handler
serial-io-stream-rubout-handler))
(let* ((mark (serial-io-stream-mark rubout-handler))
(buffer (serial-io-stream-buffer rubout-handler))
(size (fill-pointer buffer))
(stream (serial-io-stream rubout-handler))
(peek (stream-peek stream)))
(if (and mark (not (eql peek #\rubout)))
(prog1
(aref buffer mark)
(setf (serial-io-stream-mark rubout-handler)
(and (< (incf mark) size) mark)))
(let ((char (stream-tyi stream)))
(when char
Description When the function close is called with a true :abort keyword, the
generic function stream-abort is called. The stream-abort
generic function should handle any bookkeeping for an abnormal
closing of the stream.
Obsolete functions
Since Macintosh Common Lisp now uses generic functions, the following two functions
are obsolete. They are included for backward compatibility.
tyi [Function ]
Description The tyi function reads one character from stream and returns it, using
stream-tyi . The character is echoed if stream is interactive,
except that the DEL character is not echoed. This function is
included for compatibility with earlier versions of Lisp.
tyo [Function ]
Contents
How Macintosh Common Lisp handles text editing / 443
Fred windows / 443
Fred dialog items / 445
Buffers and buffer marks / 445
Copying and deletion mechanism: The kill ring / 446
MCL expressions relating to buffer marks / 447
Using multiple fonts / 464
Functions for manipulating fonts and font styles / 465
Fred functions / 470
The class fred-mixin / 470
Fred window and Fred dialog item functions / 471
Creating a Fred window / 471
Functions relating to Fred windows and Fred
dialog items / 477
Functions implementing standard editing processes / 493
Multiple-level Undo / 495
Functions relating to Undo / 496
Working with the kill ring / 500
Functions for working with the kill ring / 501
Using the minibuffer / 502
Functions for working with the minibuffer / 502
Defining Fred commands / 504
Fred command tables / 505
Keystroke codes and keystroke names / 505
Command tables / 507
Fred dispatch sequence / 507
MCL expressions associated with keystrokes / 507
MCL expressions relating to command tables / 512
441
You should be familiar with the standard functionality of the
editor, Fred, discussed in Chapter 2, “Editing in Macintosh Common
Lisp.” You should also be familiar with the way that Macintosh
Common Lisp handles windows, discussed in Chapter 5, “Views and
Windows.”
If you are creating editable dialog items, you should also read
Chapter 6, “Dialog Items and Dialogs.”
The actual text being edited is stored in abuffer.Macintosh Common Lisp does not
keep a file open while it is being edited. It merely reads the file into a buffer, lets
you edit it, then reopens the file when you save the buffer.
The buffer is displayed in the window. A window’s contents include the whole
buffer, not only the part currently visible on screen (so, to take a trivial example, you
can select or search the entire contents of a Fred window, not only the visible portion
of the buffer).
Each of these concepts is discussed in more detail in the paragraphs that follow.
Fred windows
Fred windows are the windows in which editor buffers appear. The classfred -
window is a subclass ofwindow and a superclass oflistener . Its superclasses are
the class fred-mixin , which adds slots whose values define the general behavior
of Fred, andwindow . (See Figure 14-1.)
Fred windows are output streams and may be used in any situation that calls for a
stream. Characters output to a Fred window stream are inserted at the insertion
point, which corresponds to a buffer mark. Stream output to Fred windows is buffered
and is not displayed untilfred-update or force-output is called.
Fred dialog items, a subclass ofsimple-view , include any dialog item with
editable text. Their class is fred-dialog-item , whose superclasses include the
class fred-mixin and an internal class whose superclasses are key-handler -
mixin and dialog-item .
For a full description of dialog items, see the sections on dialog items in Chapter 6,
“Dialog Items and Dialogs.”
A buffer has
n a set of buffer marks
n a modification counter, which is incremented any time the buffer is modified
n a property list
There is no data type for buffers; the representation of buffers is internal to the MCL
implementation. Buffers keep track of their operations by using buffer marks and are
accessed only through buffer marks.
For deletion and copying, Fred supports both an Emacs-style kill ring and the
Macintosh Clipboard.
The kill ring is a list of blocks of text that have been deleted. Any command that
deletes or copies text saves that text on the kill ring. There is only one kill ring,
shared among all buffers; with it you can move or copy text from buffer to buffer. Cut,
Copy, and Emacs commands such as Control-K (
ed-kill-line ) move text onto the
kill ring. Also saved on the kill ring is text deleted incidentally, for example, text
that is deleted when you type or paste over a selection. Saving all deleted text onto
the kill ring provides a level of safety not supported by the usual Macintosh Undo
mechanism.
The Macintosh commands Cut, Copy, and Paste move text to and from the Clipboard.
The Paste command ignores the kill ring, always pasting from the Clipboard.
The section “Working With the Kill Ring” describes tools for working with the kill
ring.
buffer-mark-p [Function ]
make-mark [Function ]
Description The make-mark function creates and installs a new mark in the same
buffer asbuffer-mark , with the specified position and direction. If
given, position must be a mark or an integer. The new mark is
returned.
move-mark [Function ]
mark-backward-p [Function ]
make-buffer [Function ]
Example
? (setq my-buffer (make-buffer))
#<BUFFER-MARK 0/0>
Example
buffer-modcnt [Function ]
Example
Description The buffer-plist function returns the property list of the buffer
containing buffer-mark . The system itself keeps certain information
on buffer property lists, so you should not use
setf with buffer -
plist .
At present, Macintosh Common Lisp uses the buffer’s property list for
nothing except storing the value offred-package .
Example
? (buffer-plist my-buffer)
NIL
buffer-getprop [Function ]
Example
Example
? (buffer-putprop my-buffer :font '("Times" 12))
("Times" 12)
? (buffer-getprop my-buffer :font)
("Times" 12)
? (buffer-plist my-buffer)
(:FONT ("Times" 12))
buffer-position [Function ]
buffer-line-start [Function ]
buffer-column [Function ]
buffer-char [Function ]
buffer-char-replace [Function ]
buffer-substring [Function ]
The order of the -end arguments doesn’t matter; they are interpreted
in whatever order produces a meaningful result.
buffer-insert-substring [Function ]
buffer-insert-with-style [Function ]
buffer-current-sexp [Function ]
buffer-current-sexp-start [Function ]
buffer-delete [Function ]
buffer-downcase-region [Function ]
buffer-upcase-region [Function ]
buffer-capitalize-region [Function ]
Description These three functions convert the words between start andend to
lowercase, uppercase, and initial capitals, respectively.
buffer-char-pos [Function ]
buffer-not-char-pos [Function ]
buffer-substring-p [Function ]
buffer-fwd-sexp [Function ]
buffer-skip-fwd-wsp&comments [Function ]
buffer-insert-file [Function ]
This function preserves and restores font information; see the next
section, “Using Multiple Fonts.”
buffer-write-file [Function ]
This function preserves and restores font information; see the next
section, “Using Multiple Fonts.”
Font-spec information is stored with each buffer. Each character in the buffer is
associated with a font spec. In addition, there is a current insertion font; characters
inserted in the buffer appear in this font. (Note that the font information is actually
stored as a series of ranges in the buffer; a separate font spec is not stored for each
character.)
Programming with multiple fonts introduces a new data structure, a style vector. A
style vector can be applied to a series of characters in a buffer. For instance, you can
use a style vector to specify that the first 10 characters after a specified position
should be displayed in 12-point New York bold, the next 20 characters in 9-point
Monaco, and the following 10 characters in 12-point Chicago outline. Style vectors do
not automatically take note of their position: when you apply one, you have to
specify a position using a buffer mark.
Note that if you use another text editor to edit a file, font information may become
misaligned with the text.
buffer-char-font-spec [Function ]
buffer-set-font-spec [Function ]
buffer-replace-font-spec [Function ]
buffer-remove-unused-fonts [Function ]
buffer-get-style [Function ]
buffer-next-font-change [Function ]
buffer-previous-font-change [Function ]
buffer-replace-font-codes [Function ]
Each Fred window has a buffer that is displayed in the window, a display start
position that is a buffer mark indicating the first line of the buffer to be displayed in
the Fred window, an insertion point that is indicated by a blinking vertical line, and
a filename string indicating a file corresponding to the buffer displayed in the
window. Fred dialog items also have these characteristics.
n Each Fred window must have a horizontal and vertical scroll bar and a
minibuffer; most Fred dialog items do not have these.
n Fred windows may have selection ranges, which are highlighted.
n Fred dialog items (that is, all dialog items with editable text) have a size and
position, a default font, one or more colors, an event handler, a key handler, and
text.
The classfred-mixin
:history-length
The number of Fred commands that are remembered.
Only commands that actually change text are
remembered. The default value for Fred windows
and Fred dialog items is*fred-history-length* ;
for the Listener, it is *listener-history -
length* .
In addition to the functions outlined in this section, many Fred functions are
associated with keystrokes. The names and actions of these functions are given in
Chapter 2, “Editing in Macintosh Common Lisp.” They take one argument, either
fred-dialog-item or fred-window .
fred [Function ]
Description The fred-dialog-item class is the class of Fred dialog items. This
class is based onfred-mixin and basic-editable-text -
dialog-item (internal to :CCL).
The following functions manipulate Fred windows and Fred dialog items by
specializing on the class fred-mixin .
Example
? (view-mini-buffer (make-instance 'fred-dialog-item))
#<MINI-BUFFER #x3AAF49>
Example
? (fred-chunk-size (fred))
4096
If the value of this variable is true, then the insertion point is made
visible.
If you modify the window or its buffer in any other context (for
example, by using a menu command or a function meant to be called
directly by user code), you must callfred-update explicitly.
Otherwise, the changes you make will not be visible on the screen.
ed-current-symbol [Function ]
Description The fred-vpos generic function returns the vertical position of the
line containing position , in local window coordinates. Ifposition is
not visible in the window, -1 is returned.
Description The fred-hscroll generic function returns the value of the desired
amount of horizontal scroll in pixels inview .
Description The view-font generic function returns three values: the font spec of
the current insertion font, the font spec of the character at the
insertion point (or the first character in the selection), and a Boolean
value. The Boolean value is t if the entire selection and the insertion
font use the same font spec; otherwise, the Boolean value is nil.
Fred does not automatically set the insertion font when you move the
insertion point. If the insertion font is("Monaco" 9) , typed
characters appear in 9-point Monaco, even if you place the insertion
point between characters displayed in Times Bold. When there is no
selection, the insertion font must always be changed explicitly by a
call to set-view-font . This behavior may change in future
releases of Macintosh Common Lisp.
Example
The following code defines a Fred command that toggles whether text is wrapped in
a window. The functioned-refresh-screen used in this example is defined in the
file assorted-fred-commands.lisp in your MCL Examples folder.
(def-fred-command (:control :meta #\w)
(lambda (w)
(setf (fred-wrap-p w) (not (fred-wrap-p w)))
(ed-refresh-screen w)))
Description The window-save generic function saves the window to its disk file.
If the window has no filename, window -save-as is called.
Note that if the user clicks Cancel in this dialog box, Macintosh
Common Lisp throws to :cancel . User code may wish to perform a
catch-cancel to prevent a return to the top level. (The macro
catch-cancel is documented in Chapter 6, “Dialog Items and
Dialogs.”)
ed-beep [Function ]
The functions that are found in the standard Macintosh editing menu are
implemented as MCL generic functions. In addition, Macintosh Common Lisp
provides a more extensive Undo facility.
The cut generic function deletes the currently selected text from the
buffer and stores it in the Clipboard and the kill ring.
The copy generic function adds the currently selected text to the
Clipboard and pushes it onto the kill ring. The selection is not
removed from the window or dialog item.
The paste generic function replaces the currently selected text with
the text in the Clipboard. If no text is selected, the text in the
Clipboard is inserted at the insertion point.
The clear generic function deletes the currently selected text from
the buffer without storing it in the Clipboard or the kill ring.
The undo generic function undoes the most recent edit if it can be
undone.
The undo-more generic function undoes edits earlier in the edit
history if they can be undone.
Example
The following code indicates that *top-listener* contains a selection that can be
cut.
? (window-can-do-operation *top-listener* 'cut)
T
Multiple-level Undo
To support Undo, Fred buffers keep a history list of all changes that have been made
since the buffer was created (or up to a user-definable limit imposed by *fred-
history-length* ). When an Undo command is issued, the most recent command on
the history list is undone. Repeatedly issuing Undo commands undoes earlier and
earlier changes, back to the initial state of the buffer or to the limit imposed by
*fred-history-length* .
A single Fred command may involve several insertions and deletions. In the functions
that relate to Undo, the argumentappend-p indicates that an insertion or a deletion
is part of the same operation as the previous insertion or deletion.
ed-insert-with-undo [Function ]
set-fred-undo-string [Function ]
Examples
The kill ring is a circular list containing text that has been deleted from Fred
windows or dialog items. Each item in the kill ring is acons cell. The car of the
cons contains a string. Thecdr of the cons contains either a style vector ornil
(style vectors are described in the section “Using Multiple Fonts” earlier in this
chapter).
add-to-killed-strings [Function ]
Argument string-style-cons
A cons whose car is a string and whosecdr is a
style vector or nil.
rotate-killed-strings [Function ]
Each instance offred-window has its own minibuffer, an instance of the class
mini -
buffer that is accessed with view-mini-buffer . Minibuffers are output streams
with some additional features.
Some of the following generic functions are associated with methods for Fred
windows and some with methods for minibuffers.
Because minibuffers are streams, you can use them as the first argumentformat
to .
Sending a newline will clear the minibuffer.
The minibuffer shows only the last line printed. Sending a newline
clears the minibuffer.
Description The stream-column generic function returns the length of the text
displayed in the minibuffer.
def-fred-command [Macro ]
Example
The following system is used to translate keystroke events into Fred actions.
This section describes the functions that allow the user to associate Lisp functions
with keystrokes.
In normal operation, keystrokes are handled by the active window. Fred treats every
keystroke typed in a Fred window as a command. Associated with every possible
keystroke is a Lisp function that implements the command. Some commands are
simple; for example, pressingA is a command to insertA in the buffer. Some are more
complex; for example, pressing Control-Meta-Shift-F is a command to select one - s
expression forward. Fred makes no distinction between these two kinds of commands.
Indeed, you can easily redefineA to perform a complicated series of actions.
When you press a key in a Fred window, Fred first translates it intokeystroke
a code .
The keystroke code contains a character and four flags called meta, control, function,
and shift . The keystroke is encoded as a small integer, with the character code in
bits 0 through 7, the meta flag in bit 8, the control flag in bit 9, the function flag in bit
10, and the shift flag in bit 11. See Table 14-1.
The :function modifier is used to support the function keys on the Apple Extended
Keyboard. The function keys are named using the characters
#\1 through #\9 and
#\a through #\f. For example, the F1 key has the keystroke name(:function
#\1), the F10 key has the name(:function #\a) , and the F15 key has the name
(:function #\f) .
You should note that the keystroke code for a letter with the shift bit set is not equal
to the keystroke code for a shifted letter. That is:
? (keystroke-code '(#\A))
65
? (keystroke-code '(:shift #\A))
2113
The binding between keystrokes and the functions they invoke is stored in a data
structure called acomtab (short for command table ). The global command table is
stored in the variable *comtab* . Each window withfred-mixin may contain a
local command table in a slot namedcomtab , the default value of which is
*comtab* . In addition, each window may also contain a shadowing command table,
which is initially nil.
When the function associated with the keystroke returns, Fred updates the display
of the window on the screen, making sure the cursor is visible. (The function may set
the variable *show-cursor-p* tonil to inhibit this.)
keystroke-name [Function ]
keystroke-code [Function ]
Example
? (keystroke-code '(:shift :meta #\F))
2406
? (keystroke-name 2406)
(:SHIFT :META #\F)
*last-command* [Variable ]
*current-character* [Variable ]
*current-keystroke* [Variable ]
The following MCL expressions are used to create and govern command tables.
*comtab* [Variable ]
Description The *comtab* variable is the global command table. You can
modify this command table or set the variable to a new command
table.
*listener-comtab* [Variable ]
Note that setting this variable to a new command table (as opposed
to modifying the command table it is set to) affects only those
Listeners created after the change.
*control-x-comtab* [Variable ]
make-comtab [Function ]
copy-comtab [Function ]
comtabp [Function ]
comtab-set-key [Function ]
Example
For example, the following form binds the F12 key to a command that prints the date
in the top window:
? (comtab-set-key *comtab* '(:function #\c) ;F12 key
#'(lambda
(d)
(multiple-value-bind
(second minutes hour date month year)
(get-decoded-time)
(declare (ignore second minutes hour))
(format d "~a/~a/~a"
month
date
(- year 1900))))
"print the date in the top window")
#<COMTAB #x2F9E99>
comtab-get-key [Function ]
Example
? (comtab-get-key *comtab* '(:meta #\h))
INSERT-HELLO
comtab-key-documentation [Function ]
Example
? (comtab-key-documentation *comtab* '(:function #\c))
"print the date in the top window"
comtab-find-keys [Function ]
Example
? (comtab-find-keys *comtab* 'ed-open-line)
(623)
Contents
Using the Foreign Function Interface / 518
High-level Foreign Function Interface operations / 518
Argument specifications / 523
Result flags / 526
Short example / 527
Low-level functions / 528
Calling Macintosh Common Lisp from foreign functions / 532
Extended example / 533
You should read this chapter if you plan to include calls to foreign
functions within Macintosh Common Lisp.
You should also be familiar with MPW object files, which are
documented inMPW: Macintosh Programmer’s Workshop
Development Environment .
517
Using the Foreign Function Interface
A call from Macintosh Common Lisp to a foreign function looks exactly like a call to
another MCL function. The MCL function that makes the call (and, for that matter,
the programmer) doesn’t even need to know that the function called was written in a
different language.
u Note: In the current version of Macintosh Common Lisp, Object Pascal foreign
functions are not called correctly. Functions produced by Fortran compilers may
not be called correctly.
To use the Foreign Function Interface you must load the file
ff.fasl , included in the
MCL Library folder, or evaluate the expression
? (require "ff")
The following high-level operations are used with the Foreign Function Interface.
They can be used only on object files in the MPW object file format.
Description The ff-load function loads the MPW object files specified by
files
and returns a foreign function environment.
Example
(setf (logical-pathname-translations "mpw")
'(("clib;**;*.*" "hard disk:mpw:libraries:clibraries:**:*.*")
("lib;**;*.*" "hard disk:mpw:libraries:libraries:**.*.*")
("**;*.*" "hard disk:mpw:**:*.*")))
(defparameter *c-libraries*
'("mpw:clib;stdclib.o""mpw:lib;interface.o"))
(ff-load "c-hacks;utils.c.o"
:ffenv-name 'c-utils
:libraries *c-libraries*
:library-entry-points
'("atoi" "strcmp"))
Example
defffun [Macro ]
deffcfun [Macro ]
deffpfun [Macro ]
Description These macros help you define an MCL interface to a foreign function.
You describe the arguments the function takes and the result it
returns, anddefffun defines an MCL function that performs
appropriate coercions and type checks on the arguments and calls the
foreign function. Thedeffcfun anddeffpfun macros are identical
to defffun except that they set the :language option.
Arguments lisp-name The name of the MCL function that is defined by the
macro. This must be a symbol.
entry-name The name of an active entry point in a foreign
function environment. It should be a string.Entry
point names arecase sensitive. If entry-name exists
in more than one loaded environment, the
environment used is undefined.
Example
The argument specifications of foreign function calls give information about each
argument the foreign function will receive, including the MCL type to expect and a
series of flags. The flags give information on the foreign type, the argument-passing
method, and the necessity for argument checking.
lisp-type Any valid MCL type specifier. It declares that the corresponding
argument to the MCL function will be of that type. If argument checking
is requested, acheck-type form is included in the MCL function. In
addition, lisp-type is used to select the argument-passing convention
and foreign type, if these are not explicitly specified. If lisp-type is a
symbol (not a list) and there are noflags , the parentheses around
argspec may be omitted.
flags Specify the format (foreign type) in which the corresponding argument
should be passed, the method for passing, and the necessity for
performing a type check of the argument. The following flags describe
the format (foreign type) of the argument to be passed to the foreign
function. They are mutually exclusive; that is, you may choose only one
of the possible values.
:long The foreign function is expecting a longword value. The MCL argument
should be an integer or a character (in which case itschar-code is
used). It can also be a four-character string or a symbol.
:word The foreign function is expecting a word value. The MCL argument
should be a fixnum. The low 16 bits of the value constitute the foreign
argument.
:double The foreign function is expecting a floating-point value in the machine
double format (8 bytes). The MCL argument should be of type double -
float.
:extended
The foreign function will receive a floating-point value in SANE
extended format (10 bytes). The MCL argument should be of type
double-float . The:extended flag is the default floating-point type
for C and Pascal.
:ptr The foreign function will receive a longword value. The argument
should be an object of typemacptr . (See Chapter 16, “Low-Level
Operating System Interface,” for a description of this MCL data type.)
If no foreign format flag is specified, a default is chosen based on the lisp-type and
the :language option, according to Table 15-1. If lisp-type is not listed in the table,
there is no default (and the foreign type must be specified).
Result flags
The type of the returned value is described by one of the following keywords. The
type determines how the result is coerced before it is passed back to Macintosh
Common Lisp.
:long The result is interpreted as a 32-bit signed integer and returned as a
signed MCL integer.
:full-long
The result is equivalent to :long; maintained for backward
compatibility.
:word The returned value is a 16-bit word. It is interpreted as a signed integer
and returned as a fixnum.
:double The foreign result is a double float. It is coerced to an MCL
double float.
:extended The foreign result is a float in extended format. It is coerced to
an MCL double float.
:float This is a synonym for:extended .
:char The foreign result is a character. The low 8 bits of the returned
value are interpreted as a character code and returned as an
MCL character.
:ptr The returned value is a 32-bit integer of typemacptr .
:novalue The foreign function returns no value. The MCL function returns
nil.
This is the default if the language is Pascal.
Short example
digitval (ch)
char ch;
{ if isdigit(ch) return ch - '0';
else return -1;
}
After compiling this file in MPW, you can use it from within Macintosh Common Lisp
as follows:
? (ff-load "test.c.o" :ffenv-name 'test
:libraries *c-libraries*)
#<A FF-ENV>
? (deffcfun (digit-value "digitval")
(character) :long)
DIGIT-VALUE
? (digit-value #\7)
7
? (digit-value #\A)
-1
The following low-level functions are used to implement the higher-level functions
described earlier in this chapter. You may want to use the low-level functions if you
require increased speed or flexibility. The ff-call function is faster than higher-
level functions because it is open-coded and the arguments are not coerced or checked
for types. This gives more flexibility at the cost of dependability.
If you use these functions, it is your responsibility to pass the right types; if you pass
the wrong types, the system will probably crash.
ff-call [Function ]
If the returned value is to be taken from the stack, room is left on the
stack for this value before any stack-based arguments are pushed.
The foreign function is entered atpointer with the return address on
the top of the stack. The function does not have to obey strict stack
discipline, but it must never lower the stack beyond its arguments (in
other words, it should never pop anything more than its arguments,
and it should not modify any data on the stack beyond the
arguments).
ff-lookup-entry [Function ]
Description The ff-lookup-entry function returns two values describing the entry
point namedentry-name . The entry point must be an active entry point in
some previously loaded environment. Note that entry point names are
case sensitive. The first value returned is a pointer to the entry point.
The second value is the A5 pointer for the environment where the entry
point was found. Ifentry-name does not exist,nil is returned. Ifentry -
name exists in more than one loaded environment, the specific
environment returned is undefined.
Examples
Here are two examples.
;frob is a foreign function:
? (multiple-value-bind (entry a5)
(ff-lookup-entry "frob")
(ff-call entry :a5 a5))
;FrobCount is a static integer variable:
? (format T "There are ~D frobs."
(%get-long
(ff-lookup-entry "FrobCount")))
%word-to-int [Function ]
Example
? (= (%word-to-int #xFFFF) -1)
T
? (= (%word-to-int 1) 1)
T
%copy-float [Function ]
Description The %copy-float function returns a copy of float , that is, a newly
consed floating-point number that iseql but noteq to float . The
argument can be an MCL double-float or a macptr to a memory
location that contains a 64-bit floating-point number in machine
format (see 68881 or SANE documentation for details).
A foreign function may call an MCL function, receive a returned value, and do further
processing before returning to Macintosh Common Lisp. An MCL function that is to be
called by a foreign function must be defined with one of the following macros. The
macros create a pointer, which can then be passed to the foreign function.
The defccallable macro is used to define MCL functions that can be called fromThe C.
defpascal macro is used to define MCL functions that can be called from the Macintosh
Toolbox or from user-written Pascal code.Both of these macros put an MCL function in the
function cell of a symbol and a pointer to the C or Pascal entry point in the value cell of a
symbol.
The defpascal and defccallable macros are described in Chapter 16, “Low-Level
Operating System Interface.”
The following example usesdefccallable . It uses a C function,addthree , that
takes two arguments: an integer and a pointer to an MCL function. The C function adds
1 to its first argument, then calls the MCL function pointed to by its second argument.
This MCL function is passed the incremented first argument.
The MCL function increments its argument and returns it, whereupon the C function
increments it again and returns the value. Here control passes from Macintosh
Common Lisp to C to Macintosh Common Lisp to C and finally back to Macintosh
Common Lisp.
The addthree function is accurately named only if it is passed a pointer to an MCL
function that takes afixnum argument, increments it, and returns the incremented
value.
Here is the C function:
int addthree (i, Lispfn)
int i, (*Lispfn) ();
{
i = i + 1;
i = (*Lispfn) (i);
return i + 1;
}
The MCLdefccallable macro sets the value of its first argument to the entry point
for the function that it defines. Here is the MCL macro:
? (defccallable add-one
(:long i :long))
(+ i 1))
ADD-ONE
Extended example
You may find it convenient to switch between MPW and Macintosh Common Lisp
while doing this. (Under Macintosh Operating System version 6, you must use
MultiFinder. MultiFinder functionality is built into system software version 7.)
Examples for testing the code are contained in the fileexample .test in the FF
Examples subfolder.
Contents
Interfacing to Macintosh data structures / 537
Upgrading from previous versions of Macintosh Common
Lisp / 538
Sharing data between Macintosh Common Lisp and the
Macintosh Operating System / 539
Macptrs / 539
Memory management / 541
Stack blocks / 542
Accessing memory / 543
Miscellaneous routines / 554
Strings, pointers, and handles / 554
Pascal VAR arguments / 559
The Pascal null pointer / 559
Callbacks to Lisp from the ROM / 559
You should read this chapter if you are accessing Macintosh data
structures at a low level. If you are using higher-level accessing, such
as through records and traps, you may wish to read this chapter for
background information.
535
When making any operating system call, you should be familiar
with its description in Inside Macintosh .
Please note the following changes if you are upgrading code from a previous version
of Macintosh Common Lisp:
n In previous versions of Macintosh Common Lisp, Lisp objects were constrained in
their range of addresses, and it was possible to determine from a thing’s address
whether it was a Lisp object and even what its data type was. Because Macintosh
Common Lisp now addresses a full 32 bits, Lisp objects may be stored in many more
locations, and it is not feasible to tell the data type of an object from its address.
n Because it is meaningful to distinguish between a 32-bit value that is used as an
address and one that is used for another purpose, Macintosh Common Lisp now
includes a new Lisp data type,macptr . Any MCL object with a 32-bit value that
represents a pointer to a Macintosh data structure must now be of typemacptr . To
distinguish them from Macintosh pointers that are not MCL objects, these objects
are called macptrs. (See the section “Macptrs” later in
this chapter.)
n All pointers to Macintosh data structures are macptrs.
n You cannot pass any other Lisp object, including
nil, to a function requiring a
macptr, and macptrs may never point to Lisp objects—only to the address of a
Macintosh data structure.
n The Pascal null pointer is now(%null-ptr) , a macptr equivalent to(%int-to -
ptr 0) . It is no longer equivalent to Macintosh Common Lisp
nil.
n The functioneql, noteq, compares two macptrs for equality.
n The functions%put-ptr , %put-long , and other functions that read and write to
memory locations were previously defined to return the pointer being used. In
Macintosh Common Lisp version 2 they returnnil.
n MCL data types that may be translated to Macintosh 32-bit longwords now
include four-character strings and symbols with four-character print names.
Macintosh Common Lisp manipulates two distinct sets of data: Macintosh data, such
as windows, patterns, and regions, and Lisp data, such as lists, symbols, and objects.
Lisp data and Macintosh data are stored in different places and in different formats.
Macintosh data is stored on the application heap, and Lisp data is stored on the Lisp
heap. These two heaps operate independently. Each piece of data belongs on either
one heap or the other.
Some Lisp data contains pointers to Macintosh data. For example, window objects
(Lisp data) contain Macintosh pointers to Macintosh window records (on the
Macintosh heap).
Macptrs
Two macptrs to the same address areeql but not necessarilyeq. That is, the two
pointers themselves may not be the same; the address they reference is the same. If
both x andy point to(%int-to-ptr 0) , then
? (eq x y)
...undetermined...
? (eql x y)
T
By taking advantage of the following in your code, you can ensure that macptrs
created incidentally are not allocated:
n Addresses that are consumed directly by primitive operations are not
encapsulated in macptrs. Of the MCL low-level functions for reading and writing
to memory locations, most avoid allocating macptrs. (See the sections “Accessing
Memory” and “Strings, Pointers, and Handles” later in this chapter.)
n Macptrs can be explicitly stack-allocated. When appropriate, you may use
dynamic-extent declarations to indicate that the compiler may safely
stack-allocate macptrs used in local contexts.
n Macptrs can be destructively modified with%setf-macptr (see the following
section).
Memory management
Macintosh Common Lisp works in cooperation with the Macintosh Memory Manager.
Thus you can use the traps#_NewPtr and#_NewHandle to allocate blocks of memory
on the application heap. The Macintosh and Lisp heaps are dynamically resized to
satisfy memory requests. This resizing sometimes triggers a garbage collection.
When you need a small amount of memory for temporary storage, it is often more
convenient and more efficient to bypass the Macintosh Memory Manager. The
%stack–block macro allows programs to allocate blocks of memory on the stack. Be
very careful using %stack–block . When you exit the %stack-block form, all the
memory allocated is reclaimed and so any remaining pointers to the stack block
become invalid. The %stack-block form should be used only for well-defined
temporary storage, for example, to set up rectangles or I/O parameter blocks to be
passed to traps, or to store
var arguments temporarily.
%stack-block [Macro ]
%vstack-block [Macro ]
Example
In this example, an 8-byte block is allocated on the stack. The memory is filled with
the coordinates of a rectangle. A pointer to the block—and two additional words —
are then passed to the trap#_FrameRoundRect. When the window is redrawn, a
rectangle with rounded corners appears at the given coordinates:
? (setq my-window (make-instance 'window))
#<WINDOW "Untitled" #x46E929>
? (defmethod view-draw-contents ((w (eql my-window)))
(let ((oval-width 12)
(oval-height 8))
(%stack-block ((my-rect 8))
(%put-word my-rect 12 0)
(%put-word my-rect 40 2)
(%put-word my-rect 32 4)
(%put-word my-rect 80 6)
(#_FrameRoundRect my-rect
oval-width oval-height))))
#<STANDARD-METHOD VIEW-DRAW-CONTENTS ((EQL #<WINDOW "Untitled"
#x46E929>))>
? (view-focus-and-draw-contents my-window)
NIL
Accessing memory
Once memory for a structure has been allocated, programs need methods for directly
reading from and writing to the memory. Macintosh Common Lisp provides the
following low-level functions for reading and writing to memory locations. (The
macrosrref andrset may be used. See Chapter 17, “Higher-Level Operating
System Interface,” for details.) Most calls to these functions are compiled inline for
efficiency.
%get-signed-byte [Function ]
%get-unsigned-byte [Function ]
%get-byte [Function ]
Description These equivalent functions get the byte (8 bits) atmacptr +offset and
return it as an unsigned Lisp integer in the range 0 through 255. The
compiler open-codes these functions.
Description The %hget-byte function accesses a handle, gets the byte (8 bits) at
handle + offset , and returns it as an unsigned Lisp integer in the range
0 through 255. The compiler open-codes this function.
%hget-signed-byte [Function ]
Description The %hget-byte function accesses a handle, gets the byte (8 bits) at
handle + offset, and returns it as a signed Lisp integer in the range
–
128 through 127. The compiler open-codes this function.
%get-signed-word [Function ]
Description The %get-signed-word function gets the word (16 bits) at macptr +
offset , sign-extends it, and returns it as a signed Lisp integer in the
range – 32,768 through 32,767. The compiler open-codes this function.
Description These equivalent functions get the word (16 bits) atmacptr + offset
and return it as an unsigned Lisp integer in the range 0 through
65,535. The compiler open-codes these functions.
%hget-word [Function ]
Description The %hget-word function accesses a handle, gets the word (16 bits)
at handle + offset, and returns it as an unsigned Lisp integer in the
range 0 through 65,535. The compiler open-codes this function.
%hget-signed-word [Function ]
Description These equivalent functions get the macptr atmacptr +offset and
return a signed Lisp integer in the range – 2,147,483,648 through
2,147,483,647. The compiler open-codes these functions.
%hget-long [Function ]
%hget-signed-long [Function ]
Description These functions access a handle, get the macptr athandle + offset,
and return a signed Lisp integer in the range –2,147,483,648 through
2,147,483,647. The compiler open-codes these functions.
%get-unsigned-long [Function ]
%get-ptr [Function ]
Description The %get-ptr function returns the macptr atmacptr +offset . The
compiler open-codes this function. The resulting macptr is heap -
consed unless it is used by another open-coded low-level primitive or
used as the initial binding of a variable that is declared to have
dynamic extent.
%hget-ptr [Function ]
Description The %hget-ptr function accesses a handle and returns the macptr at
handle +offset . The compiler open-codes this function.
Description The %get-string function gets the Pascal string atmacptr +offset
and returns it as a Lisp string. This function is not open-coded by the
compiler. If macptr points to a handle on the Macintosh heap, the
handle is dereferenced to access the string.
%get-cstring [Function ]
%get-ostype [Function ]
Description The %get-ostype function gets the 4 bytes atmacptr + offset and
returns them as an os-type, a keyword of four characters. (See
Inside
Macintosh for details on os-types.) It returns
nil.
Description The %put-byte function stores the low 8 bits of data at macptr +
offset . It returns nil. The compiler open-codes this function.
%hput-byte [Function ]
Description The %hput-byte function accesses a handle and stores the low 8 bits
of data at handle + offset . It returns nil. The compiler open-codes
this function.
%put-word [Function ]
Description The %put-word function stores the low 16 bits of data at macptr +
offset . It returns nil. The compiler open-codes this function.
%put-long [Function ]
%put-full-long [Function ]
Description These functions store the integer value ofdata at macptr + offset .
(The function %put-full-long is included for backward
compatibility; both functions allow full 32-bit accuracy.) The
compiler open-codes these functions.
%hput-long [Function ]
Description The %hput-long function accesses a handle and stores the integer
value of data at handle + offset . The compiler open-codes this
function.
%put-ptr [Function ]
%hput-ptr [Function ]
%put-string [Function ]
%put-cstring [Function ]
%put-ostype [Function ]
The following routines provide additional tools and information for communicating
between Macintosh Common Lisp and the Macintosh Operating System. These
include a set of functions for performing various types of data conversion and handle
dereferencing, information on Pascal VARarguments and Boolean values, and the
definitions of Lisp functions that can be called by ROM routines.
The following utilities are provided for using strings, pointers, and handles.
with-pstrs [Macro ]
with-cstrs [Macro ]
with-returned-pstrs [Macro ]
Arguments symbol A symbol that is bound to the Pascal string for the
duration of the macro.
string A string with a maximum length of 255 characters.
start The position at which to begin reading characters
from the string.
end The position at which to stop reading characters
from the string.
form Zero or more forms that make up the body of the
macro.
macptrp [Function ]
pointerp [Function ]
Description The pointerp function returnst if and only if the address that
macptr contains is in RAM; otherwise, it returnsnil. If macptr is not
a macptr, an error is signaled.
handlep [Function ]
with-pointers [Macro ]
%incf-ptr [Macro ]
%ptr-to-int [Function ]
%int-to-ptr [Function ]
Pascal VAR arguments are passed by reference rather than by value; that is, you
pass the function of a pointer to a piece of data rather than to the data itself. The
called function may then affect the data and in this way communicate information to
the caller. Implementing VAR arguments in Macintosh Common Lisp is very easy.
Just allocate memory of the appropriate size for the piece of data (either on the
stack or on the Macintosh heap, depending on how long you want to use that piece of
data) and pass the macptr as the VAR argument.
The following two MCL expressions relate to the Pascal null pointer.
%null-ptr [Macro ]
Syntax %null-ptr
%null-ptr-p [Function ]
The following macros define Lisp functions that can be passed to the ROM or other C
or Pascal code. This lets the other code make callbacks to Lisp.
defccallable [Macro ]
Description The syntax of these macros is similar to that ofdefun , except that
the lambda list contains alternating types and parameter names and
ends with a type specifier for the value returned by the procedure.
The &optional , &keyword , and&rest keywords are not permitted,
because they are not supported by the Pascal- or
C-calling sequences.
Contents
Traps and records / 565
Changes from previous versions of Macintosh Common
Lisp / 565
Traps / 566
Loading trap definitions / 567
Defining a trap / 569
Examples of calling traps / 570
Determining record types and record field types / 571
Records / 574
Installing record definitions / 575
The structure of records / 575
Defining record types / 576
Variant fields / 579
Creating records / 580
Creating temporary records withrlet / 580
Creating records with indefinite extent / 582
Using records / 584
Getting information about records / 593
Trap calls usingstack-trap andregister-trap / 594
Low-level stack trap calls / 595
Low-level register trap calls / 597
Lisp macros for calling Macintosh traps / 598
Notes on trap calls / 603
32-bit immediate quantities / 603
Boolean values: Pascal true and false / 604
563
You should read this chapter if you are using records or traps within
Macintosh Common Lisp or if you are using Macintosh Common Lisp
to program applications on the Macintosh. Traps discussed in this
chapter are those documented inInside Macintosh , so this chapter
assumes some familiarity with Inside Macintosh .
You must keep some caveats in mind when sharing data between
Macintosh Common Lisp and the Macintosh Operating System.
These are described in the first three sections of Chapter 16, “Low
-
Level Operating System Interface.” You should be familiar with the
information in those sections before reading the rest of this chapter.
Traps call procedures in the Macintosh Operating System. (They are defined and
discussed inInside Macintosh. ) Traps often require the allocation ofrecords,areas of
Macintosh memory usually stored as Pascal records. For example, the procedure to
draw and fill an oval in a window requires calling a trap—calling a Macintosh
Operating System procedure that knows how to draw and fill an oval. That trap in
turn requires an area of memory, a record, to store the rectangle that defines the
filled oval.
MCL functions and programs work efficiently with traps and records. You can easily
access and alter data structures created at run time (such as windows and event
records) as well as Macintosh resources.
The traps mechanism has been simplified and made more robust in this version of
Macintosh Common Lisp. Macintosh Common Lisp now has interface files containing
information about all Macintosh Operating System traps, constants, records, and
mactypes. If the value of *autoload-traps* is true, information is automatically
loaded from the relevant interface file when the trap is called. This functionality is
described next.
This file is still available for backward compatibility. New code should use the new
implementation of traps, described immediately following.
Names of record formats and trap calls in Macintosh Common Lisp correspond to
those in MPW andInside Macintosh . In Macintosh Common Lisp, however, calls to
the operating system are indicated by the reader macros number sign–underscore #_)(
or number sign–dollar sign#$).
( (See the section “Loading Trap Definitions” later in
this chapter.)
Traps
On the Macintosh, the Toolbox and operating system reside in ROM. However, to
allow flexibility for future development, application code must be kept free of
specific ROM addresses, so all references to Toolbox and operating system routines
must be made indirectly through atrap dispatch table.To issue a call in assembly
language to the Toolbox or operating system, you usetrap
a macrodefined in a set of
macro files.
An attempt to execute any instruction word beginning with$A causes a trap to the
trap dispatcher, which determines what operation the trap word stands for, looks
up the address of the corresponding routine in the trap dispatch table, and jumps to
the routine.
In the Interfaces folder, a subfolder of Library, are source files giving definitions of
over 2000 Macintosh traps described in Inside Macintosh .
u Note: The autoloading mechanism uses the index files in the folder
ccl:library;interfaces;index; to find trap and constant definitions. If
you modify any of the interface files, you must evaluate the form(reindex -
interfaces) to update the index files.
Syntax #_symbol
Syntax #$symbol
Since #_ and#$ are reader macros, they are evaluated only at read time. Therefore,
if you include autoloaded symbols in a macroexpansion, you must require-trap
use
or require-trap-constant .
require-trap [Macro ]
Example
? (defmacro draw-string (string start end)
(let ((pstr (gensym)))
`(with-pstr (,pstr ,string ,start ,end)
(require-trap #_DrawString ,pstr))))
DRAW-STRING
require-trap-constant [Macro ]
Syntax reindex-interfaces
Defining a trap
deftrap [Macro ]
Description The deftrap macro makestrap-name into a symbol for a trap and
defines the behavior of the trap.
Example
The macrodeftrap is used extensively in the files in the Interfaces subfolder of your
MCL Library folder.
This section gives several examples of calling traps.All of these traps make
ephemeral records with rlet , which is used to create a record for the duration of a
procedure call.
The following code creates a new window and draws inside it, using Macintosh
Operating System traps that require records.
Within Lisp, call the PaintRoundRect procedure to draw and fill a rectangle
inside the window. This Inside Macintosh definition of this procedure is as follows:
The data type of the first argument,r, is :rect (see Inside Macintosh ), so you must
define a record with rlet or make-record . Then call the trap from within
Macintosh Common Lisp using #_PaintRoundRect , which corresponds to the
PaintRoundRect procedure.
(rlet ((r :rect :top 20 :left 20 :bottom 80 :right 60))
(with-focused-view *w*
(#_paintroundrect r 30 30)))
A call to the trap PtToAngle (see Inside Macintosh ) gets a result by passing an
argument by reference:
? (rlet ((angle :integer)
(r :rect :topleft #@(100 50)
:bottomright #@(120 70)))
(with-focused-view *w*
(#_Framerect r)
(#_moveto 110 60)
(#_lineto 150 20)
(#_PtToAngle r #@(150 20) angle)
(%get-word angle)))
This trap call creates a record to hold the result of the call toStuffHex (see Inside
Macintosh ), which translates a Pascal string into binary data. It creates another
record to call the rectangle required byFillOval , and finally it draws the oval
with the pattern in the window:
? (rlet ((pat :pattern))
(with-pstrs ((hex-string "1020408102040801"))
(#_stuffhex pat hex-string)
(rlet ((r :rect :topleft #@(200 20)
:bottomright #@(250 100)))
(with-focused-view *w*
(#_filloval r pat)))))
When you are creating a trap, you must know the data types of the arguments. You
can determine them by consulting the trap definition inInside Macintosh. The data
type of all arguments is shown at the end of each chapter.
array macptr
boolean t or nil
byte fixnum
char Lisp character (#\char )
handle macptr
integer fixnum
longword integer
os-type fixnum , string, or symbol
usually a symbol, such as':|STR |
point fixnum or point made with#@(h v)
pointer macptr
string macptr made bywith-pstrs
Anything passed by reference (VAR; macptr
can be made withrlet
or %stack-block )
Other records, i.e., a record made macptr
with make-record or rlet
find-record-descriptor [Function ]
record-length [Macro ]
record-fields [Function ]
Description The record-info function returns a list of the offset, type, and
length of each field in record-type.
field-info [Function ]
Description The field-info function returns the offset, type, and length of the
field field-name of record-type.
Records
Records can be viewed from two perspectives: how they are stored and used and how
they are passed by Lisp.
Records keep track of blocks of Macintosh memory within Macintosh Common Lisp.
As stored and used, record
a is a contiguous structured block of memory of a specific
size, stored on the stack or Macintosh heap. As passed around by Lisp, a record is a
simple pointer to Macintosh memory, with no formatting or length information.
In the following discussion, the wordrecord can mean either a block of memory or a
pointer to memory, depending on the context. For example, when you allocate a new
record with make-record , a block of memory is allocated on the heap, and a pointer
to the block is returned. For the sake of brevity, this process is described in this way:
a record is allocated and returned.
In the Interfaces folder, a subfolder of Library, are source files giving definitions of
many of the Macintosh records described in Inside Macintosh .
If you reference a known Macintosh record and the value of
*autoload-traps* is
true, the record definition is automatically loaded.
Other records may be defined with the macrodefrecord .
Many standard record types are already defined in the Interface files. However, you
can also define your own record types with
defrecord .
defrecord [Macro ]
Arguments record-name Either a symbol that will be used to name the type of
record, or a list whosecar is the symbol used to name
the record and whosecadr is a keyword that
specifies the default type of storage used for the
record. See the note at the end of this definition on
overriding default record storage.
The package of the symbol used to name the record is
ignored; all record names are converted to the
keyword package.
The keyword should be either :pointer or
:handle . If the keyword is :pointer , records of
this record type are allocated and accessed as
pointers. If the keyword is:handle , they are
allocated and accessed as handles. If no keyword is
given, the record type is assumed to be
:pointer .
slot-descriptions
One or more slot descriptions. A standard slot
description is a list of the form(name type
{option }*).
name The name used to access the field in the record. The
name cannot bevariant , which has special meaning
(see the next section, “Variant Fields”).
Examples
This call, one of the calls in the Interface files, creates a record type called
PenState with four slots.
? (defrecord foo
(field1 :integer :default 42)
(field2 (array :longint 10))
(field3 (array :byte 5 5))
(field4 (some-record-type :handle))
(field5 (:string 255)))
s Important The Macintosh ROM is very strict about whether records are
passed to it by handle or by pointer. It is recommended that you
explicitly specify the storage type by using the:storage
keyword in calls tomake-record andrref or by using thehref
or pref macros. s
MCL records correspond exactly to MPW Pascal packed records, except that Boolean
fields always take up a full byte. Fields that are 2 or more bytes long always begin
at word boundaries (that is, at even memory locations). Fields that are 1 byte long
are padded to 2 bytes if necessary. See Inside Macintosh for more details on field
size.
Table 17-2 lists the predefined record field types and their lengths.
array 4 pointer
boolean 1
byte 1 unsigned-byte
signed-byte 1
unsigned-byte 1 byte
character 1
handle 4
integer 2 unsigned-integer
signed-integer 2
unsigned-integer 2 integer
long 4 signed-long
signed-long 4
unsigned-long 4
longint 4 signed-long
(continued)
signed-longint 4 signed-long
unsigned-longint 4 unsigned-long
ostype 4
point 4
pointer 4
short 2 unsigned-integer
signed-short 2 signed-integer
unsigned-short 2 unsigned-integer
string 4
word 2 unsigned-integer
signed-word 2 signed-integer
unsigned-word 2 unsigned-integer
Variant fields
You can usevariant fields to access the same portion of a record in different ways.
Variant fields allow an area of a record to be mapped to different sets of fields. For
example, you can use variant fields to access one part of a record as a single longword
or as 4 bytes. Variant fields (like records in general) are useful mnemonic aids and
short cuts. The size of a variant field is equal to the total size of the largest set of
fields in the variant portion.
The section of the record described by the variant may be accessed through N sets of
fields. The size of the variant field is equal to the size of the largest set of fields.
You can specify an:origin keyword argument for a field. The keyword:origin
simply sets the offset counter.
Creating records
rlet [Macro ]
Description The rlet macro creates a temporary record on the stack and
evaluates form. The value of the last form is returned. Therlet
macro is the most efficient way to create temporary records.
The records are stored on the stack and are therefore ephemeral.
When the evaluation of forms is done, all the records vanish
irretrievably and should not be referenced. (This macro is similar to
%stack-block , to which rlet macroexpands.)
Examples
The binding is ephemeral; r no longer has a binding after the value of the last form
is returned:
? r
> Error: Unbound variable: R
> While executing: SYMBOL-VALUE
and then to
(let* ((r (ccl::%new-ptr 8)))
(declare (dynamic-extent r))
(ccl::%put-point r 655370 0)
(ccl::%put-point r 6553700 4)
(traps:_framerect r))
The record-type may also be a record field type. In that case,rlet allocates enough
storage for one of the specified record fields. For example, the call
(rlet ((p :point))...)
allocates enough storage to hold a point (that is, 4 bytes). When you allocate storage
using record field types, you cannot specify the initial contents.
When you want to return a record from a function, you must create a record that has
indefinite extent. The memory this record takes up is not subject to automatic garbage
collection; it uses space in the Macintosh heap until it is explicitly disposed of.
Some records, such as windows, must be created and initialized by specific Toolbox
routines. Such records should be created not by using
make-record but by using the
appropriate Toolbox traps.
make-record [Macro ]
Description The make-record macro allocates space in the Macintosh heap for
a recordrecord-name and returns a pointer or a handle to it. This
record has indefinite extent (as opposed to blocks allocated with
%stack-block or rlet).
Arguments record-name Either a symbol that will be used to name the type of
record, or a list whosecar is the symbol used to name
the record and whosecadr is a keyword that
specifies the default type of storage used for the
record. The keyword should be one of the following:
:storage A keyword used to override the default storage
method used by the record. If specified, this should
be :pointer or :handle .
Using records
href [Macro ]
Description The href macro returns the contents of the specified field ofhandle .
This macro is the most efficient way to access the fields of a record.
pref [Macro ]
Description The pref macro returns the contents of the specified field ofpointer .
This macro is the most efficient way to access the fields of a record.
rref [Macro ]
Description The rref macro returns the contents of the specified field ofrecord .
This macro is the most efficient way to access the fields of a record.
Examples
rset [Macro ]
Examples
(rset wptr :window.portrect.topleft #@(100 200))
(rset my-rect :rect.left -10)
(rset teptr :terec.viewrect.top 50 :storage :pointer)
(rset my-control :control.controlvalue 200)
raref [Macro ]
Example
Assume that you have a record typefoo.
(defrecord foo
(field1 :integer :default 42)
(field2 (array :longint 10))
(field3 (array :byte 5 5))
(field4 (some-record-type :handle))
(field5 (:string 255)))
rarset [Macro ]
clear-record [Macro ]
get-record-field [Function ]
The following functions give information on records. They are provided primarily for
use during development and debugging of programs that use records.
*record-types* [Variable ]
*mactypes* [Variable ]
Description The *mactypes* variable contains a list of all the field types for
use in records. (Note that this list does not include record types
themselves, which can also be used as field types.)
Description The print-record function prints the values of the fields ofrecord
of type record-type . No values are returned.
handle-locked-p [Function ]
Most older Macintosh traps accept arguments either on the stack or in registers, but
not in both places. Some newer traps accept arguments through both. In general, the
operating system traps are register based and the Toolbox traps are stack based, but
there are exceptions.
Within a single trap call, some arguments are passed as immediate values and some
are passed by reference (that is, a pointer to the value is passed). In general, data 4
bytes long or less is passed by value, and data longer than 4 bytes is passed by
reference. Check Inside Macintosh for the calling sequences of particular traps.
Arguments passed by reference (Pascal VAR parameters) may be modified by
the trap.
For each trap TrapName , the file traps.lisp in the Library folder defines a
constant_TrapName (equal to the trap number) and a macro _TrapName that
expands into the trap call and is recognized by the compiler. You can use
stack-
trap, register-trap , and %gen-trap to call any trap.
_TrapName [Macro ]
Examples
This form calls the trap FrameRoundRect with three arguments: a pointer and two
words. The valuenil is returned.
? (let ((oval-width 12)
(oval-height 8))
(%stack-block ((my-rect 8)) ;rectangles are 8 bytes
(%put-word my-rect 12 0) ;top=12
(%put-word my-rect 40 2) ;left=40
(%put-word my-rect 32 4) ;bottom=32
(%put-word my-rect 80 6) ;right=80
(_FrameRoundRect:ptr my-rect
:word oval-width
:word oval-height)))
The following two forms are equivalent, although the first is much easier to read:
? (_GetResource :ostype "STR#" ;ASCII "STR#"
:word 15 ;resource number 15
:ptr) ;return value is pointer
Note that in the second form, the components of the resource type are pushed in
reverse order so that they will be in the correct order on the stack.
_TrapName [Macro ]
stack-trap [Macro ]
Arguments :check-error
Signals an error if the trap returns a negative value
in register d0.
trap-number Evaluates to a 68000 A-trap instruction. These
instructions can be found in
Inside Macintosh . If
trap-number is specified as a compile-time constant
expression, the trap call can be open-coded by the
compiler.
register-keyword
Specifies the register that holds the subsequent
argument. Recognized register keywords are:a0
through :a6 and:d0 through :d7.
argument An argument to a register call. Arguments are
evaluated in left-to-right order and placed in
registers. Arguments to be placed in data registers
should be 32-bit values. Arguments placed in address
registers should be macptrs.
:trap-modifier-bits bitmask
Anywhere that a register-keyword /argument pair
may appear, the sequence:trap-modifier-bits
bitmask is also allowed. The :trap-modifier -
bits specifier causes the associated bitmask to be
logical-ored with the value of _TrapName and the
resulting value used as the trap number. The
placement of any:trap-modifier-bits forms in
the argument list is not significant.
return-register-keyword
Specifies which register holds the value returned by
the trap (if any). Recognized register keywords are
:a0 through :a6 and:d0 through :d7.
Placement is not significant; this call is equivalent to any of the preceding ones.
(_NewPtr :d0 10 :trap-modifier-bits #$trap-clear-bitmask :a0)
%gen-trap [Function ]
The following sections discuss 32-bit immediate quantities and Boolean true and
false values.
Pascal parses Boolean values as words (2 bytes) with bit 8 set. Macintosh Common
Lisp automatically converts between this representation and the MCL values nil
and t. Thus,
(stack-trap _button :boolean)
is equivalent to
(logbitp 8 (stack-trap _button :word))
and
(stack-trap foo :boolean x)
is equivalent to
(stack-trap foo :word (if x -1 0))
Contents
The Metaobject Protocol / 606
Metaobject classes defined in Macintosh Common Lisp / 606
Unsupported metaobject classes / 607
Unsupported Introspective MOP functions / 608
MCL functions relating to the Metaobject Protocol / 608
MCL class hierarchy / 621
Types and tag values / 621
Reader macros undefined in Common Lisp / 623
Numeric argument undefined in Common Lisp / 624
Numbers / 624
Characters / 626
Arrays / 626
Packages / 628
Additional printing variables / 629
Memory management / 630
Function swapping / 630
Garbage collection / 631
Ephemeral garbage collection / 632
Generations / 632
Memory management unit support / 632
Full garbage collection / 636
Evaluation / 637
Compilation / 638
Tail recursion elimination / 638
Self-referential calls / 638
Compiler policy objects / 638
Miscellaneous MCL expressions / 644
605
The Metaobject Protocol
Table A-1 shows the class structure of the metaobject classes defined in Macintosh
Common Lisp version 2. All the metaobject classes are instancesstandard-class
of
exceptgeneric-function andstandard-generic-function , which are
instances offuncallable-standard-class . They are not documented inCommon
Lisp: The Language, but some of them are documented in The Art of the Metaobject
Protocol.
standard-object t
structure-object t
metaobject standard-object
method-combination metaobject
long-method-combination method-combination
short-method-combination method-combination
standard-method-combination method-combination
method metaobject
standard-method method
standard-accessor-method standard-method
standard-writer-method standard-accessor-method
standard-reader-method standard-accessor-method
(continued)
generic-function metaobject
ccl::funcallable-standard-
object
standard-generic-function generic-function
specializer metaobject
class specializer
ccl::compile-time-class class
structure-class class
built-in-class class
ccl::std-class class
funcallable-standard-class std-class
standard-class std-class
The following metaobject classes do not exist in Macintosh Common Lisp version 2.0:
eql-specializer
forward-referenced-class
slot-definition
The following functions, which are part of the de facto Introspective MOP standard,
are not supported by Macintosh Common Lisp verson 2.0:
class-default-initargs
class-direct-default-initargs
generic-function-argument-precedence-order
generic-function-declarations
generic-function-initial-methods
generic-function-lambda-list
method-lambda-list
slot-boundp-using-class
slot-definition-class
slot-definition-allocation
slot-definition-initargs
slot-definition-initform
slot-definition-initfunction
slot-definition-name
slot-definition-readers
slot-definition-type
slot-definition-writers
slot-exists-p-using-class
slot-makunbound-using-class
slot-value-using-class
Example
? (defclass foo () ())
#<STANDARD-CLASS FOO>
? (defclass bratch (foo) ())
#<STANDARD-CLASS BRATCH>
? (defclass gronk (foo) ())
#<STANDARD-CLASS GRONK>
? (class-direct-subclasses (find-class 'foo))
(#<STANDARD-CLASS GRONK> #<STANDARD-CLASS BRATCH>)
? ? (class-direct-subclasses (find-class 'standard-object))
(#<STANDARD-CLASS FOO>
#<STANDARD-CLASS INSPECTOR::ERROR-FRAME>
#<STANDARD-CLASS INSPECTOR::UNDO-VIEW-MIXIN>
#<STANDARD-CLASS INSPECTOR::BOTTOM-LINE-MIXIN>
#<STANDARD-CLASS INSPECTOR::CACHE-ENTRY>
#<STANDARD-CLASS INSPECTOR::BASICS-FIRST-MIXIN>
#<STANDARD-CLASS INSPECTOR::OBJECT-FIRST-MIXIN>
#<STANDARD-CLASS INSPECTOR::UNBOUND-MARKER>
#<STANDARD-CLASS INSPECTOR::INSPECTOR> #<STANDARD-CLASS MENUBAR>
#<STANDARD-CLASS KEY-HANDLER-MIXIN> #<STANDARD-CLASS APPLICATION>
#<STANDARD-CLASS CONDITION> #<STANDARD-CLASS SCRAP-HANDLER>
#<STANDARD-CLASS CCL::LISP-WDEF-MIXIN>
#<STANDARD-CLASS CCL::INSTANCE-INITIALIZE-MIXIN>
#<STANDARD-CLASS FUNCALLABLE-STANDARD-OBJECT>
#<STANDARD-CLASS METAOBJECT>)
The file grapher.lisp in your MCL Examples folder contains a good example of the
use ofclass-direct-subclasses .
Example
? (defclass my-io-stream (input-stream output-stream) ())
#<STANDARD-CLASS MY-IO-STREAM>
? (class-direct-superclasses *)
(#<STANDARD-CLASS INPUT-STREAM> #<STANDARD-CLASS OUTPUT-STREAM>)
Example
? (defclass foo () ())
#<STANDARD-CLASS FOO>
? (class-precedence-list *)
(#<STANDARD-CLASS FOO> #<STANDARD-CLASS STANDARD-OBJECT> #<BUILT-IN -
CLASS T>)
? (defclass bar () ())
#<STANDARD-CLASS BAR>
? (class-precedence-list *)
(#<STANDARD-CLASS BAR> #<STANDARD-CLASS STANDARD-OBJECT> #<BUILT-IN -
CLASS T>)
? (defclass gronk (foo bar) ())
#<STANDARD-CLASS GRONK>
? (class-precedence-list *)
(#<STANDARD-CLASS GRONK> #<STANDARD-CLASS FOO> #<STANDARD-CLASS BAR>
#<STANDARD-CLASS STANDARD-OBJECT> #<BUILT-IN-CLASS T>)
Example
Example
Example
? (defmethod foo ((x integer)) x)
#<STANDARD-METHOD FOO (INTEGER)>
? (defmethod foo ((x fixnum)) (+ x (call-next-method)))
#<STANDARD-METHOD FOO (FIXNUM)>
? (generic-function-methods #'foo)
(#<STANDARD-METHOD FOO (FIXNUM)> #<STANDARD-METHOD FOO (INTEGER)>)
Example
? (defmethod foo ((x integer)) x)
#<STANDARD-METHOD FOO (INTEGER)>
? (method-name *)
FOO
Example
? (defmethod bar ((x integer) (y list)) (cons x y))
#<STANDARD-METHOD BAR (INTEGER LIST)>
? (method-specializers *)
(#<BUILT-IN-CLASS INTEGER> #<BUILT-IN-CLASS LIST>)
Example
? (defclass foo () (x y))
#<STANDARD-CLASS FOO>
? (mapcar 'slot-definition-name
(class-direct-instance-slots *))
(X Y)
Example
clear-specializer-direct-methods-caches [Function ]
Syntax clear-specializer-direct-methods-caches
clear-clos-caches [Function ]
Syntax clear-clos-caches
clear-gf-cache [Function ]
clear-all-gf-caches [Function ]
Syntax clear-all-gf-caches
method-exists-p [Function ]
Arguments generic-function
A generic function or a symbol naming a generic
function.
args One or more arguments to the generic function.
*check-call-next-method-with-args* [Variable ]
When the value of this variable is true (the default), then the check
is made to ensure that new arguments do not change the set of
methods that are applicable for the generic function.
*defmethod-congruency-override* [Variable ]
When the value of this variable is nil (the default), then an error
is signaled.
In Macintosh Common Lisp, references to Lisp objects are encoded in 32-bit 680x0
longwords. The 3 least significant bits of the longword are referred to as the object’s
tag and determine the type of the object (see the list of tag values that follows). In
the case ofimmediate objectssuch as fixnums, characters, and short floats, the value
of the object is contained in the remaining 29 bits. In other cases, the 32-bit longword
constitutes atagged pointerto the associated object.
A consequence of this tagging scheme is that all nonimmediate Lisp objects are
allocated on 8-byte boundaries.
n The tag value of 0 is used to represent fixnums; the two’s-complement value of the
fixnum is stored in the upper 29 bits of the longword. Fixnums can therefore store
values in the range -2^28 through (2^28)-1 , inclusive. Note that this
representation allows the direct use of machine arithmetic instructions where
applicable.
n The tag value of 1 is used to represent variable-length objects calleduvectors.
Objects with this tag include all arrays, CLOS instances, structure instances,
bignums, ratios, complex numbers, macptr pointers, packages, and a few more
internal types. A pointer that contains this tag points 1 byte beyond the beginning
of the storage occupied by the object it points to.
The mapping between tags and Common Lisp types is an implementation detail that
is likely to change in future version of Macintosh Common Lisp.
The following functions provide low-level access to objects that are tagged as
uvectors.
uvectorp [Function ]
uvref [Function ]
Description The uvref function returns the element ofobject at index. The
function signals an error unless(<= 1 index (uvsize object )).
Macintosh Common Lisp uses the CLOS #P syntax for pathnames, but it also has a
numeric argument that specifies one of four possible unusual conditions in the
pathname. These numeric arguments are an error in Common Lisp and should not be
used in portable code:
#3P Means that the type of a pathname is:unspecific and its name is
"".
Numbers
Two internal floating-point data formats are supported. The format used to represent
instances of the Common Lisp data types single-float , double-float , and
long-float corresponds to IEEE double or 64-bit floating-point format. Each such
floating-point number is 64 bits (8 bytes) long and consists of a sign bit, an 11-bit
binary exponent (allowing exponents in the range –1022 through 1023), and a 52-bit
significand. The significand precision is 53 bits.
The format used to represent instances of the Common Lisp data type short-float
consists of 3 tag bits, a sign bit, a 5-bit binary exponent, and a 23-bit significand (for
tags, see discussion of the tagging scheme, in the section “Types and Tag Values”
earlier in this appendix). This format is similar to the IEEE single format, but the
smaller exponent restricts the range of representable numbers (for example, the
values of least-positive-short-float and least-negative-short-float )
and does not allow the representation of denormalized numbers.
bignump [Function ]
fixnump [Function ]
lsh [Function ]
Description The lsh function logically shifts fixnum by count and returns the
result of the operation, which must also be a fixnum. This is the same
as the Common Lispash function, except that any bits shifted out of
the (currently) 29 bits of a fixnum are lost.
Characters are represented as immediate data. The character code is the 8-bit
extended ASCII value. In this release there is no support for theextended -
character type: all characters are of type base-character and all strings are of
type base-string .
The reader macros#\^@ through #\^_ can be used to read the characters with ASCII
values 0 through 31. More generally,#\^c, for any characterc, is equivalent to
(code-char (logxor 64 (char-code #\ c))). In addition, #\nnn, where nnn is
two or three octal digits, is equivalent to(code-char #o nnn).
Arrays
Table A-2 lists the distinct types of array element that are supported.
bit 1
character 8
double-float 64
(unsigned-byte 8) 8
(signed-byte 8) 8
(unsigned-byte 16) 16
(signed-byte 16) 16
(unsigned-byte 32) 32
(signed-byte 32) 32
t One node (32 bits per element)
bit most-positive-fixnum
character #xFFFFF8
double-float #x1FFFFF
(unsigned-byte 8) #xFFFFF8
(signed-byte 8) #xFFFFF8
(unsigned-byte 16) #x7FFFFC
(signed-byte 16) #x7FFFFC
(unsigned-byte 32) #x3FFFFE
(signed-byte 32) #x3FFFFE
t #x3FFFFE
All these limits represent arrays requiring approximately 16 MB of contiguous memory.
There is no limit on the size of individual dimensions of an array except the limits
imposed by the total array size.
Multidimensional arrays and arrays that were created with non-nil values for the
:displaced-to and/or the:fill-pointer arguments tomake-array are stored
as two vectors, a header and a storage vector.
displaced-array-p [Function ]
Example
? (setq a (make-array 10))
#(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
? (setq b (make-array 5
:displaced-to a
:displaced-index-offset 3))
#(NIL NIL NIL NIL NIL)
? (displaced-array-p b)
#(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
3
? (eq * a)
T
Packages
Macintosh Common Lisp, following the forthcoming ANSI Common Lisp standard,
uses the package namecommon-lisp instead oflisp. The only external symbols of
the COMMON- LISP package are the approximately 900 symbols of Common Lisp.
The CCL package uses theCOMMON -LISP package. Its exported symbols consist of
extensions to Common Lisp provided by Macintosh Common Lisp. CCL
The package
shadows none of the Common Lisp symbols.
The COMMON -LISP-USER package uses both theCCL and the COMMON -LISP packages.
The default value of the :use argument tomake-package and todefpackage is the value
of the variable *make-package-use-defaults* . The initial value of this variable is
("COMMON-LISP" "CCL") . (See Common Lisp: The Language, page 263.)
Macintosh Common Lisp includeslisp a package that behaves similarly to the one
described in the first edition ofCommon Lisp: The Language. However, full
compatibility is not guaranteed.
The variable *autoload-lisp-package* determines whether the LISP package is
loaded when it is first referenced. The value of*autoload-lisp-package* is nil. If you
are running your own code that depends on the LISP package, or using code such as PCL or
Richard Waters’s pretty printer (see Common Lisp: The Language, Chapter 27), you may
need to do one or more of the following:
Variable Purpose
Macintosh Common Lisp divides the application heap into two areas: a Lisp heap
and a Macintosh heap. Most Lisp data structures (suchconsas cells, symbols,
arrays, and functions) are stored in the Lisp heap; most Macintosh data structures
(such as Window records, bitmaps, and CODE resources) are stored in the Macintosh
heap.
Function swapping
purge-functions [Function ]
preload-all-functions [Function ]
Syntax preload-all-functions
The following code may be placed in aninit file to remove swapping completely:
(progn
(preload-all-functions)
(purge-functions NIL))
This is recommended for configurations with 3 MB or more of RAM.
Garbage collection
Macintosh Common Lisp performs two kinds of garbage collection, ephemeral and
full. They are described in this section.
Generations
This garbage collector is “lifetime based.” In cooperation with the storage allocation
primitives, the ephemeral garbage collector partitions the population of all
dynamically allocated objects into sets, called generations, whose members are
created at roughly the same time relative to the members of some other generation.
n Newly created objects are elements of the youngest generation (generation 0).
n When the total size of all objects in generation 0 exceeds a specified threshold,
ephemeral garbage collection is invoked. Those objects that were members of the
youngest generation and survive the ephemeral garbage collection are “promoted”
into the next older generation, generation 1.
n When generation 1 fills up, its partition is garbage collected and surviving objects
are promoted into the oldest generation, generation 2.
The current implementation maintains up to three ephemeral generations and one
nonephemeral generation.
n If and when enough objects have been promoted into the oldest generation to cause
that generation to fill up, a full garbage collection is performed.
The MCL kernel can provide MMU support to the ephemeral garbage collector in the
following circumstances:
n If a memory management unit is present. Currently, this means either a 68030 or 68040
processor, or a 68020 processor with a 68851 coprocessor.
n When the operating system either provides system calls to test and reset the modified
status of a memory page, or does not interfere with attempts to obtain such information
directly from the MMU hardware. Currently, this means that MMU support is not
available under A/UX.
n When the MMU is configured to use a reasonably small page size (8K or 4K). Currently,
this means either a 68040 processor, the use of the System 7 virtual memory, or the use of
the ptable system extension provided as part of the MCL distribution.
The ephemeral garbage collector is said to be enabled when Macintosh Common Lisp has
been asked to use it; it is said to be active when Macintosh Common Lisp is in fact using it. (It
may be enabled but inactive when, for instance, free space in the heap is less than the size
limit of the youngest generation.)
The following functions can be used to control and configure the ephemeral garbage collector.
egc [Function ]
Description The egc function attempts to enable and activate the ephemeral
garbage collector if the value of enable-p is true. (See the discussion of
enabling and activation preceding this definition.) If the value of
enable-p is nil, egc disables the ephemeral garbage collector. The
function returnst if the ephemeral garbage collector is enabled after
performing the operation, nil otherwise.
Syntax egc-enabled-p
Description The egc-enabled-p function returnst if the ephemeral garbage
collector is enabled and returnsnil otherwise.
egc-active-p [Function ]
Syntax egc-active-p
Description The egc-active-p function returnst if the ephemeral garbage
collector is active and returnsnil otherwise.
configure-egc [Function ]
egc-configuration [Function ]
Syntax egc-configuration
Syntax gctime
gccounts [Function ]
Syntax gccounts
gc-event-check-enabled-p [Function ]
Syntax gc-event-check-enabled-p
set-gc-event-check-enabled-p [Function ]
Evaluation
Macintosh Common Lisp offers two evaluator options: a standard evaluator and a
compiling evaluator.
n The standard evaluator conforms to Common Lisp standards as described in the
second edition ofCommon Lisp: The Language, Chapter 20. However,evalhook
and applyhook were removed from the Common Lisp standard by vote of the
X3J13 committee in November 1989 (afterCommon Lisp: The Language went to
press). Macintosh Common Lisp still supports them, but they are deprecated.
n The compiling evaluator compiles nontrivial expressions and then runs them. For
looping or self-recursive constructs, the compiling evaluator is much faster (up to
several hundred times). The compiling evaluator is used when the variable
*compile-definitions* is non-nil.
In the default environment, the system uses the compiling evaluator; that is, the
value of *compile -definitions* is t.
*compile-definitions* [Variable ]
If the value of this variable is true (the default), then all function
definitions and most top-level forms are compiled.
This section describes some of the behavior of the MCL compiler and describes some
means of influencing that behavior.
The MCL compiler attempts to minimize the stack usage of compiled functions by
being properly tail recursive. A function is tail recursive if it returns the value(s) of
the last function it calls as its own. In that case, the stack space allocated for the
function’s returned value(s) can be deallocated before it begins execution.
One side effect of the elimination of tail recursion is that, in general, the Stack
Backtrace tools display only a portion of the execution history, since those function calls
in which tail recursion was eliminated are no longer awaiting return values.
The compiler can be advised that tail recursion should never be eliminated from
calls to certain single-valued global functions. Do this by adding the names of those
functions to the list that is the value of the variable ccl::*nx-never-tail -
call*. You can also use customized compiler policy objects to control when the
compiler eliminates tail recursion. (See the section “Compiler Policy Objects” later
in this appendix.)
Self-referential calls
Within a named function, the compiler may assume that a call to a function of the
same name refers to the same function (unless that function has been declared not
inline). Although this approach allows such calls to be compiled slightly more
efficiently, debugging tools such astrace andadvise violate this assumption.
This aspect of the compiler’s behavior can also be controlled through appropriate
use of compiler policy objects.
new-compiler-policy [Function ]
Arguments :allow-tail-recursion-elimination
When this value is nil or a function that inspects
the environment and returnsnil, the compiler does
not eliminate tail recursion. The default value is a
function that returns true unless the value of the
debug optimize quantity in the environment is 3.
:inhibit-register-allocation
When this value is true or a function that returns
true, the compiler does not allocate frequently used
values in registers. The default value is a function
that returns true when the value of the debug
optimize quantity in the environment is 3.
:trust-declarations
When this value is true or a function that returns true
and the value of the safety optimize quantity in
the environment is not 3,the compiler attempts to
exploit type declarations to produce faster and/or
smaller code. If those declarations are incorrect, the
resulting code may show unpredictable behavior.
The default value is a function that returns true if,
within the environment, the value of the speed
optimize quantity is not less than the value of the
safety optimize quantity.
current-compiler-policy [Function ]
Syntax current-compiler-policy
current-file-compiler-policy [Function ]
Syntax current-file-compiler-policy
set-current-file-compiler-policy [Function ]
ignore-if-unused [Declaration ]
Syntax ignore-if-unused
*always-eval-user-defvars* [Variable ]
If the value of this variable is nil (the default) , then defvar acts
in the normal Common Lisp way (see Common Lisp: The Language,
pages 86–87).
require-type [Function ]
Example
? (require-type (front-window) 'window)
#<LISTENER "Listener" #x42DDB1>
? (require-type (target) 'listener)
> Error: value #<WINDOW "Inspector Central" #x4618A1> is not of the
expected type LISTENER.
structurep [Function ]
*loading-file-source-file* [Variable ]
Contents
The snapshot utility / 648
Creating images / 648
Removing Macintosh pointers / 651
The top-level function / 653
Setting the top-level function / 653
Catching errors and aborts / 654
Using *idle* and event-dispatch / 655
Using eval-enqueue / 655
This chapter describes the “snapshot utility,” which you can use to
save images (snapshots) of MCL environments and to create
customized applications.
647
The snapshot utility
This chapter describes a utility that you can use to save complex MCL states and
create customized MCL applications.
To create a customized version of Macintosh Common Lisp, arrange your system the
way you like (by loading files and so on) and then callsave-application . The
save-application function produces an MCL application containing your heap
image, then restarts Macintosh Common Lisp. The heap image will contain all the
states from files you have loaded and work you have done up to the moment you take
the snapshot.
If what you want is a set of predefined system startups, you can use an MCL
init
file. See the section “The init File” in Chapter 1, “The Macintosh Common Lisp
Environment.”
Creating images
The following functions and variables are used in the creation of images.
save-application [Function ]
If your program maintains pointers to the Macintosh heap, you should deallocate
these with a function included on the list*save-exit-functions* . You can then
reinitialize the pointers and handles with functions specified bydef-load -
pointers .
u Note: Leftover Macintosh pointers in a heap image can cause system crashes and
other erratic behavior.
The def-load-pointers macro can be used to allocate memory on the heap during
startup.
*lisp-cleanup-functions* [Variable ]
*save-exit-functions* [Variable ]
def-load-pointers [Macro ]
*lisp-startup-functions* [Variable ]
When Macintosh Common Lisp is running, a Lisp function is always running. For
example, during normal programming the functiontoplevel-loop runs. This
function takes input from the Listener (and other buffers), evaluates it, prints out the
result, and then gets another input.
Whenever the top-level function returns, the Lisp kernel arranges for it to be called
again. In this way Macintosh Common Lisp can run indefinitely. To quit Lisp, you set
the top-level function to nil and return from the current top-level function.
There are two ways to set the top-level function. The first is to make an explicit call
to the function%set-toplevel . The second is to specify a top-level function when
you call save-application .
Macintosh Common Lisp actually has two notions of the top-level function. One is
the function that is currently running. The other is the function (stored in a system
variable) that is called when the currently running top-level function returns. During
most programming sessions these are both the function toplevel-loop .
When you call %set-toplevel , you set the pending top-level function. Setting the
pending top-level function does not, however, cause an automatic exit from the top -
level function that is currently running. The new pending top-level function is not
called until the top-level function that is currently running exits, either by returning
or through a system throw.
toplevel [Function ]
Syntax toplevel
Description The toplevel function throws past all pending catches to the Lisp
kernel, which then calls the pending top-level function. If the
pending top-level function isnil, Lisp exits to the Finder.
%set-toplevel [Function ]
Argument new-toplevel-function
A compiled function object or
nil. This argument
cannot be a symbol.
toplevel-loop [Function ]
Syntax toplevel-loop
You may want your top-level function to catch errors and aborts. If you don’t, errors
cause the Listener containing the error message to appear. Catching aborts is
especially important. If your top-level loop doesn’t catch them, pressing Command-
period causes the errorCan't throw to tag :abort to be displayed. You remain
in your top-level function.
Using*idle* andevent-dispatch
The variable *idle* lets your top-level function (or other parts of your program)
tell Macintosh Common Lisp when it is idling. If the value of*idle* is true,
Macintosh Common Lisp uses *idle-sleep-ticks* instead of*running-sleep -
ticks* as the sleep time for calls to#_WaitNextEvent . This approach gives the
maximum amount of time to background processes. During normal operation, *idle*
is bound tot by the top-level loop as it awaits input.
If your main program consists of a small loop waiting for events, you should place a
call to event-dispatch in the loop. This improves the response time to events and
gives background applications more time when your program is idling.
Usingeval-enqueue
An event (such as choosing a command or clicking a dialog box) that begins a long
process should not simply execute the process. If it does, the process runs with
interrupts disabled and future events are ignored until the process returns. This is fine
for quick actions but can be a problem for time-consuming actions. The process is
described in more detail in Chapter 11, “Events.”
The solution to this problem is for event actions to queue up forms. The forms are
received and processed in order by the top-level loop, which keeps interrupts
enabled.
There are many ways to queue up forms. The simplest is to push them onto a list and
have the top-level loop pop things from the list.
In many cases you may wish to have a single mechanism that works both with your
top-level function and with the standard top-level function,toplevel-loop . To do
this, you useeval-enqueue to queue up forms. When toplevel-loop is running, it
automatically gets these forms and evaluates them. Your top-level loop can do the
same thing by calling the function get-next-queued-form .
get-next-queued-form [Function ]
Syntax get-next-queued-form
Contents
Macintosh Common Lisp and the Common Lisp Object System
standard / 659
How CLOS differs from Object Lisp / 659
Definitions / 660
Classes and their superclasses / 660
Slots / 661
Instances / 661
Generic functions and methods / 661
Classes and instances / 662
Creating a class with the macro defclass / 662
Creating an instance and giving its slots values / 664
Redefining a class / 665
Allocating the value of a slot in a class / 666
Classes as prototypes of other classes / 667
Methods / 667
Defining a method and creating a generic function / 668
Congruent lambda lists / 669
Documentation of methods / 669
Defining methods on instances / 670
Creating and using accessor methods / 670
Customizing initialization with initialize-instance / 672
Creating subclasses and specializing their methods / 673
Method combination / 674
The primary method / 674
The primary method and the class precedence list / 674
Examples of classes with multiple superclasses / 675
When there is a conflict: Choosing between methods / 676
Choosing between methods associated with direct and with
more distant superclasses / 677
Creating auxiliary methods and using method qualifiers / 678
Mixin classes and auxiliary methods / 680
Extended example / 680
657
This appendix is directed toward users who are familiar with Object
Lisp, as implemented by Macintosh Common Lisp version 1.3 and
previous versions of Macintosh Common Lisp. It provides a summary
of the differences between Object Lisp and CLOS, with examples,
and includes an extended example of CLOS syntax.
If you are already familiar with the syntax of CLOS, you should
read Appendix D, “Converting Your Files to CLOS.” In that
appendix you will find general rules for conversion, some specific
changes to watch out for, and an extended comparison of CLOS and
Object Lisp code.
Macintosh Common Lisp uses the Common Lisp Object System (CLOS), the proposed
ANSI standard for the Common Lisp community. CLOS is based on five years of
experience with Common Lisp, augmented by substantive proposals and changes
suggested by its developers and users, and coordinated by X3J13, a subcommittee of
ANSI committee X3.
Common Lisp: The Language , second edition, written by Guy L. Steele and others,
provides detailed summaries of the X3J13 committee’s thinking. Though not an
official standards document, the second edition of Steele extensively documents
almost all functions that will be proposed in the draft standard. Some changes to the
standard have been approved since the time of publication of Common Lisp: The
Language. Where they affect Macintosh Common Lisp, these changes are
documented in the appropriate sections of this manual.
Wherever possible, the developers of Macintosh Common Lisp have included routines so
that your older MCL code will continue to run. However, your Object Lisp code will require
conversion; see Appendix D, “Converting Your Files to CLOS.”
As you write new code, you should consult the proposed standard as described in
Steele or in the draft ANSI standard.
Macintosh Common Lisp version 1.3 used the object protocol Object Lisp, which
supported multiple inheritance but only simple method combination. In Object Lisp
you could make an object fourth-grader with an instanceamanda , then create bob,
which inherited from amanda , andgeorge , which inherited from bob. CLOS uses a
class-instance protocol. In CLOS you cannot make a subclass from
amanda , because
amanda is not a class. Instead you must create another class, possibly a subclass of
fourth-grader .
Definitions
The basic concepts of CLOS include classes, slots, instances, generic functions, and methods.
A class is an object that determines the inherited behavior of other objects, called its
instances.
n Classes are organized in a hierarchy.
n A class can inherit structure from other classes, which are called itssuperclasses.
Its immediate superclasses are called itsdirect superclasses.A class is asubclass
of each of the classes from which it inherits.
n There are two classes at the top of the class hierarchy. The class namedt has no
superclasses and is a superclass of every class except itself. The class named
standard-object is a superclass of all the classes programmers create.
(However, it is not a superclass of some built-in classes.)
n A class has a name.
n A class has aclass precedence list,which is the total ordering of the class and all
its superclasses. When a class is defined, the order in which its direct
superclasses are mentioned determines the order of the class precedence list.
Most Common Lisp types now correspond to a class with the same name. That is, for a
type macptr , there will also be a class macptr .
Slots
Instances
Unlike Object Lisp, Macintosh Common Lisp version 2 maintains a clear distinction
between classes and instances.
n An instanceis a Common Lisp object, one of a group of zero or more instances of a
class. An instance may have a default state derived from the class definition, or
may have its own particular state.
n An instance may use a method defined on its class or on one of the class’s
superclasses, or may have its own method. See the next section for the definition
of methods.
n Unlike Object Lisp objects, CLOS instances cannot generally be used as classes.
n However, every Common Lisp object, even a class object, is an instance of some
class (for example, a class object may be an instance of the class
class).
Classes can be created and redefined. You can create instances of classes and give
values to slots in a class or an instance.
The macrodefclass creates a new class. Its first argument is a list of the
superclasses of the new class. If the argument is
nil, the new class is based on
standard-object .
Its second argument is a list of slot specifiers. Each slot is a list, the first element of
which is a symbol that names the slot. The second and third elements are the slot’s
initialization argumentand defaultinitial value form, if it has them. These appear
in definitions as the initarg andinitform keywords.
An instance has slots as determined by its class and that class’s superclasses.
You can set the values of an instance’s slots when you create it. The following
example creates an instance offourth-grader and uses the initialization argument
:teacher to override the default value for that slot:
? (setf john (make-instance 'fourth-grader
:teacher "Ms. Hsu"))
#<FOURTH-GRADER #x477181>
The functionslot-value retrieves the value of a slot. This function takes two
arguments, the class or instance and the name of the slot.
You can set the value of most slots of an already created instance by using
setf with
the name of the slot, for example, to give the instancejohn its own name (Figure C
-
2) or to change the value of the:teacher slot.
To find the slot value associated with an instance, CLOS first looks up the value
associated with the slot at the instance level. If the slot is unbound at the instance
level, CLOS looks up the value associated with the instance’s class. If the slot is
still unbound, CLOS looks for the value in the slot associated with the first class
that is a member of the class’s class precedence list, then looks in the slot of the
second class, and so on until it finds one value, which it returns.
Redefining a class
To redefine a class, simply edit the previous definition of the class and evaluate it
again. Here is a revised definition of fourth-grader , adding aschool slot :
? (defclass fourth-grader ()
((teacher :initarg :teacher
:initform "Mrs. Marple")
(school :initarg :school
:initform "Lawrence School")
(name :initarg :name)
(age :initarg :age :initform 9)))
#<STANDARD-CLASS FOURTH-GRADER>
When you create a new instance, you can specify a value for the
school slot.
You can specifically instruct a slot to be associated not with an instance, but with the
instance’s class, by using the:allocation option when you define the slot.
? (defclass picky-fourth-grader
(fourth-grader)
((subjects-studied
:initarg subjects-studied
:initform '(English math woodworking)
:allocation :class)))
#<STANDARD-CLASS PICKY-FOURTH-GRADER>
As you can see from the example “Creating an Instance and Giving Its Slots Values”
earlier in this appendix you can build classes from other classes. Subclasses may add
slots or change the default initial value of a slot that already exists. Subclasses may
also have their own methods (see the next section, “Methods”).
The instance mariah inherits slots and values it does not redefine.
? (slot-value mariah 'school)
"Lawrence School"
Methods
CLOS is built on the idea that many functions operate in different ways when called
on different classes of objects. Any function that operates in more than one way is
called a generic function,a Lisp function whose behavior depends on the parameters
supplied to it. Like any other Lisp function, a generic function can be passed as an
argument and returned as a value, and it does all the other things a function does.
In cases where the instance’s class has a complex parentage, methods may be
combined. What the function does—which bodies of code are called and how they
are combined—is calculated from theclass precedence list,the total ordering of the
set of classes from which a class inherits. It also depends on the method combination
type.
All methods on a generic function have congruent lambda lists. That is, they have
the same number of required and optional arguments. (For full details on congruent
lambda lists, see Common Lisp: The Language , pages 791–792.) For example, the
generic function #'say always requires an instance to which it is applied and a
sentence.
Documentation of methods
In this book, methods on generic functions are documented as follows. The function
name is in bold in the header. The syntax of methods is given below the header. The
name of the class for which the generic function has a method is in Courier (this class
is called the specializer). The arguments are in italics, and the initialization
argument keywords (if any) are in Courier. The action of the function is described,
and the arguments are described at the end of the body of the definition.
You can specialize methods on individual instances as well as on entire classes. If you
need a method for#'say that is called only onalisa, an instance offourth -
grader, then specify child to beeql toalisa , as shown in the following example.
The expression(declare (ignore sentence)) avoids a compiler warning. The
function(call-next-method) calls the next most specific method, which is the
method onfourth-grader :
Applied to other fourth-graders, such assharon , say still calls its usual fourth -
grader method.
? (say sharon "Hello")
***Hello!***
NIL
Using accessors to read and write the values of slots is preferable because accessor
methods hide implementation detail. Your clients can call the accessor method
without knowing whether it accesses a slot or computes a value in some other way.
The implementation can later change without affecting the client’s code.
Here is the fourth-grader class redefined using accessor methods. The accessor
doesn’t need to have the same name as the slot; here the accessor of the slot
teacher
is namedfourth-grade-teacher :
? (defclass fourth-grader ()
((teacher :initarg :teacher
:initform "Mrs. Marple"
:accessor fourth-grade-teacher)
(name :initarg :name
:reader name)
(school :initarg :school
:initform "Lawrence School"
:accessor school)
(age :initarg :age
:initform 9
:accessor age)))
? (fourth-grade-teacher delia)
"Mr. Smith"
? (age delia)
9
Accessor methods create regular generic functions and can be used just like any other
Lisp functions. For instance, you can combinefourth-grader methods say and
school to have an instance offourth-grader report on the school it goes to.
Because all look-ups occur at run time, this works even though
say was defined
before fourth-grader was redefined.
Creating instances is not only a matter of associating values with slots; other
initialization must often be performed. You specify what needs to be done by
specializing the generic function initialize-instance . A method on
initialize-instance for fourth-grader might look like the following:
(defmethod initialize-instance ((child fourth-grader) &rest initargs)
(add-to-class-list child)
(check-vaccinations child)
(check-special-programs child))
When you create a subclass, you can write methods specific to that subclass.
An instance of a subclass still inherits slot values and methods from its class’s
superclasses.
? (school max)
"Lawrence School"
u Note: This and the following sections provide a very simplified summary of
method combination. For full details seeCommon Lisp: The Language .
How does a function decide which method to use for a particular set of arguments?
There are two categories of methods. The first, theprimary method, defines the
main action of the effective method that the generic function applies to the instance.
The second category,auxiliary methods, may modify that action in one of three
ways. An auxiliary method has the method qualifier :before , :after , or
:around . They run before the primary method, after the primary method, or around
the primary method and all of its :before and:after methods.
The primary method applied to the instance is always the most specific method the
generic function has for the arguments it has been given. When a generic function has
a method for an instance, the instance’s method is used. If not, CLOS looks up
applicable methods for the instance’s direct superclass, then for that superclass’s
superclass, and so on. As soon as one applicable method is found, the search stops and
that method is applied to the instance. (If there is no applicable primary method,
the function signals an error.)
It is important to know in what order to look up methods. When a class has many
superclasses, behavior is determined by the ordered list of its superclasses—its class
precedence list. The class precedence list is basic to method combination.
However, when elements of the class precedence list have superclasses in common,
CLOS examines, in this order:
1. all of the elements of the first superclass except the class in common
2. all of the elements of the second superclass except the class in common
3. the class in common (followed by its superclasses)
We have seen simple class precedence at work in earlier examples. Let us look at
some examples of multiple superclasses.
When two classes inherit from the same superclasses, CLOS uses the class precedence
list to determine which primary method to use. For example, we can define two new
classes,happy-kid-with-homework andbored-kid-with-pet , that inherit
from the same superclasses, but in opposite order.
? (defclass happy-kid-with-homework
(happy-kid bored-kid)())
#<STANDARD-CLASS HAPPY-KID-WITH-HOMEWORK>
? (setq smiley (make-instance 'happy-kid-with-homework))
#<HAPPY-KID-WITH-HOMEWORK #x609C48>
When CLOS looks for a method, it examines a class before its direct superclasses and
a direct superclass before all other direct superclasses specified to its right in the list
of the class’s parents. Remember, if two of the direct superclasses of a class have a
superclass in common, then the order is
1. all of the elements of the first superclass except the class in common
2. all of the elements of the second superclass except the class in common
3. the class in common (followed by its superclasses)
Within those constraints, the local ordering of the class precedence list is
determined by taking all the elements of the class and doing a topological sort on
them.
Only one primary method can be applied to any set of arguments, but its behavior can
be modified using auxiliary methods.
All :before methods are run before the primary method. CLOS looks for :before
methods in the same order as it looks for primary methods: instance first, then class,
then direct superclasses. This order is calledmost specific first . After all applicable
:before methods have run, Macintosh Common Lisp calls the primary method,
then the :after methods in reverse order, from the:after methods associated
with t all the way down to the class and instance:after methods if there are any.
(This order is called least specific first .)
All :around methods (which are seldom used) specify code that is to be called
instead of other applicable methods, but can pass control to other methods, including
the primary, :before , and:after methods. The effect is that the :around
method runs “around” the other methods. An :around method usescall-next -
method to pass control to the other methods.
Mixins (not an official CLOS term) are ordinary CLOS classes with useful values or
methods that “mix in” some special behavior. They are generally not used alone, but
add their specializations to another class. In Macintosh Common Lisp, they usually
appear first in the class precedence list. The class that adds Fred behavior to a
window or dialog item,fred-mixin , is a mixin.
Extended example
This section shows a commented example of more realistic CLOS code than has been
used in this appendix so far. This code creates a new subclass of window, shape-
window, and a specialized scroller,shape-scroller . A shape window has a draw
area and a shape-scroller area, which contains two buttons, titled Circles and
Squares. Clicking inside the draw area causes the shape window to draw a shape,
either a circle or a square. Clicking inside the shape-scroller area does nothing.
Changing which radio button is pushed causes all the already drawn shapes to
redraw themselves in the new selected shape.
The code also contains a new menu bar, which includes a menu that changes the color
of the shapes.
u Note: If you are not running Macintosh Common Lisp in a color window, the
shapes display as black.
This code is compared with its Object Lisp equivalent in Appendix D, “Converting
Your Files to CLOS.” It is available in the file shapes_code.lisp in your
Examples folder.
Contents
General procedure for converting files to CLOS / 686
Turningdefobject andexist pairs into defclass and
initialize-instance pairs / 686
Turning occurrences of
defobfun into defmethod / 687
Replacing free variable references / 688
Removing calls to ask / 689
Replacing oneof with make-instance andkindof with
defclass / 689
Changing function names / 690
An extended example / 691
Calling packages and setting variables / 692
Turning calls todefobject andexist into defclass and
initialize-instance / 694
Turning other calls todefobfun into defmethod / 698
Removing ask and replacingoneof by make-instance / 700
Making a window instance / 704
685
General procedure for converting files to CLOS
In Macintosh Common Lisp 1.3,defobject generally contains the class hierarchy and
exist contains a group of uses have
of , with their default values. Most frequently, the
corresponding material in CLOS goes intodefclass with its slot specifiers.
If you usehave dynamically, you can deal with it in one of two ways. You can either
n transform uses ofhave into static slots and values indefclass
or
n put an association list as one of the slots in the
defclass , then redefine have to
put values on that association list and search for them
Here's an example of old and new versions of code. Here is the Object Lisp version.
? (setq fourth-grader (kindof nil))
#<Object #322, a generic object>
You must turn all of your object functions into generic functions. That is, every piece of
code of the form
(defobfun ( foo editable-text-dialog-item) arguments body)
must become
(defmethod foo ((item editable-text-dialog-item) rest-of-args )
body)
You can find a piece of code that performs most of this transformation for you in the
file defobfun-to-defmethod.lisp in your Examples folder.
Here is an example of old and new versions of code. Here is the old Object Lisp code.
? (defobfun (say fourth-grader) (sentence)
(princ "***")
(princ sentence)
(princ "***")
(terpri))
SAY
Here is the new CLOS code.
? (defmethod say ((child fourth-grader) sentence)
(princ "***")
(princ sentence)
(princ "!***")
(terpri))
SAY
Slot values and variables don’t access the same namespace, so you must bring all free
variable references into the slot namespace. In your version 1.3 code most of these free
variables should already be declared.
Again, you have a choice of ways of dealing with free variables. You can either
explicitly set them with slot-value or use accessor calls.
Accessors usually are preferable, since they allow you to change the representation of
your classes without changing any of the user code.
Here’s an example of old and new versions of code. First is the Old Object Lisp code.
? (setq school "Bronx Science")
"Bronx Science"
? school
"Bronx Science"
? (ask fourth-grader school)
"Bronx Science"
? (ask fourth-grader (have 'school))
NIL
? (ask fourth-grader (setq school "MIT"))
"MIT"
? school
"Bronx Science"
Instead of calling ask, you now useslot-value or an accessor for a value, or call a
method. Depending on the context, you should choose the appropriate thing to do.
Remember that you run methods on instances of a class. All calls must now be to
instances, not to class objects. An Object Lisp
ask for the object functionsay
()
? (ask billy-crystal (say "Marvelous"))
Rather than creating all new objects with oneof , you create instances withmake-instance .
Similarly, you replace kindof with defclass . But note that in CLOS, you cannot
make instances directly into classes. Instead you make new classes based on the class
you want to specialize and then create instances of those classes.
Note that if vpp-computer existed as a free variable in your version 1.3 code,
instances in CLOS will no longer find it. See the section “Replacing Free Variable
References” earlier in this appendix.
Numerous function names and other symbols have changed in both Common Lisp and
Macintosh Common Lisp. To investigate name changes, see this manual or use
Apropos on the Tools menu. Functions involving dialog items or windows are
frequently affected. Name changes are also documented in the fileold-dialog -
hooks.lisp in the MCL Examples folder.
The following code provides an extended example of conversion from Object Lisp to
CLOS. This code creates a new type of window, shape-window . A shape window has a
draw area and ashape-scroller area containing two buttons, marked Circles and
Squares. Clicking inside the draw area causes the shape window to draw a shape,
either a circle or a square. Changing which radio button is pushed causes all the
already drawn shapes to redraw themselves in the new selected shape.
The code also contains a new menu bar, which includes a menu that changes the color
of the shapes.
u Note: If you are not running Macintosh Common Lisp in a color window, the
shapes display as black.
In the following pages, Object Lisp code appears on the left pages and CLOS code on
the right. In these examples only the code is given; Macintosh Common Lisp’s
response does not appear.
The package syntax is the same as in Macintosh Common Lisp version 1.3. However,
you should check that the functionality you want is still in the same package. For
instance, older Common Lisp code uses the package name lisp, but Macintosh
Common Lisp version 2 usescommon-lisp , as required by the proposed new
standard.
When you defined objects in Object Lisp, you specified their properties using have
within defobfun . In CLOS you specify slot values withindefclass . You can
specify these values only if they can be initialized with initialization arguments or
initial value forms.
Here are some examples of turning Object Lispdefobfun calls into defmethod calls.
These functions define the behavior of the shape window and shape scroller.
(defmethod view-click-event-handler
((scroller shape-scroller) position)
(let ((my-window (view-container scroller)))
(setf (slot-value my-window 'shape-list)
(cons position (shape-list my-window)))
(view-draw-contents scroller)))
The following code defines a new menu bar and sets it to be the active menu bar. This
conversion is almost automatic. You only need to remove the call ask
to and replace
oneof with make-instance.
Again, the code for creating instances is simplymake-instance rather than oneof .
The corresponding CLOS code is the action performed by the New Shape Window
menu item.
(make-instance 'shape-window)
Note that you cannot create a subclass from an instance. You must define a new class
with defclass . See the section “Replacing oneof With make-instance and
kindof With defclass ” earlier in this appendix.
Contents
QuickDraw in Macintosh Common Lisp / 707
Windows, GrafPorts, and PortRects / 707
Points and rectangles / 708
Window state functions / 710
Pen and line-drawing routines / 712
Drawing text / 720
Calculations with rectangles / 721
Graphics operations on rectangles / 726
Graphics operations on ovals / 730
Graphics operations on rounded rectangles / 733
Graphics operations on arcs / 737
Regions / 741
Calculations with regions / 744
Graphics operations on regions / 748
Bitmaps / 749
Pictures / 751
Polygons / 753
Miscellaneous procedures / 757
705
This appendix assumes some familiarity with the various
discussions of QuickDraw in Inside Macintosh . You should also be
familiar with the “Points” section of Chapter 3, “Points and Fonts,”
and with the MCL implementation of records, described in Chapter
17, “Higher-Level Operating System Interface.”
Macintosh Common Lisp version 2 allows you to call QuickDraw traps directly (see
Chapter 17, “Higher-Level Operating System Interface”). The interface routines
support all of the functionality found in the original (64K ROM) Macintosh
packages.
The arguments to the MCL QuickDraw functions generally parallel the arguments to
the Pascal QuickDraw functions given inInside Macintosh . In several places Pascal
functionality has been extended by taking advantage of the optional arguments
provided by Macintosh Common Lisp. In some places the order of arguments has been
changed to make the mapping of the optional arguments more effective. Last var
arguments have sometimes been eliminated, and instead a value is returned.
Some QuickDraw functions may be performed only as methods on views. The view
must be a window or must be contained in a window. The functions depend on the
existence of a graphics port (GrafPort). All other functions may be performed
globally.
Before calling any of the functions described in this chapter, you must load the
QuickDraw file, which is in your MCL Library directory.
This process is simplified for the graphics routines given in this appendix.
n When you create a window, an initialized GrafPort is automatically created.
n Drawing commands are defined as methods on views, which must be windows or
contained in windows; when you call a method to perform one of the commands in
a window, GrafPorts are set and restored automatically with
with-focused -
view.
Drawing is also affected by the clip region (described later) and the PortRect. The
PortRectis an arbitrary rectangle designating the outermost bounds in which
drawing can occur. (See Figure E-2.) It supplies a frame of reference for the window.
The default PortRect is infinitely large; you can set it using low-level calls
(although you usually won’t need to worry about this at all).
Since all the drawing functions usewith-focused-view , you can speed up drawing
considerably if you wrapwith-focused-view around all calls to multiple drawing
functions.
Points are stored as encoded integers. Points lie at the intersection of two grid lines on
the QuickDraw plane. Note that points and pixels are not equivalent. The point
associated with a given pixel is at the upper-left corner of the pixel. (See Figure E-
1.)
See the “Points” section of Chapter 3, “Points and Fonts,” for a general description of
the MCL point data format.
For many of the MCL QuickDraw functions that use rectangles, you do not need to
allocate rectangle records explicitly at all. The rectangles can be specified as four
coordinates, or as two points, or as a rectangle record (see Figure E-2). In general, if
you use a rectangle only once, it is all right to pass it as two points or four coordinates.
However, if you use it several times, it is more efficient to create and pass an actual
rectangle record.
The following functions operate on the window containing the view asked to perform
a function.
Description The origin generic function returns the coordinates of the upper-left
point in the window’s content region. This is usually#@(0 0) but
may be different if it is set by user-written code.
Description The set-origin generic function sets the origin to the point
specified by h and v.
The contents of the window are not moved; only future drawing is
affected.
Example
Description The clip-region generic function returns the window’s current clip
region.
See the section “Regions” later in this appendix for functions that allocate and
manipulate regions.
Description The clip-rect generic function makes the window’s clip region a
rectangular region equivalent to the rectangle determined by arg. It
returns nil.
Every window has its own pen. The state of the pen determines how drawing occurs in
the window. For example, if the pen is hidden, drawing commands have no effect on
the screen. In addition to its state as hidden or shown, a pen has a size (height and
width), a position in the window, and a pattern used for drawing. (See Figure E-4.)
Description The pen-show generic function shows the pen. Drawing occurs only
when the pen is shown.
Description The pen-hide generic function hides the pen. If the pen is hidden,
no drawing occurs.
Description The pen-shown-p generic function returnst if the pen is shown and
nil if the pen is hidden.
Description The pen-size generic function returns the current pen size as a point
(expressing a width and height).
Description The set-pen-size generic function sets the pen size to the point
indicated by h and v. Figure E-5 shows QuickDraw pen sizes.
Description The pen-pattern generic function returns the window’s pen pattern.
A pattern is stored as a 64-bit block of memory (see Figure E-6). The definition of a
pattern record allows patterns to be accessed as 8 bytes or four words.
Pattern records, like all records, continue to take up space on the Macintosh heap
until they are explicitly disposed of.
(defrecord pattern
(variant ((b0 byte) (b1 byte) (b2 byte) (b3 byte)
(b4 byte) (b5 byte) (b6 byte) (b7 byte))
((w0 integer) (w1 integer)
(w2 integer) (w3 integer))))
Pen modes affect the way drawing occurs in the window. They provide a logical
mapping between the current state of pixels in the window and the state of the pixels
being drawn.
Description The set-pen-mode generic function sets the window’s current pen
mode. (See Figure E-7.)
Pen-state records represent the pen mode as an integer. This integer is equal to the
position of the corresponding pen-mode keyword in the list *pen-modes* . To
translate an integer into a keyword, make the call (elt *pen-state* mode-
integer ). To translate a keyword into an integer, make the call position
( mode-
keyword *pen-state* ).
Description The pen-state generic function returns the current pen state, a
record containing the pen’s location, size, mode (as an integer), and
pattern.
Description The set-pen-state generic function sets the window’s pen state.
Description The pen-normal generic function sets the pen size to#@(1 1) , the
pen mode topatCopy
: , and the pen pattern to*black-pattern* .
The pen location is not changed.
Description The move-to generic function moves the pen to the point specified by
h andv without doing any drawing. It returns the point to which the
pen moved.
Description The move generic function moves the penh points to the right andv
points down without doing any drawing.
Description The line-to generic function draws a line from the pen’s current
position to the point represented byh andv .
Drawing text
When a window is created, its pen position is #@(0 0) . This means that any text
drawn in it will be above the visible portion of the window until the pen position is
lowered.
The following functions do not draw; they simply perform calculations. They do not
depend on a GrafPort, and so they are defined globally rather than as generic
functions.
offset-rect [Function ]
intersect-rect [Function ]
union-rect [Function ]
point-in-rect-p [Function ]
points-to-rect [Function ]
equal-rect [Function ]
Description The equal-rect function returnst if rect1 andrect2 are equal and
nil otherwise.
Description The frame-rect generic function draws a line just inside the
boundaries of the rectangle specified byarg, using the current pen.
(See Figure E-13.)
Description The paint-rect generic function fills the rectangle specified byarg
with the current pen pattern and mode.
Description The erase-rect generic function fills the rectangle specified by arg
with the current background pattern (inpatCopy mode).
Description The invert-rect generic function inverts the pixels inside the
rectangle specified by arg . (See Figure E-14.)
Syntax fill-rect (view view) pattern left &optional top right bottom
Description The fill-rect generic function fills the rectangle specified by arg
with pattern (in :patCopy mode).
Ovals are drawn just inside rectangles. The oval is determined by the specified
rectangle. (See Figure E-15.)
Description The frame-oval generic function draws a line just inside the
boundaries of the oval specified by the rectangle, using the current
pen pattern, mode, and size. The rectangle is specified
by arg.
Description The paint-oval generic function fills the oval specified by the
rectangle specified by the arguments with the current pen pattern
and mode.
Description The erase-oval generic function fills the oval specified by the
rectangle with the current background pattern (in:patCopy mode).
The rectangle is specified by the arguments.
Description The invert-oval generic function inverts the pixels enclosed by the
oval specified by the rectangle. The rectangle is specified by the
arguments.
Syntax fill-oval (view view) pattern left &optional top right bottom
Description The fill-oval generic function fills the oval specified by the
rectangle with pattern (in :patCopy mode). The rectangle is
specified by the arguments.
A rounded rectangle (see Figure E-16) is a rectangle whose corners are rounded. The
shapes of the corners are determined by ovals associated with the rounded
rectangles. Thus, a rounded rectangle is determined by (1) the rectangle, (2) the
width of the oval, and (3) the height of the oval.
Description The frame-round-rect generic function draws a line just inside the
boundaries of the rounded rectangle, using the current pen pattern,
mode, and size. The rounded rectangle is specified by the rectangle,
oval-width, and oval-height .
Description The frame-arc generic function draws a line just inside the arc
specified by the rectangle, start-angle , and arc-angle using the
current pen pattern, mode, and size. The rectangle is specified by the
arguments. Figure E-17 shows an arc with a start angle of 45 and an
arc angle of 135 inside a rectangle with the coordinates#@(0 0) and
#@(150 100) .
Description The paint-arc generic function fills the arc specified by the
rectangle, start-angle, and arc-angle with the current pen pattern
and mode. The rectangle is specified by the arguments .
Description The erase-arc generic function fills the specified arc with the
current background pattern. The arc is specified by the rectangle,
start-angle , andarc-angle . The rectangle is specified byleft, top,
right, bottom.
Description The invert-arc generic function inverts the pixels enclosed by the
arc specified by the rectangle, start-angle , and arc-angle . The
rectangle is specified by left, top, right, bottom.
Description The fill-arc generic function draws a line just inside the arc
specified by the rectangle, start-angle , andarc-angle using the
current pen pattern, mode, and size. The rectangle is specified by
left,
top, right, bottom.
A region divides the graphics plane of points into two sets of points: those inside the
region and those outside the region. Regions can have any arbitrary shape. (See
Figure E-18.)
The storage for regions is not subject to automatic garbage collection. You must reclaim
region storage by calling the functiondispose-region . With this limitation, the
use of regions has been greatly simplified from the specification given inInside
Macintosh . Specifically, much of the initialization of regions is performed
automatically.
new-region [Function ]
Syntax new-region
Description The new-region function allocates a new empty region and returns it.
copy-region [Function ]
set-empty-region [Function ]
set-rect-region [Function ]
Description The open-region generic function hides the pen and begins
recording a region. Subsequent drawing commands to the window add
to the region. Recording ends whenclose-region is called. The
function returnsnil.
Description The close-region generic function shows the pen and returns a
region that is the accumulation of drawing commands in the window
since the last open-region for the window. It returns the result in
dest-region, if supplied, or else in a newly created region.
The following functions do not draw; they simply perform calculations. They do not
depend on a GrafPort, and so they are defined globally rather than as generic
functions.
offset-region [Function ]
inset-region [Function ]
union-region [Function ]
difference-region [Function ]
xor-region [Function ]
Description The xor-region function returns a region that consists of all the
points that are in region1 or region2, but not both. It returns the result
in dest-region , if supplied, or else in a newly created region.
point-in-region-p [Function ]
equal-region-p [Function ]
empty-region-p [Function ]
Description The frame-region generic function draws a line just inside the
boundaries ofregion , using the current pen.
Description The paint-region generic function fills region with the current pen
pattern and mode.
Description The erase-region generic function fills region with the current
background pattern, using:patCopy mode.
Description The fill-region generic function fills region with pattern , using
:patCopy mode.
Bitmaps
Bitmaps are rectangular arrays of pixels that are either black or white. The
following functions are useful in manipulating bitmaps.
make-bitmap [Function ]
Description The make-bitmap function returns a new bitmap the size of the
rectangle specified by the arguments. This bitmap is not displayed
anywhere but can be used for calculations and storage.
copy-bits [Function ]
Description The copy-bits function copies and scales the bits inside rect1 of
bitmap1 to the bits insiderect2 of bitmap2 using the transfer mode
pen-mode .
Description The scroll-rect generic function shifts the bitsh pixels to the
right and v pixels down withinrectangle , erases the uncovered
region, and adds the uncovered region to the window’s update region.
See Figure E-19 for an example of a scrolled rectangle.
Pictures
Description The start-picture generic function hides the pen and starts
recording QuickDraw commands in a picture whose frame is the
rectangle specified by the arguments, if supplied. Otherwise, the
window’s PortRect is the frame. The function returns nil.
Description The get-picture generic function shows the pen and returns a new
picture representing the cumulative effect of all the QuickDraw
commands given since the last call tostart–picture .
Note that if the PortRect was used as a frame when the picture was
made, and if the PortRect was arbitrarily large (the default set up
by Macintosh Common Lisp), then scaling will produce no drawing
(since the drawing frame is so much smaller than the creation
frame).
kill-picture [Function ]
Polygons
The MCL polygon commands are different from QuickDraw ones because Macintosh
Common Lisp handles some of the memory management automatically.
Description The start-polygon generic function hides the pen and starts
making a polygon. Subsequentline andline-to commands are
added to a new polygon.
Description The get-polygon generic function shows the pen and returns a
polygon representing the cumulative effect of all the line and
line-to commands since the last call tostart–polygon .
kill-polygon [Function ]
Description The frame-polygon generic function draws a line just inside the
boundaries ofpolygon using the current pen. A framed polygon is
shown in Figure E-20.
Description The paint-polygon generic function fills polygon with the current
pen pattern and mode.
Description The erase-polygon generic function fills polygon with the current
background pattern, using:patCopy mode.
Description The fill-polygon generic function fills polygon with pattern using
:patCopy mode.
Miscellaneous procedures
This section contains functions to perform miscellaneous graphics procedures.
scale-point [Function ]
map-point [Function ]
map-polygon [Function ]
Contents
The single most valuable source / 764
If you are learning Lisp / 764
If you are learning CLOS / 765
If you’re learning about Macintosh programming / 766
If you’re updating from a previous version of Macintosh
Common Lisp / 766
If you’d like examples of MCL programming / 765
If you’d like to communicate with other MCL programmers / 767
Communicating through Internet / 767
Communicating through Usenet / 767
Communicating through AppleLink / 768
Communicating through CompuServe / 768
Communicating through other services / 768
Bugs and bug fixes / 768
Infrequent announcements of general interest / 769
If you’re a developer: APDA / 769
763
The single most valuable source
At least until the release of the draft ANSI specification, Common Lisp: The
Language is the standard reference manual and language specification for CLOS, as
well as the most up-to-date specification for all of Common Lisp. It is not a tutorial,
but is a must for every Lisp user.
Steele, Guy L., and others.Common Lisp: The Language. Second edition. Maynard,
MA: Digital Press, 1990.
Many good tutorials exist on Common Lisp. Here is a selection of the best.
Koschmann, Timothy.The Common Lisp Companion . New York: John Wiley, 1990.
This well-written book includes material from the second edition ofCommon
Lisp: The Language , including information on CLOS. The author is on the ANSI
XJ313 standards committee for Common Lisp.
Miller, Molly M., and Eric Benson.Lisp Style and Design. Maynard, MA: Digital
Press, 1990.
An excellent book for all levels of Common Lisp programming, with many
examples. Source code for this book is available.
Touretzky writes well and includes many good examples for novices.
Winston, Patrick, and Berthold Claus Paul Horn.Lisp. Third edition. New York:
Harper & Row, 1989.
Finally, though it uses Scheme instead of Lisp, the following is possibly the best
book ever written on computer programming. With a relatively small knowledge of
Lisp, you can follow it:
Because CLOS is such a new standard, it is integrated into relatively few tutorials.
Sonya Keene’s book, below, is generally reckoned to be the most thorough CLOS
tutorial on the market. Keene was also a contributor to the second edition Common
of
Lisp: The Language .
Lawless, Jo A., and Molly M. Miller.Understanding CLOS: The Common Lisp Object
System. Maynard, MA: Digital Press, 1991 .
The books by Winston and Horn, Norvig, and Koschmann, described in the previous
section, also include material on CLOS.
The following book describes current thinking about the Metaobject Protocol.
Kiczales, Gregor, and others.The Art of the Metaobject Protocol . Cambridge, MA:
MIT Press, 1991.
If you want to know more about programming the Macintosh, Apple Developer
University offers excellent self-paced courses for novice and intermediate Macintosh
programmers, including courses on Macintosh Programming Fundamentals and
Introduction to Object-Oriented Programming. “Live” courses on other subjects are also
offered through Developer University.
Depending on the development work you are doing, you may not need toInside
use
Macintosh as a reference. However,Inside Macintosh is indispensable for
programming all low-level Macintosh features.
If you’re not familiar with the Common Lisp Object System, read Appendix C, “The
Common Lisp Object System.” Appendix D, “Converting Your Files to CLOS,” is a
guide to converting your code to the new object standard. (The experience of early
MCL users is that converting code is not nearly so daunting as thinking about it.)
The Examples and Library folders of Macintosh Common Lisp provides examples of
MCL programming. Other examples and continuing discussions of Macintosh Common
Lisp and Lisp programming issues take place through the MCL online discussion
group,info-mcl . Third-party code for other MCL tools and extensions is also stored
oninfo-mcl and can be downloaded. See the next section.
Apple supports MCL developers through an Internet discussion group and Usenet
group,info-mcl . The info-mcl mailing list posts specific technical questions and
their answers and provides a forum in which MCL developers can communicate with
each other. It also provides an archive and a library of extensions, third-party code,
and patches, which are available for downloading through anonymous FTP. Many
programmers find this an extremely valuable feature of Macintosh Common Lisp.
Some other communications services have links with Internet, and more are being
developed. Please check with the Customer Services group at your preferred
communications service.
If you find a bug in Macintosh Common Lisp, you can report it through the mailing
list bug-mcl , reachable in the same way asinfo-mcl . This list is one-way. Fixes of
general interest are distributed through info-mcl . Apple reserves the right to
redistribute any sample code or bug fixes that are sent to
bug-mcl.
If you’re a developer—APDA
APDA, Apple’s source for developer tools, offers convenient worldwide access to over
three hundred development tools, resources, and training products and to information
for anyone interested in developing applications on Apple platforms. Customers
receive a quarterly APDA Tools Catalog featuring the most current versions of Apple
development tools and the most popular third-party development tools. Ordering is
easy; there are no membership fees, and application forms are not required for most
of our products. APDA offers convenient payment and shipping options, including site
licensing.
APDA
Apple Computer, Inc.
20525 Mariani Avenue, M/S 33-G
Cupertino, CA 95014-6299 USA
771
*background-event-ticks* variable *green-color* variable 269
397, 398 *help-output* variable 43, 346
*background-sleep-ticks* variable *i-beam-cursor* variable 179, 405
397 *idle-sleep-ticks* variable 396
*backtrace-on-break* variable 22, 355 *idle* variable 394
*black-color* variable 269 defined 396
*black-pattern* variable 83 using 655
*black-rgb* variable 269 *inspector-disassembly* variable 371
*blue-color* variable 269 *killed-strings* variable 33
*break-on-errors* variable 22, 354 *last-command* variable 496, 510, 511
*break-on-warnings* variable 22, 354 *light-blue-color* variable 269
*brown-color* variable 269 *light-gray-color* variable 269
*check-call-next-method-with-args* *light-gray-pattern* variable 83
variable 619, 620 *lisp-cleanup-functions* variable 651
*clear-mini-buffer* variable 36, 502 *.lisp-pathname* variable 308
*color-available* variable 263 *lisp-startup-functions* variable 652
*compile-definitions* variable 358, *listener-comtab* variable 512
637 *listener-default-font-spec*
*comtab* variable 470, 507, 512 variable 5, 167
*control-x-comtab* variable 512 *listener-history-length* variable
*current-character* variable 507, 511 471
*current-event* variable 377, 394, 395 *listener-window-position* variable 5
*current-keystroke* variable 379, 511 *listener-window-size* variable 6
*current-view* variable 129 *loading-file-source-file* variable
*cursorhook* variable 129, 402, 404, 405 645
*dark-gray-color* variable 269 *load-verbose* variable 22
*dark-gray-pattern* variable 83 *logical-directory-alist* variable
*dark-green-color* variable 269 330, 331
*default-menubar* variable 90 *logical-pathname-alist* obsolete
*default-pathname-defaults* variable variable. See *logical-directory-
315 alist*
*emacs-mode* variable 22, 36, 39 *make-package-use-defaults* variable
*eventhook* variable 394, 396 628
*fasl-save-definitions* variable 336 *menubar-bottom* variable 84
*fasl-save-doc-strings* variable 336 *menubar-frozen* variable 104
*fasl-save-local-symbols* variable *menu-id-object-alist* variable 104
22, 43, 336, 338 *menubar* variable 89
*features* variable (Common Lisp) 370 *mini-buffer-font-spec* variable 36
*font-list* variable 82 *mini-buffer-help-output* variable
*foreground-event-ticks* variable 43, 338
397, 398 *modal-dialog-on-top* variable 259
*foreground-sleep-ticks* variable 397 *module-file-alist* variable 309
*fred-default-font-spec* variable 36, *module-search-path* variable 309
167 *modules* variable 310
*fred-history-length* variable 471 *mouse-view* variable 129
*fred-keystroke-hook* variable 510 *multi-click-count* variable 46
*fred-special-indent-alist* variable *next-screen-context-lines* variable
483 38, 44, 45
*gray-color* variable 269 defined 37
*gray-pattern* variable 83 *open-file-streams* variable 324
Index 773
buffer-current-sexp-bounds function buffer-substring-p function 461
459 buffer-upcase-region function 459
buffer-current-sexp function 457 buffer-word-bounds function 462
buffer-current-sexp-start function 458 buffer-write-file function 464
buffer-delete function 459 built-in-class class 607
buffer-downcase-region function 459 button-dialog-item class 190, 206
buffer-fwd-sexp function 462 button dialog items, creating instances 206
buffer-getprop function 451 buttons 206–207, 208
buffer-get-style function 467 default 207, 208, 209
buffer-insert-file function 463, 465 radio 218–221
buffer-insert function 456
buffer-insert-substring function 456 C
buffer-insert-with-style function 457 caches 618–619
buffer-line-end function 454 call-next-method function 619, 620, 670
buffer-line function 453 Cancel button 258
buffer-line-start function 453 cancel function 349
buffer-mark class 446, 447 cancel-text keyword 251
buffer-mark-p function 189, 447 caps-lock-key-p function 393
buffer marks catch-abort. See restart-case
definition 443, 446 catch-cancel macro 249
MCL expressions relating to 447–469 catch-error. See handler-case
buffer-modcnt function 450 catch-error-quietly. See ignore-
buffer-next-font-change function 468 errors function
buffer-not-char-pos function 460 Caution icon 250
buffer-plist function 451 ccl::*name-char-alist* variable 626
buffer-position function 452 ccl::compile-time-class class 607
buffer-previous-font-change ccl::std-class class 607
function 468 cell-contents generic function 225
buffer-putprop function 452 cell-deselect generic function 231
buffer-remove-unused-fonts function cell-font generic function 229
465, 467 cell-position generic function 233
buffer-replace-font. See buffer- cell-selected-p generic function 231
replace-font-spec function cell-select generic function 231
buffer-replace-font-codes function 469 cell-size generic function 229
buffer-replace-font-spec function 189, cell-to-index generic function 245
466 change-key-handler generic function 383
buffers 443–445 characters 626
definition 443, 445 capitalize 51
evaluate 17 literal 50
select, in Fred 47 lowercase 50
buffer-set-font. See buffer-set-font- outputting from stream 428
spec function quoted 50
buffer-set-font-codes function 469 read from stream 429
buffer-set-font-spec function 189, 466 unread from stream 430
buffer-set-style function 468 uppercase 50
buffer-size function 450 check-box-checked-p generic function 217
buffer-skip-fwd-wsp&comments function check-box-check generic function 218
189, 463 check-box-dialog-item class 190, 216
buffer-string-pos function 461
buffer-substring function 456
Index 775
:color-p keyword 155, 189, 473 :fork keyword 322
:command-key keyword 107, 117 :frame keyword 170, 192, 199, 275, 477
:comtab keyword 470, 474, 477 :full-long keyword 526
:condense keyword 69 :handle keyword 576
:content keyword 170, 275 :help-spec keyword 94, 107, 118, 127, 129,
:copy-styles-p keyword 471, 473, 477 192, 236, 238, 251, 474
:cstring keyword 524 :hilite keyword 170, 275
:D0 keyword 599 :history-length keyword 471, 474
:D0–D7 keyword 527, 529, 530, 602, 603 :host keyword 303
:default-button keyword 207 :if-does-not-exist keyword 318
:default-item keyword 235 :if-exists keyword 319, 321, 322
:default-menu-background keyword 92, :include-invisibles keyword 157, 158,
274 159
:default-menu-item-title keyword 92, :include-windoids keyword 157, 158, 159
101, 274 :inhibit-event-polling keyword 641
:default-menu-title keyword 92, 274 :inhibit-register-allocation
:defaults keyword 305 keyword 640
:device keyword 303 :inhibit-safety-checking keyword 641
:dialog item-colors 189. See also :initial-string keyword 252
:part-color-list keyword :inline-self-calls keyword 641
:dialog-item-action keyword 192, 194, :italic keyword 69
236 :item-display keyword 235
:dialog-item-enabled-p keyword 192, :item-key keyword 114, 275
477 :item-mark keyword 114, 275
:dialog-item-handle keyword 192 :item-title keyword 114, 275
:dialog-item-text keyword 192, 211, :language keyword 522
235, 477 :left keyword 162
:direction keyword 237, 427 :libraries keyword 519
:directories keyword 314 :library-entry-names keyword 519
:directory keyword 303, 328, 329 :lisp-ref keyword 524
:directory-pathnames keyword 314 :long keyword 523, 526, 529, 530, 598, 599,
:disabled keyword 107, 118 602, 603
:document keyword 155, 473 :mac-file-creator keyword 319
:document-with-grow keyword 155, 473 :mac-file-type keyword 319, 328
:document-with-zoom keyword 155, 473 :max keyword 237
:do-it keyword 367 :menu-background keyword 101, 274
:double-edge-box keyword 155, 473 :menubar keyword 92, 274
:double keyword 523, 526 :menu-colors keyword 94, 235
:draw-outline keyword 477 :menu-item-action keyword 107, 118
:entry-names keyword 519 :menu-item-checked keyword 107, 118
:erase-anonymous-invalidations :menu-item-colors keyword 107, 118
keyword 139, 156 :menu-items keyword 94, 235
:extended keyword 523 :menu-item-title keyword 106, 117
:extend keyword 69 :menu-title keyword 94, 101, 274
:ffenv-name keyword 520 :method keyword 360, 363, 366, 368
:filename keyword 472, 489 :min keyword 237
:files keyword 314 :modeless keyword 252, 254, 255
:float keyword 526 :name keyword 304
:font keyword 449 :no-check-arg keyword 526
:force-boundp-checks keyword 642 :no-error keyword 315
Index 777
color-red function 264 compute-applicable-methods generic
colors 261, 262–276 function 619
blue 265 comtab 507, 512
Color Picker 262, 268 definition 505
Color QuickDraw 263 shadowing 507
component values 265 comtab-find-keys function 515
dialog items 275 comtab-get-key function 514
display as same color 265 comtab-key-documentation function 515
encoding 262 comtab-set-key function 513
green 264 comtabp function 513
implementation 261 configure-egc function 634
menu bars 91, 274 container 132
menu items 275 definition of 123
menus 274 context lines 37
red 264 continue 18
returning encoded color 263 continue function 354
RGB records 266, 267, 269 Continue menu item 18
values 265 Control-A keystroke 44
windows 270–272, 275 Control-B keystroke 44
color-to-rgb function 266 Control-D keystroke 52
color-values function 264, 265 Control-E keystroke 44
Color Window 290 Control–equal sign keystroke 42, 339
color-window-mixin. See :color-p Control-F keystroke 44
keyword Control-G keystroke 4, 60
command-key generic function 110 Control key 39
command-key-p function 393 control-key-p function 393
command keystrokes 9 Control-K keystroke 52
Command-Meta-click 43 Control–Left Arrow keystroke 44
command tables 504 Control-Meta-A keystroke 44
definition 505 Control-Meta-B keystroke 44
Common Lisp Object System (CLOS) 658–684 Control-Meta–close parenthesis keystroke 45
COMMON LISP: THE LANGUAGE 659 Control-Meta-Delete keystroke 52
compatibility Control-Meta-E keystroke 44
implementation of file system in MCL Control-Meta-F keystroke 44
version 2 297 Control-Meta-H keystroke 47
MCL version 2 and CLOS xxii Control-Meta-K keystroke 52
between MCL version 2 and earlier Control-Meta-L keystroke 56
versions 628, 659 Control-Meta-N keystroke 4, 45
MCL version 2 and Metaobject Protocol Control-Meta-number keystroke 57
xxii Control-Meta-O keystroke 49
updating from previous versions 766 Control-Meta–open parenthesis keystroke 45
compilation 7, 10, 638–643 Control-Meta-P keystroke 45
compiler policy objects 638 Control-Meta-Q keystroke 49
eliminating tail recursion 638 Control-Meta-semicolon keystroke 53, 55
options 335–337 Control-Meta-Shift–Down Arrow keystroke
self-referential calls 638 48
compiled file (.FASL file) 10 Control-Meta-Shift-M keystroke 54
Compile File menu item 17 Control-Meta-Shift-N keystroke 48
compiler-policy class 639 Control-Meta-Shift-P keystroke 48
compiler policy objects 638 Control-Meta–Shift–Up Arrow keystroke 48
Index 779
cut generic function 16, 116, 181, 216, 372, dialog-item-action generic function 194
494 check-box-dialog-item 217
Cut menu item 16 dialog-item class 191
dialog-item-dialog. See view-
D container generic function
dead keys, in Fred 40 dialog-item-disable generic function 201
debugging 333–373 dialog-item-enabled-p generic function
MCL functions related to 340 201
declaration-information function 640 dialog-item-enable generic function 200
debugging commands in Fred 337–340 dialog-item-font. See view-font generic
default-button-dialog-item class 208 function
default-button dialog items 208 dialog-item-handle generic function 203
default-button generic function 208 dialog-item-nick-name. See view-
default-button-p generic function 209 nick-name generic function
default buttons 207–209 dialog-item-position. See view-
default values (initforms) 663 position generic function
defccallable macro 560 dialog items 190–259
deffcfun macro 521 activate event handler 203
defffun macro 521 add 290
deffpfun macro 521 add to window 202
def-fred-comtab macro 504 Alert icons 250
defgeneric macro 668 associated function 194, 195
definitions, editing 9 button 206
definitions, listing 19 Caution icon 250
def-load-pointers macro 652 checkboxes 216–218
def-logical-directory function 331 color of parts 199
def-logical-pathname (obsolete function) color of parts, returning 200
331 color of parts, setting 200
defpascal macro 560 colors 275
defmethod macro 668 creating instances 191
defrecord macro 576 deactivate event handler 204
defstruct macro 645 default button 208, 209
deftrap macro 569 default size 204
deinstall-appleevent-handler function default width correction 205
418 definition 186, 190
delete 496 disable 201
delete-file function 318 editable-text 210–216
Delete keystroke 52, 60 enable 200
deletion 52 enabled, checking if 201
descent 73, 76 event handling 195
Design Dialogs menu item 288 find 259
dialog boxes 187, 289 find named sibling 135
Document-with-Grow 289 find named subview 135
dialog class 256 focused 205
dialog item-default-size. See view- focus on container and draw contents 196
default-size generic function font 198
dialog-item-action-function generic font codes 77
function 195 font codes set 78
font setting 198
font specifiers 198
Index 781
ed-backward-select-sexp generic ed-get-documentation generic function
function 46 43, 339
ed-backward-select-word generic ed-help function 42, 338
function 46 ed-history-undo generic function 56
ed-backward-sexp generic function 44 ed-indent-comment generic function 55
ed-backward-word generic function 44 ed-indent-differently generic function
ed-beep function 493 45
ed-beginning-of-buffer generic function ed-indent-for-lisp generic function 49
45 ed-indent-sexp generic function 49
ed-beginning-of-line generic function 44 ed-insert-char generic function 481
ed-bwd-up-list generic function 45 ed-insert-double-quotes generic
ed-capitalize-word generic function 51 function 50
ed-copy-region-as-kill generic function ed-insert-sharp-comment generic
53 function 50
ed-current-sexp generic function 484 ed-insert-with-style generic function
ed-current-symbol generic function 483 482
ed-delete-char generic function 52 ed-inspect-current-sexp generic
ed-delete-forward-whitespace generic function 43, 339
function 53 ed-i-search-forward generic function 60
ed-delete-horizontal-whitespace ed-i-search-reverse generic function 60
generic function 53 editable-text-dialog-item class 190,
ed-delete-whitespace generic function 53 210
ed-delete-with-undo generic function editable-text dialog items 210–216, 445
497, 498 creating instances 211
ed-delete-word generic function 52 edit-definition function 356
ed-downcase-word generic function 50 Edit Definition menu item 18
ed-edit-definition generic function 42, edit-definition-p function 344
338 Edit Dialog menu item 288
ed-end-of-buffer generic function 45 editing definition of source code 18
ed-end-of-line generic function 44 Edit menu 16
ed-end-top-level-sexp generic function Edit Menubar menu item 287
44 editor 7–8
ed-eval-current-sexp generic function 54 evaluating from 10
ed-eval-or-compile-current-sexp format to use with other editors 9
generic function 54 edit-select-file generic function 56
ed-eval-or-compile-top-level-sexp ed-kill-backward-sexp generic function
generic function 54 52
ed-exchange-point-and-mark generic ed-kill-comment generic function 53, 55
function 48, 51 ed-kill-forward-sexp generic function 52
ed-forward-char generic function 44 ed-kill-line generic function 52
ed-forward-select-char generic function ed-kill-region generic function 53
46 ed-kill-selection generic function 501
ed-forward-select-sexp generic function ed-last-buffer generic function 56
47 ed-macroexpand-current-sexp generic
ed-forward-select-word generic function function 54
46 ed-macroexpand-1-current-sexp
ed-forward-sexp generic function 44 generic function 54
ed-forward-word generic function 44 ed-move-over-close-and-reindent
ed-fwd-up-list generic function 45 generic function 45
Index 783
event ticks 396, 397, 398 examples of code (continued)
event-dispatch function 388, 394, 655 Foreign Function Interface 533
event handler 394 and C language 533
activate view 380 testing 533
click in view 377, 387 help balloons 127
deactivate view 380 icons 190
disable event processing during execution input/output stream 426
of forms 401 interface building 277
mouse 403 interface programming 705
mouse button up 385 logical pathnames, setting 520
null event 384 MCL class hierarchy 621
queue form for evaluation 399, 656 menu-item-update methods 119
release key 384 menus 87
release mouse button 385 Meta key rebound to Escape 7
update window 388 pop-up menus 234
view activate 380 QuickDraw 705
view deactivate 380 stack allocation 543
window 398 using class-direct-subclasses 609
window key up 384 using invalidate-view 139
window no event 384 using set-view-font 168
window select 384 using view-click-event-handler 149
window update 388 using view-draw-contents 390
window zoom 386 where to find 767
event-keystroke function 508 windoid event handling 183
events 376–410 execution stack 349
idling 655 exit 15
interrupts 655 exit-key-handler generic function 213
queued 655 expand-logical-namestring (obsolete
response time 655 function) 315
time-consuming events 655 expressions
event-ticks function 388, 397 current, definition 41
examples of code xxiii, 30, 33, 40, 41, 214, evaluating from editor 6
223 inspecting 43, 339
Apple Events 423 macroexpanding 339
application programming 277 macroexpanding repeatedly 339
Boyer-Moore search algorithm 61 reading 339
calling traps 570 extended keyboard keys 41
CLOS 658–684 extended wildcards 317
CLOS conversion 685–704 extensions
:pict scrap handler 408 .fasl (compiled file) 10
communicating with HyperCard 423 .lisp (source file) 10
defining a scrap handler 406 .text (non-Lisp text file) 10
defrecord macro 577 externalize-scrap generic function 409,
dialog boxes with Alert icons 250 410
dialog functions, obsolete 188
dialog items 187, 201 F
dialog items, implementing custom class fact 361
246 failing i-search prompt 58
ephemeral garbage collector 632 fasl file (compiled file) 10
font menus 7, 120
Index 785
frame-round-rect generic function 733 Fred commands
fred-mixin class 680 add mode line 54
Fred 7 capitalize word 51
Apple Extended Keyboard keys 41 comment column, set 55
background color 487 comment insert or align 55
chunk size 478 copy current region 53
Clipboard 33 current editor window 42, 339
context lines 37 defining 504
dead keys 40 delete 52, 53
debugging commands 337–340 character left 52
default font 36 character right 52
deleting 52 current region 53
editing, implementation of 443 horizontal white space 53
Emacs mode 22, 36 s-expression left 52
Escape key as Meta modifier 40 s-expression right 52
evaluating from 10 to end of current line 52
evaluation 6, 8 to next non-white-space character 53
font, setting 33 white space 53
fonts 33, 464 word left 52
foreground color 488 word right 52
format to use with other editors 9 documentation of function 43, 339
Fred Commands menu item 19 evaluate current s-expression 54
Fred dialog items 445 evaluate or compile current sexp 54
Fred windows 443, 444 evaluate or compile top-level s-expression
horizontal scroll 486 54
horizontal scroll, set 486 examine code definition for symbol 42
insertion font behavior 33 files 56
kill ring 33 function documentation 339
line wrap checking 491 help 19, 42
Lisp operations 54 help commands 42–43
Macintosh editing features 7, 38 Help window 338
margin return 490 incremental search 57–61
margin set 491 commands 60–61
Meta and Control modifiers 7 insert 49–51
multiple fonts 33 current kill ring string into buffer 49
programming 441 double quotation mark 50
set package of windows 34–35 line 49
setting a font 33 next kill ring string into buffer 49
spaces per tab return 491 parentheses 50
styles, retaining 37 quoted character 50
using Macintosh Option character set 40 sharp-sign comment 50
window information, saving 37 inspect current s-expression 43, 339
windows 124 kill comment 53, 55
yank, rotating 49 Lisp operations 54–55
fred-blink-position generic function lowercase word 50
480 macroexpand current s-expression 54, 339
fred-buffer function 189 macroexpand current s-expression
fred-buffer generic function 450, 478 repeatedly 339
fred-chunk-size generic function 449, 478
Index 787
gc-event-check-enabled-p function 636 have (obsolete ObjectLISP function),
gccounts function 635 equivalent 664
gc function 13, 636 Help
gctime function 635 Fred 42, 338
generation, definition 632 Fred commands 19
generic-function class 607 Listener commands 19
generic-function-methods generic help features xxiii
function 615 Help keystroke 369
generic functions 661–662 help-spec generic function 101
associated with a method 615 hfs device 326
defining new 668 hfs-volume-p function 326
definition 661, 667 hget-signed-long function 547
method exists, checking 619 hierarchy 621
methods 615 highlight-table-cell generic function
methods that run when a generic function 227
is invoked 615 Horn, Berthold C. P. 765
on given specializer 614 href macro 584, 587
get-back-color generic function 487 HyperCard, communicating with 423
get-dead-keys (obsolete MCL function) 41
get-fore-color generic function 488 I
get-internal-scrap generic function 406, ignore (Common Lisp declaration) 643
409 ignore-if-unused declaration 643
get-next-event function 394 ignore-errors function 189
get-next-queued-form function 656 immediate objects 621
get-picture generic function 752 implementation 605–645
get-pixel generic function 758 Include Close Box attribute 290
get-polygon generic function 754 incremental compilation 7
get-record-field function 592 incremental search 57
get-scrap function 406, 409 commands 60–61
get-string-from-user function 252 index-to-cell generic function 245
global point initargs 663
from local point 757 initforms 663
to local point 757 initialize-instance generic function
global-to-local generic function 757 button-dialog-item 206
global variables 19 check-box-dialog-item 217
gorilla 676 default-button-dialog-item 208
grafport-font-codes function 79 dialog-item 191
GrafPort origin 145 editable-text-dialog-item 211
GrafPorts 707 fred-dialog-item 475
grafport-write-string macro 72 fred-window 472
graphics 707 input-stream 427
menu 94
H
menu-item 106
handle output-stream 427
dialog item 192 pop-up-menu 235
locked, checking 594 radio-button-dialog-item 219
handle-locked-p function 594 scroll-bar-dialog-item 236
handlep function 556 sequence-dialog-item 243
handler-case 189 simple-view 127
Index 789
K keyboard equivalents (continued)
Keene, Sonya E. 765 Control-S Control-Y 60
keyboard equivalents Control-Shift-A 47
Command-Meta-click 43 Control-Shift-E 47
Command-Option-click 42 Control-Shift–Left Arrow 46
Control-A 44 Control-Shift-N 47
Control-B 44 Control-Shift-P 47
Control-E 44 Control-Shift–Right Arrow 47
Control-equal sign 42, 339 Control-Shift-V 48
Control-F 44 Control-S Meta-W 60
Control-G 60 Control–Space bar 51
Control-K 52 Control-T 51
Control–Left Arrow 44 Control-Tab 45
Control-M 54 Control-U 57
Control-Meta-A 44 Control-underscore 56
Control-Meta-B 44 Control-V 45
Control-Meta-Delete 52 Control-W 49, 53, 60
Control-Meta-E 44 Control-X Control-A 43, 338
Control-Meta-F 44 Control-X Control-C 54
Control-Meta-H 47 Control-X Control-D 43, 339
Control-Meta-K 52 Control-X Control-E 54
Control-Meta-L 56 Control-X Control-F. See Control-X
Control-Meta-N 45 Control-V keystroke
Control-Meta-number 57 Control-X Control-I 369
Control-Meta-O 49 Control-X Control-M 54
Control-Meta-P 45 Control-X Control-R 54
Control-Meta-Q 49 Control-X Control-S 56
Control-Meta-semicolon 53, 55 Control-X Control-V 56
Control-Meta-Shift–Down Arrow 48 Control-X Control-W 56
Control-Meta-Shift-M 54 Control-X Control-X 48, 51
Control-Meta-Shift-N 48 Control-X H 47
Control-Meta-Shift-P 48 Control-X semicolon 55
Control-Meta-T 51 Control-X U 56
Control-Meta-underscore 56 Control-Y 49, 60
Control-Meta–close parenthesis 45 defining 504
Control-Meta–open parenthesis 45 Delete 52, 60
Control-Meta–Shift–Up Arrow 48 Enter 54
Control-Meta–Space bar 47 Help 369
Control-N 44 Left Arrow 44
Control-number 57 Meta-B 44
Control-O 49 Meta-backslash 53
Control-P 44 Meta-C 51
Control-Q 50, 60 Meta–close parenthesis 45
Control–question mark 42, 338 Meta-D 52
Control-R 60 Meta-Delete 52
Control-Return 49 Meta–double quotation mark 50
Control-Right Arrow 44 Meta-F 44
Control-S 60 Meta–greater than 45
Control-S Control-W 60 Meta-L 50
Meta–left angle bracket 45
Index 791
Macintosh Common Lisp (continued) map
information about 763–769 point 759
install xxxii polygon 761
menu bar commands 13–20 rectangle 760
programming procedure 9–11 region 761
quit xxxii map-point function 759
start xxxii map-polygon function 761
syntax xxix–xxxi map-rect function 760
Macintosh data structures 537 map-region function 761
Macintosh editing features 38 map-subviews generic function 134
Macintosh Operating System 122, 537, 539 map-windows function 159
MCL functions for strings, pointers, and mark-backward-p function 448
handles 554–558 markp. See buffer-mark-p function
Macintosh Programmer’s Workshop maybe-default-stream-reader macro
interfaces 537 433
Macintosh Programmer’s Workshop, maybe-default-stream-writer macro
communicating with 423 432
Macintosh Toolbox 537 MCL menu items
calling Macintosh Common Lisp 532 apropos 18
mac-namestring function 312 cancel current operation 17
macptrs 538, 539 close current window 15
macptrp function 555 compile file 17
macro dispatch characters, inspect 370 continue current operation 18
macroexpand function 339 copy text 16
macroexpanding current s-expression 339 cut text 16
macroexpanding current s-expressions delete text 16
repeatedly 339 documentation 18
macroexpand-1 function 339 edit definition 18
mactype, definition (a record field type) 566 environment options 19
make-bitmap function 749 evaluate selection 17
make-buffer function 449 evaluate window contents 17
make-color function 263 exit 15
make-comtab function 512 find source code 18
make-dialog-item function 193 help on Fred 19
make-instance generic function 664 help on Listener 19
menu 94 list definitions 19
menu-item 106 load file 17
simple-view 127 open file 15
view 128 open selected file 15
vs. initialize-instance 672 page setup 15
window 153 paste text 16
window-menu-item 117 print 15
make-mark function 447 print options 15, 19
make-pathname function 303 quit 15
make-point function 67 restart current operation 18
make-record function 542 revert window contents to last saved
make-record macro 583 version of file 15
save copy of Listener contents as named
file 15
save window contents to file 15
Index 793
menu-item-update-function generic Meta-G keystroke 4
function 113 Meta–greater than keystroke 45
menu-item-update generic function 113, Meta key 39
119 Meta–left angle bracket keystroke 45
menus 85, 120. See also menu items, window Meta-Left Arrow keystroke 44
menu items Meta–left parenthesis keystroke 50
advanced menu features 103–105 Meta–less than keystroke 45
Balloon Help 101 Meta-L keystroke 50
colors 88, 101, 102 Meta-M keystroke 45
creating instances 94 Meta modifier 39
definition 93 Meta-number keystroke 57
deinstalling 96 Meta–number sign keystroke 50
dimming 97 metaobject class 606
disabling 97 Metaobject Protocol xxii, 606–621
enabled, checking if 97 introspective MOP functions 608
enabling 97 MCL functions related to 608–621
File 15 metaobject classes 606–608
font style 98 Meta–open parenthesis keystroke 50
freezing menu bar 104 Meta-period keystroke 42, 338
handle to menu record 103 Meta-quotation mark keystroke 50
hierarchical 87 Meta–right angle bracket keystroke 45
identification number association list 104 Meta–Right Arrow keystroke 44
installation, checking for 96 Meta-semicolon keystroke 55
installing 96 Meta–sharp sign keystroke 50
MCL forms relating to menu elements 98– Meta-Shift–Left Arrow keystroke 46
102 Meta-Shift–Right Arrow keystroke 46
MCL forms relating to menus 93 Meta-Shift-V keystroke 48
removing from menu bar 96 Meta–Space bar keystroke 53
restoring 97 Meta-T keystroke 51
retitling 95 Meta-U keystroke 50
title 95, 437 Meta-V keystroke 44
turning off 97 Meta-W keystroke 49, 53
turning on 97 Meta-Y keystroke 49
unique numeric identification 104 method class 606
update function 98 method-combination class 606
updating 103, 119 method-exists-p function 619
Windows 20 method-function generic function 615
menu-style generic function 98 method-generic-function generic
menu-title generic function 95, 437 function 615
menu-update generic function 103, 119 method-name generic function 616
menu-update-function generic function 98 method qualifiers 678
merge-font-codes function 80 method-qualifiers generic function 616
message-dialog function 249 methods 661–662
Meta-B keystroke 44 accessor 671
Meta-backslash keystroke 53 auxiliary 678
Meta-C keystroke 51 congruent lambda lists 669
Meta–close parenthesis keystroke 45 defining new methods 668
Meta-Delete keystroke 52 definition 662
Meta-D keystroke 52 for a generic function 615
Meta–double quotation mark keystroke 50
Index 795
parentheses, inserting 50 %get-cstring function 549
part-color generic function 272 %get-long function 547
dialog-item 199 %get-ostype function 549
menu 101 %get-ptr function 548
menubar 91 %get-signed-byte function 544
menu-item 114 %get-signed-long function 547
table-dialog-item 230 %get-signed-word function 545
window 170 %get-string function 549
part-color-list generic function 273 %get-unsigned-byte function 544
dialog-item 200 %get-unsigned-long function 547
menu 102 %get-unsigned-word function 546
menubar 93 %get-word function 546
menu-item 115 %hget-byte function 545
window 171 %hget-long function 547
Pascal language %hget-ptr function 548
calling Macintosh Common Lisp 532 %hget-signed-byte function 545
calling sequence 560 %hget-signed-word function 546
null pointer 538, 559 %hget-unsigned-long function 548
Pascal types and MCL equivalents 572 %hget-word function 546
true and false 604 %hput-byte function 550
VAR arguments 559, 594 %hput-long function 551
Paste command 33 %hput-ptr function 552
paste generic function 16, 116, 181, 216, 494 %hput-word function 551
Paste menu item 16 %incf-ptr macro 558
pathnames 299–329 %inc-ptr function 558
creating 302 %int-to-ptr function 558
definition 297 %null-ptr macro 559
escape character 307 %null-ptr-p function 559
MCL functions related to 303–305 %path-from-fsspec function 417
namestring conversion 299 %ptr-to-int function 558
numeric arguments 298 %put-byte function 550
parsing 305–306 %put-cstring function 553
printing 298 %put-full-long function 551
quoting special character 307 %put-long function 551
reading 298 %put-ostype function 553
set pathname 327–329 %put-ptr function 552
specification 302 %put-string function 552
pen-hide generic function 713 %put-word function 550
pen-mode generic function 716 %setf-macptr function 541
pen-mode keywords 82 %stack-block macro 542
pen-normal generic function 718 %set-toplevel function 654
pen-pattern generic function 715 %stack-block vs. rlet 542
pen-position generic function 713 %vstack-block macro 542
pen-show generic function 713 %word-to-int function 531
pen-shown-p generic function 713 pictures
pen-size generic function 714 draw 753
pen-state generic function 718 get 752
%copy-float function 531 kill 753
%gen-trap function 601 start 752
%get-byte function 544 stop and return 752
Index 797
reader methods 671 rectangles
reading current s-expression 339 angle number 725
readtable, inspect current 370 empty, checking 726
real-color-equal function 262, 265 equality between rectangles 725
real-font function 71 erase 728
record field fill with pattern 729
definition 575 frame 726
structure 575 intersection 722
record field types (mactypes) 566, 571–574 invert pixels 728
length 578, 579 map 760
record-fields function 573 move 721
record-info function 574 paint 727
record-length macro 573 point in rectangle, checking 724
records 574–594 points defining rectangle 724
changes from previous version of shrink or expand 722
Macintosh Common Lisp 565 union 723
copying 592 rect-in-region-p function 747
create efficient record 580 redraw-cell generic function 226
create record with indefinite extent 583 regions
create temporary record 580 allocate new region 741
define record type 576 close region record 743
definition 565, 574 copy or create 742
dispose of 584 difference 745
examples 570 dispose 742
find fields 573 empty 742
find info about all fields 574 empty, checking 747
find info about one field 574 equality between regions, checking 747
find length 573 erase 748
find record field type 573 exclusive-or of two regions 746
find record type 572 fill 749
listing record field types 593 frame 748
listing record types 593 intersection 745
menu record handle 103 invert pixels 749
printing values of fields 594 map 761
record field, definition 575 move 744
return contents of fields 584, 586, 587 open region record 743
returning value of field 592 paint 748
setting value of field 593 point in region, checking 746
variant fields 579 rectangle, set to 742
record types 571–574 rectangle in region, checking 747
define 576 shrink or expand 744
find 572 union 745
inspect 370 register trap call 597
listing record field types 593 register-trap macro 600
listing record types 593 reindex-interfaces function 569
rectangle record, storage 709 remove-dialog-items. See remove-
subviews generic function
remove-key-handler generic function 382
remove-menu-items generic function 99
Index 799
select entire buffer 47 set-internal-scrap generic function 407,
selection-range generic function 486 409
selection, types allowed in tables 254 set-local macro 357
select-item-from-list function 254 set-mac-default-directory function 311
sequence-dialog-item class 190, 243 set-mac-file-creator function 323
sequence dialog items, creating instances 243 set-mac-file-type function 323
set-allow-returns generic function 215, set-mark function 448
476 set-menubar function 88, 89
set-allow-tabs generic function 215, 476 set-menu-item-action-function generic
set-cell-font generic function 230 function 105, 108
set-cell-size generic function 229 set-menu-item-check-mark generic
set-choose-file-default-directory function 111, 118
function 329 set-menu-item-style generic function
set-clip-region generic function 711 112, 118
set-command-key generic function 110 set-menu-item-title generic function 109
set-current-compiler-policy function set-menu-item-update-function generic
643 function 113
set-current-file-compiler-policy set-menu-title generic function 95
function 643 set-mini-buffer generic function 503
set-current-key-handler generic set-origin generic function 708, 710
function 211, 381 set-part-color generic function 273
set-cursor function 404 dialog-item 200
set-dead-keys (obsolete mcl function) 41 menu 102
set-default-button generic function 209 menubar 92
set-dialog-item-action-function menu-item 115
generic function 195 table-dialog-item 230
set-dialog-item-font. See set-view- window 171
font generic function set-pen-mode generic function 716
set-dialog-item-handle generic function set-pen-pattern generic function 715
203 set-pen-size generic function 714
set-dialog-item-size. See set-view- set-pen-state generic function 718
size generic function set-record-field function 593
set-dialog-item-text generic function set-rect-region function 742
197, 211 set-scroll-bar-length generic function
set-empty-region function 742 238
set-event-ticks function 397 set-scroll-bar-max generic function 239
set-file-create-date function 321 set-scroll-bar-min generic function 239
set-file-write-date function 321 set-scroll-bar-scrollee generic
set-fore-color generic function 270 function 240
set-fred-display-start-mark generic set-scroll-bar-setting generic function
function 479 241
set-fred-hscroll generic function 486 set-scroll-bar-track-thumb-p generic
set-fred-last-command generic function function 241
511 set-scroll-bar-width generic function
set-fred-margin generic function 491 242
set-fred-package generic function 490 set-selection-range generic function 487
set-gc-event-check-enabled-p function set-table-dimensions generic function
637 228
set-grafport-font-codes function 79 set-table-sequence generic function 244
setting a font 33
Index 801
stream-listen generic function 436 table-hscrollp generic function 233
stream-peek generic function 434 tables. See table dialog items
stream-reader generic function 431 table-sequence generic function 244
streams 426–439 table-vscrollp generic function 234
clear pending input from 436 tagged pointer 621
close 438 tag values 621–623
close abnormally 439 tail recursion 638
current column 434 target function 158
definition of class 426 Tatar, Deborah 764
end, check for 436 terminating a command 60
functionality 426 text, selecting 46
increase speed by buffering 428 throw-cancel macro 248
line length 434 time macro 372
outputting character 428 Tool dialog box 289
print newline in 435 Tools menu 18
read further characters from 436 top-inspect-form function 348, 371
read next character 429 toplevel function 653
reopen after close 438 toplevel-loop function 654, 655
unread character from 430 Touretzky, David 765
write all pending output 428 trace macro 360
stream-tyi generic function 429 trace-tab function 364
stream-tyo generic function 428, 720 tracing 359, 360–368
stream-untyi generic function 430 MCL functions associated with tracing
stream-writer generic function 431 363–365
stream-write-string generic function 435 transposition 51
strings, print readably 629 trap call
string-width function 72 register 597
structure-class class 607 stack 595, 597
structured directories 313–316 traps 565–574, 594–604
structure-object class 606 create named trap 569
structurep function 645 define behavior 569
structures, print readably 629 dispatch table 566
structure-typep function 645 examples 570, 577
subtract-points function 68 trap macro 566
subviews generic function 133 trap word 566
superclasses 621 update index files 567
suspend 18 updating interface index files 569
Suspend command 11 turnkey dialogs 248
Sussman, Gerald 765 tyi (obsolete function) 439
syntax xxix–xxxi tyo (obsolete function) 439
system requirements xxxi
U
T unadvise macro 368
Tab keystroke 49 uncompile-function function 356
table-dialog-item class 190, 221, 223 _waitnextevent trap 655
table dialog items 221–234 undo 496, 497, 498
creating instances 224 undo generic function 16, 116, 181, 216
definition 221 Undo menu item 16
table-dimensions generic function 227 undo more generic function 16
Index 803
view-scroll-position generic function window-drag-rect generic function 179
145 window-draw-grow-icon generic function
view-size generic function 144, 163, 189 390
dialog-item 196 window-ensure-on-screen generic
view-subviews generic function 133 function 172
view-window function 142 window-eval-buffer generic function 181
visible-dimensions generic function 228 window-eval-selection generic function
volume-number function 324 116, 181
volumes, MCL operations related to 324–327 window-eval-whole-buffer generic
function 116
W window-event generic function 398
widmax 73, 76 window-filename generic function 489
wildcards 317 window-font. See view-font generic
Wilensky, Robert 765 function
windoid class 183 window-grow-event-handler generic
windoids 124, 183 function 385
window-activate-event-handler. See window-grow-rect generic function 178
view-activate-event-handler window-hardcopy generic function 116, 181,
generic function 493
window-active-p generic function 173 window-hide generic function 172
window-buffer. See fred-buffer generic window-hpos. See fred-hpos generic
function function
window-can-do-operation generic window-key-up-event-handler generic
function 182, 495 function 384
window-can-undo-p (obsolete MCL window-layer generic function 174
function) 182, 495 window-line-vpos. See fred-line-vpos
window-can-undo-p generic function 216, generic function
494 window-menu-item class 117
window class 153 window menu items 115–118
window-click-event-handler. See creating instances 117
view-click-event-handler generic window-mouse-position. Seeview-mouse-
function position generic function
window-close-event-handler generic window-mouse-up-event-handler generic
function 387 function 385
window-close generic function 116, 160, 181 window-needs-saving-p generic function
window-cursor generic function 180 116, 182
window-deactivate-event-handler. See window-null-event-handler generic
view-deactivate-event-handler function 383, 384
generic function window-object function 180
window-default-zoom-position generic window-on-screen-p generic function 173
function 175, 176 window-package generic function 35
window-default-zoom-size generic window-position. See view-position
function 177 generic function
window-defs-dialog generic function 116, window-revert generic function 116, 181,
181 492
window-do-first-click generic function windows 152
387 activate 148, 175
window-drag-event-handler generic active, checking 173
function 386 can take dialog items 188
close 15, 160
Index 805
with-aedescs macro 416
with-back-color macro 272
with-cstrs macro 554
with-cursor macro 402, 403, 404
with-dereferenced-handles macro 557
with-focused-dialog-item macro 205
with-focused-view macro 129, 130, 181,
708
with-font-focused-view macro 131
with-fore-color macro 271
without-interrupts special form 180,
358, 401, 405
with-pointers macro 557
with-port macro 180
with-pstrs macro 554
with-returned-pstrs macro 554
with-rgb macro 267
wptr
font codes 80
window object 180
wptr-font-codes function 80
wptr generic function 141
writer methods 671
X, Y, Z
x-coordinate of points 64
xor-region function 746
yank 49
rotating 49
y-coordinate of points 64
y-or-n-dialog function 250
zone-pointerp function 556