Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Database

An Introduction to Hypercard Programming


SP 88: AN INTRODUCTION TO HYPERCARD PROGRAMMING

This article contains the following executables: HYPER.ARC

Dan Allen is a Software Explorer for Apple Computer where he has worked on several projects including MacApp, HFS, MacPlus, MacsBug, and MPW. He is currently working with Bill Atkinson on HyperCard. He can be reached at Apple Computer Inc., 20525 Mariani Ave., MS: 27E, Cupertino, CA 95014.


HyperCard is a hypertext application that includes two major subsystems: a bitmap graphics editor and a programming language. Bill Atkinson, HyperCard's inventor, refers to HyperCard as a software erector set. Others see it as an information toolkit. It is not a traditional database, although it can handle large quantities of data quickly. Rather, HyperCard is a new type of application that does not fit neatly into traditional software categories.

HyperCard descended from two related applications that Bill Atkinson wrote: MacPaint{1} and QuickFile.{2} HyperCard also makes extensive use of QuickDraw, the Macintosh graphics routines found in ROM.{3} HyperCard began under the code name WildCard in late 1985. The first working developmental version was given only limited internal distribution at Apple in June 1986.

In the fall of 1986, the developers decided to include a programming language in WildCard, so Atkinson and Dan Winkler designed WildTalk. HyperCard's language, now known as HyperTalk, has a rich, English-like vocabulary that allows users to write powerful yet simple programs called scripts.

HyperTalk as an Object-Oriented Language

HyperTalk follows the object-oriented programming tradition with its own flavor of objects, classes, and inheritance:

object oriented = objects + classes + inheritance{4}

HyperCard's classes are stacks, backgrounds, cards, fields, and buttons. Users can create many new objects (which by definition are instances of these classes), but they cannot create entirely new types of classes.

Each individual object can have a script associated with it, and each HyperTalk script can contain many handlers (methods) that can send, receive, and service messages. Handlers are similar to procedures in that they can be passed parameters and called recursively, but handler definitions cannot be nested. Handlers support local and global variables.

HyperTalk's inheritance path allows messages to be dealt with by handlers at various points in the system. When a message is passed to a HyperCard object, first the script of that object is checked for a corresponding handler of the same name. If it is found, it is then interpreted: otherwise, the current cards script is checked, then the background script, then the stacks script, then the script for the home stack, and finally HyperCard itself.{5} The HyperCard commands listed in Table 1, page 58, for example, are simply messages handled by HyperCard, and thus can be redefined by the user through the inheritance path. Objects can subvert the standard hierarchy by use of the keyword send.

Table 1: HyperTalk Elements

The HyperTalk language can be divided up into the following categories. This summary does not include information about the syntax of the HyperTalk vocabulary, but is simply a list of the HyperTalk lexical elements or parts of speech.

Adjectives
abbr, abbrev, abbreviated, long, short.

ChunkParts
char, character, item, line, word.

Commands
add, answer, arrowKey, ask, beep, choose, click, close, controlKey, convert, debug, delete, dial, divide, doMenu, drag, edit, enterKey, find, functionKey, get, go, help, hide, multiply, open, play, pop, print, push, put, read, reset, returnKey, set, show, sort, subtract, tabKey, type, visual, wait, write.

Constants
down, eight, empty, false, five, formFeed, four, lineFeed, nine, one, pi, quote, seven, six, space, tab, ten, three, true, two, up, zero.

Functions
abs, annuity, atan, average, charToNum, clickLoc, cmdKey, commandKey, compound, cos, date, diskSpace, exp, exp1, exp2, heapSpace, length, In, In 1, log2, max, min, mouse, mouseClick, mouseH, mouseLoc, mouseV, number, numToChar, offset, optionKey, param, paramCount, params, random, result, round, seconds, secs, shiftKey, sin, sound sqrt, stackSpace, tan, target, ticks, time, tool, trunc, value, version.

Messages
closeBackground, closeCard, closeField, closeStack, deleteBackground, deleteButton, deleteCard, deleteField, deleteStack, idle, mouseDown, mouseEnter, mouseLeave, mouseStillDown, mouseUp, mouseWithin, newBackground, newButton, newCard, newField, newStack, openBackground, openCard, openField, openStack, quit, resume, startup, suspend.

