Hypercard

This article is an overview for new Revolution developers who have experience with HyperCard and the HyperTalk language, and who want to learn how to leverage their HyperCard knowledge and existing stacks to get a running start in Revolution. Since Revolution can read HyperCard stacks, you can start out by converting or re-creating your existing stacks, then extend your work to include the new capabilities available in Revolution.

Note: We recommend you look at the material in the Learning Center (available within the trial version) to get up to speed before you convert a HyperCard stack.

We also recommend the excellent in-depth tutorial on Jacqueline Landman Gay's HyperActive Software site.

As an experienced HyperCard developer, you’ll find Revolution’s object model and development environment both familiar and different. It is familiar because objects remain objects and the language is extremely similar. It is different because unlike HyperCard, Revolution is a modern development tool with support for both standard operating system paradigms plus compelling new features.

You create objects in a stack window (which can have one or more cards). You write handlers in the Revolution language, whose syntax is very similar to HyperTalk.

Revolution supports all the object types HyperCard does, plus more: buttons, fields, images (bitmaps you can either paint in or display a file in), draw graphics, QuickTime players, and scrollbars. You use the Object Properties palette to change the appearance and behavior of these objects and to edit scripts.

In converting from HyperCard to Runtime Revolution, you should be aware of some differences in conventions.

In HyperCard, each window is a stack, and each stack is a file. A Revolution project has a master stack and can have multiple sub-stacks, allowing you to create multi-window applications in either a single file or in multiple files.

Revolution also gives you additional window options. A stack can be displayed as a normal editable window, as a palette, or as a modal or modeless dialog box. This means you can easily create custom palettes and dialogs without using externals, and include them in the same file as your main windows.

Stacks can be resized either using the resize box in the lower left corner or under script control. You can remove the resize box as well as set minimum and maximum sizes for the window.

Tip: Use the Geometry Manager feature to have Revolution automatically move and resize objects in the stack when the user resizes the window.

In HyperCard, you place objects in the background layer, and each card with that background displays those objects behind the card objects.

In Revolution, you can use the Group menu item (or the group command) to combine any set of selected objects into a group. Unlike HyperCard backgrounds, groups can be added to any card in the stack, and a card can contain more than one group. Groups can be interleaved with, or in front of, non-grouped objects.

Groups are very flexible. You can select and move a group, show it, hide it, give it borders or scrollbars, and place it on any card or remove it from any card. Like a background, a group can have a script. You can even create a group that contains other groups.

When you create a new card, any groups on the current card are placed on the new card, just like the way HyperCard adds a new card to the current background.

It is important to remember that groups are not backgrounds. In HyperCard, every card belongs to a background.

In Revolution, however, cards do not have to have groups. A group belongs to cards rather than the card belonging to a group.

In HyperCard, you create popup menus by setting a button’s “style” property to “popup” and placing the menu contents in the button. You change menus in the menu bar using the “create menu” command, and use the “doMenu” command to simulate choosing a menu item.

In Revolution, all menus (including menus in the menu bar) are implemented as buttons. Button menus are created in much the same way as HyperCard popup menus. You set the style of the button to menu, and set its menuMode property to specify a pulldown menu, popup menu (called an “option menu” in Revolution), or combo box. These button menus can be placed anywhere in a stack.

To create a menu bar, you first create a button for each menu, setting the button’s menuMode to pulldown. Then you combine those menus into a group, placed at the top of the stack window.

Tip: Use the Menu Manager feature to automatically create and place the buttons for a menu bar, set its appearance appropriately for any platform, and specify keyboard equivalents for its menu items.

If you set the stack’s menubar property to the name of the group, Revolution displays the group’s menus as a normal MacOS menu bar and changes the window size to hide the buttons. This means that the menu bar will appear in the proper place for each platform: on MacOS systems, the menus appear at the top of the screen in the menu bar, while on Unix and Windows systems they appear at the top of the stack window, in accordance with user-interface standards for those platforms.

Many of the features HyperCard developers have called for over the years were included in the earliest versions of Revolution:

  • Fully native, script-controllable color for all objects
  • Easy cross-platform development for Windows and Unix
  • Vector (resizable) graphics
  • True arrays
  • Effectively unlimited text in fields
  • Effectively unlimited script length

In general, limits on size are larger, script execution is much faster, more media formats and object types are supported, and the number of built-in commands, functions, and properties is greater.

While Revolution supports the HyperCard 1.x XCMD model (which means that most XCMDs and XFCNs that don’t display a window will work in Revolution without modification), most HyperCard developers find that they rarely need to use externals because equivalents for common externals are already part of Revolution. You can use the Revolution language to rename, move, and delete files; move resources among files; get the contents of a folder; set the cursor location; place a solid backdrop behind your stack; and get URLs, post data to a web server, or communicate directly with other systems on the Internet via sockets. Color is built in, and so is the ability to create and control palettes and dialog boxes. And the Revolution language is fast enough that repetitive tasks that once required externals for speed become practical to implement as handlers instead.

