Port from HyperCard to Revolution?

This article is 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.

Revolution for Hypercard Developers

This article is 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.

Moving From HyperCard to Revolution

As an experienced HyperCard developer, you’ll find Revolution’s object model and development environment very familiar. 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.

There are some differences between HyperCard and Revolution that you should understand in order to make the port as easy as possible from HyperCard to Revolution.

Stacks and windows

In HyperCard, each window is a stack, and each stack is a file. In Revolution, each window is still a stack, but a stack file can contain multiple stacks, so you can create a multi-window application in a single file.

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.

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

Backgrounds and groups

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. However, it’s important to remember that groups are not backgrounds. In HyperCard, every card belongs to a background. In Revolution, however, cards can exist without having any groups, and the groups belong to the cards they’re on rather than vice versa.

Menus

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. (This is the normal location for menu bars on Unix and Windows systems.)

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.

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.

Revolution Enhancements

Many of the features HyperCard developers have called for over the years are included in 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:

Chunk operations

Theis among operator tests whether a specified chunk exists in a string:

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

Revolution containslineOffset,itemOffset, andwordOffset 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

Unix-style regular expressions

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.

Direct URL addressing

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"

Manipulating the message path

Revolution supports HyperTalk’sstart using command to let you use other stacks as script libraries. You can also use theinsert 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.

Custom properties

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.

Inheritance of text appearance

You can set thetextFont,textSize, andtextStyle 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 youset the textFont of a stack to Helvetica, all the objects in the stack will automatically switch to Helvetica (unless you’ve specified an indepedenttextFont for them).

Binary data and nulls

In Revolution, you can read and write binary files which may contain null characters, ASCII zero. (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.

Associative arrays

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.

Scan the Revolution Dictionary to explore new language terms.

The Revolution Development Environment

Revolution’s development environment is similar to HyperCard’s. 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 and HyperTalk

Revolution’s scripting language is called Revolution. Since HyperTalk is one of Revolution's ancestors, almost all your knowledge of how to write HyperTalk code will translate easily.

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.

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 Revolution 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. Refer to the Revolution Dictionary in the Revolution documentation for complete language information.

Importing HyperCard Stacks

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

  1. In HyperCard, compact the stack.
  2. 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’sHCStack property to true. Check this property if you need to know whether a stack originated in HyperCard.

An imported stack’sHCAddressing 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. ThedynamicPaths 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. Here are the most common gotchas and some useful tips:

Custom properties instead of hidden fields

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.

Overriding built-in commands and functions

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 acloseCard handler to save the current stack automatically when you go to another card if you want to emulate the HyperCard automatic save.)

Inserting handlers in the Home stack

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.

Everything in memory

When you open a stack file in Revolution, all its stacks are loaded into memory and kept resident until you purge the file. (Use thedestroyStack 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.)

Dates, times, and the start of the eon

The MacOS date routines (and therefore HyperCard) use midnight, January 1st, 1904 as the “beginning of time”. Theseconds 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.

Theticks function in Revolution goes back to the start of the eon, not to the last time the system started up.

Thedate andtime functions and theconvert command always use the U.S. format for dates and times.

Language parsing

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.)
  • Thedo command and value function may require strings to be more strictly enclosed in double quotes, and values to be enclosed in parentheses.

Object references

Revolution does not assume either the card or background layer when referencing buttons and fields. In other words, you can specifybutton myButton orfield 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’sstyle 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 thesend 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.

Polling the mouse position

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

Window layers

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 thetopStack function anddefaultStack 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

Revolutiont’s visual effect command does not allow the visual effect name to be enclosed in quotes. The statementvisual 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 Revolution, this property is called themark.

Closing fields

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

on enterInField
select empty -- closes the field
end enterInField

Shared text fields

In Revolution, fields whosesharedText 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).

Cursors and icons

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.

Stack location property

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

About LiveCode

Related LiveCode