Months/Days
January, Jan, February, Feb, March, Mar, April, Apr, May, June, Jun, July, Jul, August, Aug, September, Sep, October, Oct, November, Nov, December, Dec, Sunday, Sun, Monday, Mon, Tuesday, Tue, Wednesday, Wed, Thursday, Thu, Friday, Fri, Saturday, Sat.

Operators
&, &&, +, -, *, /, ^, <, <=, <>, =, >, >=, and, contains, div, in, is, mod, not, or.

Ordinals
first, second, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth, any, mid, middle, last.

Prepositions
after, before, into.

Properties
autoHilite, blindTyping, brush, centered, cursor, dragSpeed, editBkgnd, filled, freeSize, grid, highlight, highlite, hilight, hilite, icon, id, language, lineSize, Ioc, location, lockMessages, lockRecent, lockScreen, lockText, multiple, multiSpace, name, numberFormat, pattern, polySides, powerKeys, rectangle, script, scroll, showLines, showName, size, style, textAlign, textArrows, textFont, textHeight, textSize, textStyle, userLevel, visible, wideMargins.

Special
all, ascending, at, background, backgrounds, barn, bkgnd, bkgnds, black, blinds, box, browse, brush, btn, bucket, button, by, can, card, cards, characters, chars, checkerboard, close, curve, cut, dateTime, descending, dialog, dissolve, door, down, effect, eraser, fast, field, file, for, forever, from, function, gray, hypercard, in, international, inverse, iris, it, lasso, left, line, me, menuBar, message, msg, modem, not, numeric, of, on, open, out, oval, paint password, pencil, plain, poly, polygon, prev, previous, printing, rect, reg, regular, right, round, script, scroll, select, selection, slow, slowly, spray, stop, tempo, text, the, this, to, tool, until, up, venetian, very, while, white, window, wipe, with, word, zoom part2.

Structured Keywords

do, else, end, exit, global, if, next, on, pass, repeat, return, send, then.

A Sample HyperTalk Script

The handler shown in Example 1, this page, exports all of the text from the background fields of a HyperCard stack to a text file. This handler illustrates how simple it is to write a tab- or CR-delimited ASCII file from inside of HyperCard. The method for importing is similar.

Example 1: A handler to export text from the background fields of a HyperCard stock to a text file.

         on mouseUp
           put the short name of this stack & ".tx" into
         defaultName
            ask "Export text to what file?" with defaultName
            if it is empty then exit mouseUp
            put it into fileName
            open file fileName
            go to first card
            repeat for the number of cards
              repeat with i = 1 to the number of fields
                put field i into temp
                repeat
                  if return is not in temp then exit repeat
                  put space into char offset (return, temp) of temp
                end repeat
                write temp to file fileName
                if i _ the number of fields then
                  write tab to file fileName
                else write return to file fileName
                end if
             end repeat
             go to next card
           end repeat
           close file fileName
         end mouseUp

XCMDs and XFCNs

When HyperTalk is too slow or is lacking a particular function, there are a couple of trapdoors that can be used: XCMDs and XFCNs. The only difference between an XFCN and an XCMD is that an XFCN returns a result; the difference here is similar to that between a procedure and a function in Pascal. For the sake of convenience, we refer to them collectively as XCMDs.

An XCMD is compiled code. Writing XCMDs is a task for programmers, not users. With Apple's Macintosh Programmer's Workshop (MPW), programmers can write XCMDs using Assembly, C, or Pascal. For more information on MPW, see "Overview of the Macintosh Programmer's Workshop," page 20.

XCMDs are called as if they were built-in HyperTalk commands. They are invoked by HyperTalk through its inheritance mechanism. As a message ascends the hierarchy, the resource forks of certain stacks{6} are checked to see if they have an XCMD or XFCN resource of the right name that will handle the message. If the appropriate resource name is found, the resource is loaded into memory and HyperCard jumps to the start of it. After the XCMD has executed, control returns to HyperCard.