Here are a few specific enhancements you may find interesting:

The is among operator tests whether a specified chunk exists in a string:

if "Fred" is among the items of "Adam,Fred,George"
then doSomething

Revolution contains lineOffset, itemOffset, and wordOffset functions in addition to HyperTalk’s “offset” function, so you can find out which line, item, or word contains a specified string.

Chunk expressions can contain negative indexes to count backward from the end of a string. For example, word -2 of myString specifies the second-to-last word.

You can also loop over each chunk in a string:

repeat for each word currentWord in myString
  if currentWord is "George" then beep
end repeat

In addition to chunk expressions, Revolution supports the powerful regular-expression syntax via its matchText function. Regular expressions are a method of specifying a text pattern you want to find - if you have been struggling to keep your HyperCard stacks running under MacOS X, you already know that the underlying operating system is based on a form of Unix.

Revolution treats URLs as containers, so you can work directly with the contents of any URL:

 put URL "http://www.example.com/file.txt" into field "Text"
put myVar into URL "file:/Disk/Folder/File"

Revolution supports HyperTalk’s start using command to let you use other stacks as script libraries. You can also use the insert script command to place any object — not just a stack — into the message path, either after all objects or before any objects. A script inserted into the front of the message path can handle a message before the target object itself receives the message.

You can create custom properties for any object. These properties can contain any kind of data, of effectively unlimited length. You get and set them in the same way as built-in properties.

You can set the textFont, textSize, and textStyle properties of a card, group, or stack (as well as their color properties). Any object whose text and color properties are not set will inherit the font, size, style, and color of the next object in the message path.

For example, if you set the textFont of a stack to Helvetica, all the objects in the stack will automatically switch to Helvetica (unless you’ve specified an indepedent textFont for them).

In Revolution, you can read and write binary files which may contain null characters, ASCII zero.

Note: In HyperCard this is not possible because the null character cannot be handled by HyperTalk’s data structures.

The ability to read and write binary files and process binary data in variables allows you to create any type of file you wish, as long as you understand the format of the file type. For example, you can create JPEG files by writing the raw data directly to the file.

Revolution supports array variables (variables that contain more than one value). The parts, or elements, of an array can be indexed by number or by any string.

Tip: Scan the Revolution Dictionary to explore new language terms.

Revolution’s development environment is modern but recognizable. There is a message box (although the Revolution message box can execute multiple-line structures as well as one-line statements) and a tool palette for working with objects.

To select an object of any type, you use the pointer (arrow) tool, rather than having a different tool for each object type. This means that, for example, you can select several buttons and fields and move them all at once.

You access an object’s properties by selecting the object, then choosing “Object Properties” from the Object menu. The Properties palette contains tabs across the top for basic properties (common to all objects), the object’s script, the object’s custom properties, and properties specific to the object’s type. Some object types, such as buttons, have two tabs.

The script editor is accessed by clicking the second tab from the left on the object’s Properties palette. The Revolution script editor accepts styled text, so you can use colors and fonts to emphasize portions of your handlers, mark unfinished code, and so on. To search a script, choose “Find and Replace” from the Script menu.

Just as in HyperCard, you can test a handler as soon as it’s written, and use your stack within the development environment. There is no compile step or separate runtime environment needed. However, if you want to test your stack in a “clean” environment without any of Revolution’s own menus, palettes, or other parts of the development environment, you can use the “Suspend Revolution UI” item in the Development menu. When you’re ready to build a standalone application, use the “Build Distribution” dialog box in the File menu. Here you can create standalone applications for any of Revolution’s supported platforms.

The development environment—menus, palettes, dialog boxes, and all—is built entirely in Revolution. This not only demonstrates the power of the Revolution engine, it means that as you advance, there is the possibility of exploring the Revolution user interface and customizing it for your needs.

Revolution’s scripting language is also called Revolution. Revolution’s language conventions will be instantly recognizable to Hypertalk users.

As in HyperTalk, the script of an object is composed of one or more handlers that respond to messages sent to the object. All the familiar HyperTalk messages are supported (along with new ones), so you can set a button’s script to read

 on mouseUp
  beep
end mouseUp

and it will react as you expect it to.

As in HyperCard, messages are sent first to the target object, then proceed along a message path containing all the owning objects. For example, if you click a button, theresulting mouseUp message is normally sent first to the button, then to the card the button is on, then to the stack the card is in.