XCMDs are easily installed and moved between files with the use of reswdit, or better yet, with rescopy, a public domain stack by Apple's Steve Maller. rescopy imitates the Font/DA Movers interface in a HyperCard stack. (rescopy itself is written as an XCMD!) There are several reasons for using an XCMD:

  • As an interface to drivers, in order to set up HyperCard to control external devices, such as video disk players and CD-ROMs
  • As a means of accessing the Macintosh OS and ToolBox routines
  • As a means of accessing some of HyperCard's internal routines
  • As a means of speeding up execution of time-critical code

XCMDs and Drivers

HyperCard, because of its outstanding user interface and its ability to be customized, is a great way to get the Macintosh to talk to other devices, such as video disk players. It is easy to control a video disk player through the built-in RS-232 ports of the Mac. XCMDs can be the glue that binds HyperCard to the video disk player.

The video disk player controller would require three pieces of code. The driver for the video disk player would be a standard Macintosh driver. These specialized pieces of code have been around since Macintosh's beginnings. Many people have become proficient at writing drivers because a desk accessory is a driver. For more information on writing drivers, see Inside Macintosh, Volume II.

The second piece of code would be the XCMD. The XCMD would be small, and its purpose would be to simply convert HyperTalk messages to the appropriate driver calls.

The third piece of code would be the HyperTalk scripts that call the XCMD with various parameters, asking it to ask the driver to ask the laser disk player to go to a certain frame, or to backup, for example.

Using XCMDs as an interface to traditional drivers is a simple but powerful operation. If an XCMD gets too big in size, think about writing a driver.

XCMDs and the Macintosh Toolbox

HyperTalk has a lot of functions, but if you need something it does not have, the Macintosh OS and ToolBox might have it. Indeed, Macintosh programming sometimes seems like an endless series of calls to the Mac ROMS.

Most ToolBox traps and routines can be called from XCMDs, with certain restrictions and limitations, outlined below. Keep in mind that XCMDs do have limitations. They are not allowed to do everything that an application is allowed to do because they are guests in HyperCard's heap. XCMDs are more like desk accessories than an application in this regard.{7} Listing One on page 66 contains a sample HyperCard XFCN, which returns the contents of memory.

Guidelines for writings XCMDs are as follows:

  • Do not initialize the various Macintosh managers by calling their init traps: that is, do not call InitGraf, InitFonts, InitWindows, and so on.
  • Do not rely upon having lots of RAM available for your code. There is some extra space in HyperCard's heap, but if HyperCard is running in 750K under MultiFinder, for example, no XCMD should exceed 32K.
  • Do not use register A5 of the 68xxx processor. The value in A5 is HyperCard's and points to HyperCard's global data, jump table, and other things that constitute an A5 World. XCMDs do not currently have their own A5 World.
  • No A5 World means no global data for XCMDs.
  • No global data means no use of string literals with MPW C, since MPW C makes string literals into global data. (Alternative: Use STR resources or put the strings in a short assembly glue file.)
  • No A5 World means no jump table. No jump table means no code segments. No code segments means a 32K limit on code size for 68000 based machines. (The 68020 supports longer branches.)
  • XCMDs can, however, allocate small chunks of memory by standard NewHandle (and if you really must do it, NewPointer) calls.
  • If your code allocated some memory in the heap, your code should also deallocate the memory.
  • If an XCMD allocates a handle to save state information between invocations of the XCMD, then you must also use HyperTalk to store the handle somewhere in the current stack, perhaps in a hidden field. You will need to convert the handle from a LongInt to a string, as everything is treated as a string on the HyperTalk end of things.
  • Since HyperTalk jumps blindly to the start of an XCMD piece of code, it is important that the main routine actually end up at the start of the XCMD: The link order is important.

XCMDs and HyperTalk Callback Routines

There are many useful internal routines that HyperTalk also allows XCMDs to call. HyperTalk provides both conversion routines as well as stackaccess routines.

The conversion routines provide support for converting various styles of strings and numbers into each other. For example, there are routines to convert C-style strings (zero terminated) back and forth to Pascal-style strings (length byte followed by string). There are also routines to convert strings to and from integers. Listing Two on page 66 contains a sample HyperCard XCMD to highlight the screen.

The stackaccess routines allow an XCMD to call back into HyperTalk and send messages to the current card or to HyperCard itself. In addition, values of variables can be recalled and stored into, and contents of fields can be examined. The bulk of the code in the glue files is there to support these callback routines.

XCMDs and Speeding up HyperTalk

HyperTalk is versatile, partly because it is an interpreted language. However, because it is interpreted, it is also sometimes slow, especially when doing anything repetitive. For this reason, it is often wise to rewrite some operations as XCMDs, to benefit from the speed of compiled native 68xxx code.

Documentation

HyperCard ships with an excellent introductory manual that, unfortunately, does not include a description of HyperTalk. However, several good sources of information about using HyperTalk are available. The Help stack that ships with HyperCard contains a great deal of information about the language, and is an excellent resource.

The most accurate single source about HyperTalk is the reference manual, HyperCard Script Language Guide, written by Alan Spragens of Apple Computer. A good tutorial (with pretty good reference material) for HyperTalk has become an overnight phenomenon: Danny Goodman's The Complete HyperCard Handbook. This book, published by Bantam, is currently a bestseller. There is a rash of other books on the market, but most of them are highly inaccurate. Reader be warned!

The official documentation on XCMDs is available from the Apple Programmer's and Developer's Association (APDA). The HyperCard Script Language Guide has some technical material on writing XCMDs, but the HyperCard Developer's Toolkit contains the bulk of the information, in this case as example XCMDs in C and Pascal for MPW. For more information, contact: Apple Programmer's and Developer's Assoc., 290 SW 43rd Street, Renton, WA 98055; 206-251-6548.

As of January 1, 1988, the following HyperCard related products are sold through APDA. All software is shipped on 800K HFS disks. HyperCard Script Language Guide (200 pages), $18.50. HyperCard Developer's Toolkit (One disk, 20 pages), $10.00. The disk includes the header and glue files shown in Listings Three (page 68) and Four (page 70).

Notes

    1. Originally packaged with every Macintosh sold, the original versions of MacPaint (1.0 through 1.5) were written 75 percent in Pascal and 25 percent in assembly language on a Lisa, using the Lisa Monitor, a smaller, faster precursor of the Lisa Workshop. The latest version of MacPaint (2.0) is a major revision by David Ramsey using MPW Pascal. MacPaint is now available through Apple's spin-off software company, Claris.

    2. QuickFile is a small publicdomain file manager that Bill Atkinson wrote in 1985. It uses a fast in-memory text search with a fixed-sized Rolodex card. Its search routine is completely different from that used in HyperCard. QuickFile was originally called Rolodex, but the name was changed due to copyright problems.

    3. Bill Atkinson originally wrote QuickDraw for the Lisa computer. When Apple decided to include QuickDraw on the Macintosh, Bill became an honorary Mac team member. QuickDraw was first written in Pascal, then rewritten many times, ending up finally as 24K of 68000 assembly code. Bill further enhanced QuickDraw for the Mac Plus by unwinding some of the loops, thus increasing the speed. However, Bill was not involved with Color QuickDraw, which is found on the Mac II, because he was involved with HyperCard at the time. Ernie Beernink and Dave Fung did Color QuickDraw.

    4. This equation is from Peter Wegner's OOPSLA '87 paper, "Dimensions of Object-Based Language Design." For more definitional information about object-oriented programming, see "Overview of the Macintosh Programmer's Workshop," page xx.

    5. Actually the inheritance path is slightly more complicated when the currently executing script goes to a different card or stack during its execution. The current script card or stack is searched as well as the current (visible) card or stack.

    6. The search order for XCMDs is: (a) the stack that contains the running script, (b) the current stack (if different from a) (c) the Home stack, (d) HyperCard itself.

    7. Desk accessories were originally meant to be a maximum of 8K. Today there are desk accessories over 100K! XCMDs of that size may work, but the system was really only designed for XCMDs of about 32K.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.