Tip: In Revolution, built-in commands and functions do not traverse the message path, but are sent straight to Revolution. This means you cannot override the behavior of a built-in command or function by inserting a handler in the message path. (To create your own functions and commands, use a custom message handler.) However, this means Transcript handlers typically run from five to one hundred times faster than their HyperTalk equivalents. This enormous speed increase means you’ll find that many computing-intensive tasks that were too slow to be practical in HyperCard are feasible in Revolution.

You can refer to objects by name, number, or ID. As in HyperCard, the ID of objects never changes. (Stacks, which do not have IDs in HyperCard, are the exception. You can change a stack’s ID in Revolution.) No two objects in a stack can have the same ID.

Revolution supports all HyperTalk control structures (if/then/else/end if, repeat, pass, send, exit, return) as well as two new ones:

  • switch: A conditional structure (like if) for use when you want to check several possible cases.
  • try/catch/throw: A structure that executes a set of statements and catches any errors that occur during execution.

Revolution 1.0 has approximately three times as many commands, properties, and functions as HyperTalk 2.4, so only a few of the new capabilities are discussed in this topic - Revolution 2.7.x has vastly increased the number of options. Refer to the Revolution Dictionary in the Revolution documentation for complete language information.

Revolution can read most HyperCard stacks directly. The basic process for importing a stack is simple:

  1. In HyperCard, compact the stack.
  1. Launch Revolution, choose “Open Stack” from the File menu, and select your stack (or use the go command in a handler). As the stack opens, Revolution automatically converts it to Revolution’s file format. Each background is converted to a group which is placed on each card of that background.

For the most part, your stacks will be compatible and run properly in Revolution. Possible issues may crop up in these areas:

  • Revolution does not import color added to HyperCard stacks using the AddColor XCMD architecture. If you have colorized your stack, you will need to re-color it using Revolution’s color properties.
  • Sounds, icons, and cursor resources are converted on input, but all other resources are discarded. If your stack requires other resources (such as XCMDs or XFCNs) whose functionality is not already included in Revolution, you will need to move them into the new stack using ResEdit or another resource mover.
  • HyperTalk commands that change the standard menu bar, or show or hide palettes, generally will not work in Revolution (with the exception of showing and hiding the message box) because the development environments are so different.
  • Since menus are handled differently in Revolution, almost all code that affects the menu bar will need to be rewritten.

If any of these issues exist in your stack, to avoid encountering script errors, comment out the handlers involved before you compact your stack and import it into Revolution. For example, you should comment out any code that deals with color, calls an external, or changes the menu bar. After the stack is successfully imported, you can rewrite the affected handlers.

When importing a HyperCard stack, Revolution sets the stack’s HCStack property to true. Check this property if you need to know whether a stack originated in HyperCard.

An imported stack’s HCAddressing property is automatically set to true, which causes Revolution to assume that references to buttons refer to card buttons and references to fields refer to grouped fields. The dynamicPaths property is also set to true, which implements HyperCard’s dynamic path in case your stack depends on that behavior Tips and Gotchas

Revolution has a high level of compatibility with HyperCard, and almost all your knowledge will translate easily. However, there are a few incompatibilities and areas where Revolution offers a different method of doing things.

Occasionally, you’ll need to store data (such as a card modification date) so that it’s not visible to users, but scripts can access it. In HyperCard, it is common practice to store such data in a hidden field on the card.

In Revolution, you can set a custom property instead. Custom properties can hold any data you want to place in them, are saved with the stack, can be associated with any object, and are used in handlers just like built-in properties.

In HyperCard, commands and functions pass through the message path, so a handler with the same name as a built-in command or function overrides its normal behavior.

In Revolution, built-in commands and functions are executed immediately rather than passing through the message path, so a handler with the same name as a built-in command or function will never be executed. Explicit save:

HyperCard saves changes to stacks automatically. Revolution uses the more usual method of requiring the user to save changes explicitly. (You can also write a closeCard handler to save the current stack automatically when you go to another card if you want to emulate the HyperCard automatic save.)

Since HyperCard’s Home stack is in the message path of all objects, many HyperCard developers place custom handlers in the Home stack script for easy availability while developing. In Revolution, you accomplish the same thing by placing a stack containing your handlers in the Plugins folder and using the Plugins Editor (in the Development menu) to automatically load it when Revolution starts up. You can create as many plugin stacks as you want, and control when they load, how they’re displayed, and which messages they receive.

When you open a stack file in Revolution, all its stacks are loaded into memory and kept resident until you purge the file. (Use the destroyStack property to remove files automatically from memory when you close them.) This makes for much faster access, since stacks are pre-loaded in memory and Revolution doesn’t need to access the disk when you go to another card.

This also means stack files cannot be too large to fit into memory. If you have a large collection of data in your stack, you may want to split it into multiple stack files, or keep media, such as pictures, videos, and sounds, in external files and display these items in referenced controls. (Files in referenced controls are loaded into memory only when you go to the card the control is on.)

The MacOS date routines (and therefore HyperCard) use midnight, January 1st, 1904 as the “beginning of time”. The seconds function counts from this moment. However, since Revolution is cross-platform, it doesn’t use the MacOS-specific date. Instead, time begins at midnight, January 1st, 1970 GMT. This will affect your stacks if you store or manipulate the value of the seconds function.

The ticks function in Transcript goes back to the start of the eon, not to the last time the system started up.

The date and time functions and the convert command always use the U.S. format for dates and times.

Revolution is pickier than HyperTalk about certain minor errors:

  • The use of the word “the” before property names is more strictly enforced.
  • Function names and property names cannot be used as variable names.
  • Literal strings must be enclosed in double quotes. (You can set the explicitVariables property to true to catch unquoted literals when you close the script.)
  • The do command and value function may require strings to be more strictly enclosed in double quotes, and values to be enclosed in parentheses.

Revolution does not assume either the card or background layer when referencing buttons and fields. In other words, you can specify button myButton or field ID 22 and Revolution will find the button or field either on the card or in a group, without needing to be told which. Paint and graphics:

It’s easier and more efficient to use graphic objects instead of paint images for such things as lines and boxes. Instead of using the line tool (which is a paint tool), you’ll do this by creating a new graphic, either in a script or using the “New Control” item in the Object menu. You can then set the new graphic’s style property to specify what shape it should be.

Graphic objects can be easily moved, resized, and changed, either by setting the object’s properties in a handler or by using the Properties palette. You should use images only for complex pictures (such as photos) that go beyond simple shapes. Using send instead of idle handlers:

At times you will need to execute one or more commands periodically. In HyperCard, it is common practice to place such commands in an idle handler. In Revolution, you can instead use the send command to send a message at a specified future time. This means you can place the commands to be executed in a handler, and at the end of that handler, send a message to execute it again after the delay you specify. This example handler beeps once per second:

 on annoyUser
  beep
  send "annoyUser" to me in 1 second
end annoyUser

This approach offers greater efficiency, since Revolution does not need to continually execute an if/then statement in an idle handler to determine whether enough time has passed.

When you need to monitor the mouse’s position, it is usual in HyperCard to use a mouseWithin handler that executes continually while the mouse pointer is within the object. In Revolution, it is more efficient to use a mouseMove handler in the object’s script to track the mouse’s motions while the pointer is within the object.

In most applications, the active window holds the current document, and menu commands operate on the active window. In Revolution, because you can open stacks as palettes and dialog boxes, this is not necessarily the case and occasionally the active window is not the frontmost stack. Use the topStack function and defaultStack property to control which stack is the active window. Pathnames:

In HyperCard, file pathnames use the MacOS convention of separating levels with a colon, and a file path might look like this: “Hard Disk:Folder:File”. Revolution uses the Unix style for pathnames, which uses slashes instead of colons, on all platforms to simplify writing cross-platform handlers. The same file path, written Revolution-style, looks like this: “/Hard Disk/Folder/File”. Revolution translates slashes to colons in pathnames, so if you have a file called “And/Or”, in a Revolution pathname it becomes “And:Or”.

Absolute paths begin with a slash and relative paths begin without a slash. The folder that contains the current folder is indicated in a relative path by “../”. For example, if the current folder is “Folder 1”, the path to “Folder 2” on the same level is written “../Folder 2/”. Visual effect quoting:

Transcript’s visual effect command does not allow the visual effect name to be enclosed in quotes. The statement visual effect “barn door” does not work in Revolution, though it works in HyperCard. The marked/mark property:

In HyperTalk, the property that specifies whether a card has been marked for further processing is called the “marked” property. In Transcript, this property is called the mark.

Pressing the Enter key doesn’t automatically close the current field. To have the Enter key close a field, insert an enterInField message into an object in the field’s message path:

 on enterInField
  select empty -- closes the field
end enterInField

In Revolution, fields whose sharedText property is false can’t have shared text. Instead, set a custom property for the field. Window appearance properties:

In HyperCard, you use the “show titlebar” and “hide titlebar” commands to control a window’s title bar. In Revolution, you set the stack’s decorations property to control its title bar (and also its zoom box and collapse box).

Since resources are a MacOS-only service, for cross-platform compatibility Revolution uses images to display cursors and icons. You can either hide these images or create a substack in the same file as your main stack to hold them.

In Revolution, a stack’s location designates its center, not its top left corner