![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/all/themes/custom_front/images/you_are_here_red.gif)
![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/default/files/beta-site.gif)
|
Volume Number: | 6 | |||
Issue Number: | 7 | |||
Column Tag: | Programmer's Workshop |
Commando Programming
By W. G. Powell, Salt Lake City, UT
Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.
With its combination of a programmable text processor, a mouse-based interactive text editor and a general command interpreter, the MPW shell is one of the most powerful and flexible development environments available on any computer. One feature of this environment is particularly Macintoshish: the ability to replace the text of a shell command with a more graphic modal dialog. The Commando tool, supplied with MPW version 2.0 and later, controls such dialogs according to behaviors specified by the programmer in resources of type ‘cmdo’.
In this article I’d like to introduce some tricks and techniques I’ve found useful for building these commando interfaces. Since commandos are fairly flexible, some examples presented here use commando as a means of convenient data entry beyond the direct application to command generation. A previous article on the MPW shell showed the effects of launching applications from within shell command scripts; in this one we’ll see the used of Commando from within shell scripts.
Commands via Commando
The conventional use of commando is to replace the typing of a command and its arguments with a more user-friendly graphical equivalent. The commando dialog is an intuitive way to illustrate the modes of an action and the choices available to the user. Commando interfaces are helpful in two ways. First, presentation of all the options on the screen relieves the user of the burden of memorizing syntax and options. Second, the use of commando dependency rules (discussed later) can increase the correctness and success of commands initiated by the user, thereby enhancing the user’s productivity.
Commando interfaces are available for the commands built into the shell application itself. A commando interface may also be added to any MPW tool or shell script (TEXT) file with ‘cmdo’ resources. A small shell script command with a few simple options will serve as a basic example of designing commando interfaces.
Example 1: A Scratch File Generator
Shell scripts of moderate complexity frequently require scratch files or windows for intermediate results and working space. As I wrote more shell scripts, I became less and less confident that I could code unique scratch file names into scripts, and feared I would ultimately overwrite some critical file by accident. A command which opens a scratch file and guarantees that it has a unique name was the obvious solution. The shell script “NewTempFile”, shown in the listings which follow, performs this function.
The command and its behavior
The NewTempFile command script works together with a few supporting facilities. A special directory is created, where all temporary files will reside. A shell variable defined in the MPW “Startup” or “UserStartup” scripts maintains the path to this directory. By convention, a temporary or scratch file is no longer needed when the command which creates the file terminates. When the user Quits the MPW shell, no commands are still active, so the “Quit” script contains commands to delete the contents of the temporary file directory. The appropriate commands are shown in the listings.
The first half of the script file for the NewTempFile command is a loop which reads, interprets and checks the command line arguments. The second half of the file is a loop which generates a unique file name and opens the file. The file name is formed by appending a number to a base name. A default base name is supplied unless the user provides an alternative as a command line argument. The first trial name is created by appending the count of files in the temporary file directory to the base name. If a file with that name already exists, a new trial name is formed by incrementing the number part by one. The incrementing process continues until an unused name is found. This method has always worked quickly for me in practice, but pathological cases exist which can cause a large number of trials before success. Readers are welcome to try better schemes.
Several command line options can be used to control the behavior of the command. As mentioned earlier, the user can specify a base name for the file on the command line. Normally, when a unique name is successfully found, it is opened as the active window; the -t option on the command line causes the file to be opened as the target window. NewTempFile usually produces no standard output, although error messages (if any) go to the Standard Diagnostic stream. Options -e or -q will echo the name of the new file on the Standard Output stream. Option -q will quote the name if it contains spaces or shell special characters, -e never quotes, and at most one of -e and -q may be specified (you can’t have things both ways!).
Examining the script in detail, one may wonder why I test the file name with the “Exists” and then use “New” to open the file when a name is found. Since the “New” command must also test for the existence of the file anyway, and returns a nonzero shell {Status} if the file exists, it looks like I am doing the same test twice. Actually, my first attempt at writing NewTempFile tried the command “New” with each trial name, using a {Status} value 2 to indicate a need for incrementing and trying again. Careful testing uncovered the flaw in this technique. Under “ordinary” use the script worked fine, but a test where I place the command inside an infinite loop failed. The “New” command returns a {Status} value of 2 when the command fails because a file of the same name already exists, but it also returns a value of 2 when too many windows are already open. Once I opened enough windows to reach my system’s limit, NewTempFile became an inefficient code to count to very high numbers instead of a convenient way to open new files. Thus the slightly more redundant, but less ambiguous test with “Exists” was added.
I digress to present this poignant example of one of my failures because it illustrates a common problem with devising shell command scripts. The description in the MPW reference manual of command status results is quite terse, and sometimes does not make clear all the cases which may produce the particular status value. The nature of the status results must be fully defined when they are used to control a script. As in any software development, successful scripting requires careful validation through testing.
The -e and -q options illustrate another useful detail of shell programming worthy of a short digression. After calling NewTempFile within a script, we will usually want to get the name of the new window for use in subsequent commands. Here are two code fragments that set the variable {WName} to the name of a window opened by NewTempFile.
#1 Set WName ‘NewTempFile -q ‘
or
#2 NewTempFile If {Status} != 0 Echo “Error”>>Dev:StdErr Else Set WName “{Active}” End
If NewTempFile fails, the first example sets {WName} to the empty string, and the second does not set {WName} at all. These two code snippets illustrate what I call the MPW Uncertainty Principle. You can use the standard output of a command in a script (via command substitution), OR you can use the status value returned by the command, but you can’t use both. In an article on MPW scripting in MacTutor [April 87, p. 37], F. Alviani presents several shell scripts with constructs like:
#3 Set SomeVar “`Request ‘some text’`” If {Status} != 0 etc.
The intention was apparently to use the “If” statement to take different actions depending upon whether the user hit the “OK” or “Cancel” button in the “Request” dialog. In reality, if the Request is cancelled, there is no standard output and the {Status} variable is set to value 2. Then the set command (successfully) sets the variable {SomeVar} to the empty string. Finally, the {Status} of 0 returned by the successful “Set” command is the value tested in the “If” expression. So the “If” sees a status of 0 no matter what status value is returned by the “Request” command. This script used the standard output of “Request”, so it couldn’t use the status of the “Request” command.
Now that we have a command, and have defined its command line arguments, let’s look in detail at the construction of its commando interface.
The command’s commando
In discussing the commando interface for NewTempFile, I will refer frequently to the Rez input for the ‘cmdo’ resource (file NewTempFile.Cmdo.R in the listings). This discussion will lead sequentially through the Rez code, so you may want to mark the page and follow along there. The appearance of the resulting dialog is shown in Figure 1.
The dialog of Figure 1 will be generally familiar to everyone who has already used the Commando tool. The dialog is divided into three rectangular regions. The uppermost “options” rectangle contains the programmed controls particular to this command and defined in the ‘cmdo’ resource. The middle rectangle shows the equivalent command and argument text that fits the options selected by the user in the dialog; this text is changed automatically by Commando as the user changes controls in the options area. The third rectangle, labelled “Help”, shows descriptive text about the command and its options; the help text is changed to describe the appropriate options as the user clicks on the various controls. The placement and action of the controls, the command line options corresponding to the various controls, and the help text are all summarized in the ‘cmdo’ resource.
The Rez input for the ‘cmdo’ resource begins with the type and resource ID number of the resource. The specific resource data are then contained within braces. The resource description begins with an integer representing the height of the dialog box in pixels, and the default string of help text that appears in the Help box when no controls are being clicked by the user. The dialog box width is fixed at 480 pixels and the MPW Reference Manual recommends that the height be less than 295 pixels to insure visibility on the original size Macintosh screen. Since only the programmable controls in the options area vary in size, the options determine the necessary size of the dialog window. Letting h represent the height specified in the Rez description, the rectangle drawn around the options area in the dialog is {7, 5, h - 105, 475}. After the default help text, another set of braces encloses input for the variable number of items in the options area of the dialog.
The first item in the NewTempFile commando options is a set of radio buttons, which appear in the upper left of the dialog in Figure 1. This pair of radio buttons allows the user to toggle between causing the temporary window to open as the active or target window. For each button in the set, the Rez input lists the bounds rectangle for the control and its label in the dialog window, the label text to show in the dialog, the command line option corresponding to the control (if any), the help text explaining the control and its option, and the initial setting of the control. Note that when the button labelled “Target” is selected, the -t option is added to the command line, but when the “Active” button is selected, no option is added since this is the default case. Entering the empty string in the command line option field for this button signifies the absence of corresponding text on the command line. The behavior of radio buttons follows Apple’s Human Interface Guidelines.
The second item in the Rez input is a type called RegularEntry. This produces the editable text box in the dialog for entering an alternative base name for the files. The specific data required to build the commando dialog is similar to the radio buttons: Separate bounds rectangles for the label and the text edit box, the text of the label in the dialog, option text that must precede the user-entered text on the command line (if any), a default entry to ignore (if any) and a string of help text explaining the item and its effect on the command. If the user enters text with spaces or shell special characters, the text is automatically quoted on the command line. The behavior of regular entry items is similar to Text Edit items in a modal dialog. Note that RegularEntry items will never word-wrap. Therefore RegularEntry items need never be more than one line of text high (although the similar scrolling list item called MultiRegularEntry must be two or more lines high).
The third and fourth items in the Rez inputs are type CheckOption, which produce the check boxes seen in the upper right of Figure 1. These check boxes correspond to the -e and -q options for echoing the file name generated by the NewTempFile command. The information in the Rez input is quite similar to that required for a set of RadioButtons, but inexplicably must be listed in a different order. As with radio buttons, the input lists the bounds rectangle of the check box and its label, the text of the label, the text of the corresponding command line option, the help text describing the effect of the control, and the initial setting. The initial setting, defined by the constants “Set” or “NotSet” indicates whether the item is checked or unchecked when the dialog is first drawn. The command line text of the item is only added to the command when the user changes the state from its initial setting. This can be confusing to the neophyte commando writer. The initial setting of radio buttons also works this way.
Another dimension of the commando interface is also illustrated by the two CheckOption items: control dependency. The first field in each control item description is used to define a dependency of the current control on the states of other controls. Controls in the commando dialogs may be enabled or disabled depending upon the enable/disable status and settings of other controls in the dialog. A dependent control defines its dependency via a logical OR or logical AND of the states of a list of other items. The items are numbered according to their order in the Rez description. The check boxes in the NewTempFile Rez input are items 3 and 4; item 3 depends upon item 4 and vice versa. The negative signs of these items in the dependency lists indicates a logical negation of the dependency on that item. Thus item 4 is enabled any time item three is NOT both enabled and checked. If item 3 is enabled and checked, item 4 becomes disabled. This dependency allows the user to choose only one of options -e and -q, but not both simultaneously. The dependency in this case prevents the user from presenting an illegal combination of options.
The fifth and sixth items present pop-up menus to control the redirection of the Standard Output stream and the Standard Diagnostic stream respectively. The only choices by the programmer with these items is whether to include them and the position in the dialog window. The behavior of these items is the same every time they appear, so no further description is necessary. The NewTempFile example shows the Standard Output item is dependent upon a choice of one of the options -e or -q. Results are written on standard output only when these options are used, so the control is only relevant when one of the corresponding check boxes has been selected. This dependency prevents the user from making unnecessary (although legal) choices.
The final two items, type TextBox, are used to draw the labelled boxes around the radio button set and the redirection controls. Graphic elements are the strength of the Macintosh interface, and the Commando documentation encourages the use of labelled or unlabeled boxes, text in any typeface and style, icons and pictures to increase the visual clarity of the Commando interface. The description of the ‘cmdo’ Rez input allows for convenient inclusion of these graphics.
This small example covers most of the basic technique in programming the Commando interface. Two features appear to distinguish good commando interfaces (and other dialog interfaces for that matter). First is good graphic design, with related elements grouped together, and less related elements differentiated by position and surrounding white space. Second is the use of control dependency to lead the user to correct choices.
Commando for Data Entry
The MPW Shell provides a number of facilities and tools for prompting the user for information or choices: Alert, Confirm, GetFileName, GetListItem and Request all serve this function. The Commando tool is sufficiently flexible that I now include commando dialogs as another mechanism for prompting the user from within menu choices and scripts. I find this usage results in a somewhat different mode of programming. When I want a commando dialog as a data-entry device, I will usually design and program the ‘cmdo’ resource first, and then write a special shell script to capture the results from the dialog. Since the only output Commando generates is executable command lines, a particular shell command script must always be written to hold the ‘cmdo’ resource. Shell scripts which will only be accessed through the commando interface can often be somewhat simpler than those meant to be true commands. In particular, because the commando dialog will always present options in the same order, simple position-dependent interpretation of the arguments is possible.
In his helpful article on MPW scripting [April 87, p. 37], F. Alviani presented a number of shell command scripts which prompted the user for necessary data and then wrote correctly formatted input for the resource compiler, Rez. Since Rez syntax is fairly intricate this is a useful application. The Alviani scripts used the “Confirm” and “Request” commands to prompt the user for input; I present here some alternative scripts which use the Commando interface as the facility for the input of necessary parameters.
The script for a ‘WIND’ resource shows many features common to all the Rez formatting scripts, and serves as the first example. The script for a ‘STR#’ resource is representative of special problems encountered with resources having a variable number of entries (other such resources are BNDL, PAT#, MENU). The ‘STR#’ example shows the use of a Commando interface from within a running shell script file.
Example 2: Rez Formatter for ‘WIND’
The shell script to take command line arguments and build correctly-formatted window resource input for the Rez tool is shown as file “RezC.WIND” in the listings. The Rez input for the Commando interface for this script is shown in the listings as file “RezC.WIND.Cmdo.R”. My intention with all these Rez formatters is that they will only be operated through their commando interfaces. I normally access the Rez formatters via a menu selection. If the menu item is created by a command like
#4 AddMenu Rez WIND ‘RezC.WIND ’
the ellipsis character in the command ensures the activation of the Commando dialog when the menu item is selected.
Commando Nested Dialogs
Figure 2 shows the Commando dialog (and its nested subdialogs) for the ‘WIND’ Rez formatter. A commando item not encountered in the earlier example appears in the main dialog for the ‘WIND’ command: the NestedDialog. This item appears as a rounded push button in the dialog, and it causes a nested commando subdialog to appear in front of the main commando dialog. The subdialog contains custom-programmed controls which can affect command line arguments and has an appearance identical to the main commando dialog, with options, command line text, and help text all shown. The nested dialog push buttons do not generate command line text; only the controls within the nested dialog affect the command line.
Rules regarding items become more complicated with nested dialogs. First, items in a commando dialog may be dependent only upon other items in the same dialog (whether that dialog is the main one or a subdialog). Item numbering for dependency expressions restarts with the first item in each subdialog. When the button for activating a subdialog shows a dependency, activation of the subdialog for user input is the only activity which is disabled. In particular, if the controls in a nested dialog are set to produce command line text, that text remainson the command line even if the nested dialog button is disabled. The order of command line arguments from nested dialogs is the same as the absolute order of the corresponding items in the ‘cmdo’ resource description. The order of the nested dialog button itself has NO effect on the order of command line argument text.
Nested dialogs have several uses. A large number of closely related choices may be collected into one nested dialog. Nested dialogs can remove less important or subsidiary choices from the main dialog, thereby minimizing the user’s attention on those items. In the ‘WIND’ example, there is a nested dialog for selection of resource attributes (Figure 2), one for standard and diagnostic output redirection (not shown) and one for selecting the type and appearance of the window (Figure 2). Each of these clearly contains a subset of closely-related choices too numerous to fit together on the main dialog.
Nested dialogs are most convenient when they contain rarely needed choices. The command line text related to the initial state of nested dialog controls appears even if the subdialog is not accessed by the user. The user need only access the nested dialog to change the initial state. The initial state of controls in a subdialog should therefore be the most common choice (see the defaults shown in the subdialogs of Figure 2). At the very least for user friendliness, the initial settings should ensure that a “legal” combination of options will result if the user does not access the dialog before executing the command.
Common elements
The upper portion of RezC.WIND’s main commando dialog prompts for elements common to all resources: the resource ID number, the resource attributes and resource name. Since these elements will recur in commandos for all Rez formatters, the Rez text for these commando items is collected into a separate file named “CmdoReztStart.R”. Reproducing these commando elements with identical appearance in several Rez formatter scripts the becomes a simple matter of a Rez preprocessor #include statement. The two text edit boxes and two nested dialog push buttons at the top of the main commando dialog of Figure 2 (and Figure 3) are contained in this include file. Also the line separating these controls from the ones below is contained in this include file, for a total of five elements. I always put the #include statement for this file before all other items in the commando so the Resource ID item is the first in the dialog. Since a resource ID is always required, I make the resource-specific items dependent upon the user making an entry in this first item. This dependency emphasizes the required items.
The nested dialogs corresponding to the “Attributes” and “Redirection” buttons in the include file are always the same, so their contents are also collected into include files. These files are “CmdoReztAttr.R” and “CmdoReztRdir.R” respectively. These files must be included in a commando description file as the second and third dialogs respectively (as with control items, multiple dialogs are numbered in order of appearance in the ‘cmdo’ resource). Resource-specific nested dialogs are placed as dialog 4 and later. See the RezC.WIND.Cmdo.R listing for the use of these include files.
Another need which occurs frequently, but not in all Rez formatters, is a way to enter Quickdraw rectangles. Resource types ‘ALRT’, ‘CNTL’, ‘DITL’, ‘DLOG’, ‘nrct’ and ‘WIND’ all need various bounding rectangles. On the left side of the main commando dialog for ‘WIND’ resources is an entry area for the window’s rectangle. This group of four RegularEntry text edit items and a bounding TextBox is collected into file “CmdoRect.R” for inclusion into various ‘cmdo’ description files by the Rez preprocessor. Unlike the earlier examples of include files however, some of the information needed to complete the description of the five included items is not known until the compilation provides a context. The including file provides this context by defining Rez macros prior to including the file containing the Rect items. The position of the items in the dialog is set by defining the top left corner of the text box in macros RTop and RLeft. The title in the text box is defined with macro RTit. The rectangle entry area can be made dependent upon other controls by providing a control list in macro RDef. This method is illustrated in the WIND example: the necessary macros are defined in file “RezC.WIND.Cmdo.R” just prior to including file “CmdoRect.R”. Perusal of the listing of file “CmdoRect.R” should provide a clear example of the use of these macro definitions in item descriptions.
Structuring dependency
I arrange the item dependency in these commando interfaces with some distinct goals in mind. First, the dependency rules are set up to prevent the user from presenting incomplete or illegal inputs. This uses the dependency processing of the Commando tool itself instead of adding more conditional tests for correctness in the scripts that process and format the data. Second, where appropriate, dependency is used to produce an ordered hierarchy of input items. The user is prompted to enter or select the more important items before subsidiary choices are made available. The first level of the hierarchy in the Rez formatters is dependency of many items in the dialog on the resource ID number (which is always required).
The button in the lower right of the Commando dialog terminates the Commando and executes the Commando-generated command line. This button may be made dependent upon other items in the dialog by using an item of type “DoItButton”. The Rez formatters insure that the DoItButton is only enabled when a valid combination of options appears on the command line. In the case of the ‘WIND’ formatter, the DoItButton is not enabled until all four elements of the window rectangle have been entered. The window rectangle items in turn are not enabled until the resource ID has been entered. The other options in the commando are always in a valid state, and the DoItButton is not dependent upon them. The logic in the ‘WIND’ and ‘STR#’ examples given here are fairly simple, but more complicated logical dependencies can be built up using “Dummy” items that have dependency, but no visible appearance and no command line text. The MPW documentation provides adequate discussion of dummy dependency. The scripts and commandos for type ‘MENU’ show a more complicated dependency logic and use “Dummy” elements. These are included in the listings.
The RezC.WIND script
The command script containing the Commando is not elegant and offers no scripting features of special interest. It merely tests the arguments, in the order defined by the Commando’s command line text. The formatted text input for Rez is written to the Standard Output stream. The logic is simple because the Commando dependency rules have taken the place of many tests for correctness or consistency of input.
Example 3: Rez Formatter for ‘STR#’
Some resources contain a lists of information of variable length. The archetype of this sort, the string list, could (don’t try this at home kids) contain up to 10’s of thousands of strings. The data to build a string list resource may be quite extensive, so it will not be too convenient to try to pack it all onto one command line.
My solution in the case of this type of resource is to invoke a commando within a loop in the command shell file. Figure 3 shows the main commando dialog that prompts for the resource ID and attributes and the first string, and a commando dialog for a subcommand invoked an indefinite number of times for entering subsequent strings. The ‘STR#’ formatter script is file “RezC.STRlist” and the corresponding commando interface is described in the Rez input file “RezC.STRlist.Cmdo.R”. The command script “RezC.STRlist.more”, containing the commando resource described in file “RezC.STRlist.more.Cmdo.R”, is executed from a loop in file “RezC.STRlist”.
Invoking Commando within scripts.
We saw an example earlier of a menu choice which activates the commando interface for a command. A commando is invoked just as simply within any shell command script. An ellipsis character ( ) is added to the command line in the script file. At the appropriate point in the executing script, the Commando tool is activated. When the user completes the input and executes the commando’s command line, that (nested) command is performed. The enclosing script then continues to execute as if the ellipsis-bearing command had been a normal command. The only important precaution is to insure that the outer shell script (the one which invokes the commando) has a proper behavior when the user clicks the “Cancel” button in the nested command instead of the “Do It Button”.
When processing input of indeterminate length, there must be a way to tell the script when all the input is complete. One way to do this is shown in the dialogs of Figure 3. The dialog for another string to add to the string list resource also contains radio buttons to use when the input is complete. The default radio button is the one labelled “More strings”. When this button is selected, the “RezC.STRlist” script will process the current string and then repeat the dialog for more input. If the “Last string” button is selected, the string in that dialog is processed, and the script exits the loop without prompting for further input with the commando dialog. If the third “Already done” button is selected, it means that the input was completed previously, the script exits the input loop and the string entered in the current dialog is NOT added to the string list. Selecting Cancel instead of the Do It button does not add a string to the string list, but the dialog will reappear for more input. If the RegularEntry field for the string is left blank, an empty string is added to the string list.
Output redirection is affected by the use of a commando inside a script. When the ellipsis character appears on a command line, the commando is invoked to prompt for command line arguments. Any arguments in the command line with the ellipsis are ignored. This includes arguments redirecting input and output. Suppose the following command line appears in a script, and the script is writing Standard Output to the active window.
#5 ACmd >>”{Target}”
The intention is to append to the target window the output of command “ACmd” (using options the user provides in the commando dialog). However, since the commando might include a redirection control, the redirection to the target window on the command line is ignored. If redirection is not selected or not available in the commando dialog, the output of this command goes to the standard output stream, following any redirection of the standard output of the enclosing script file. The desired redirection can be programmed by using an additional nesting level of command file. In the original outermost script file, replace the ACmd command line with
#6 BCmd >>”{Target}” #no ellipsis.
BCmd is a simple script containing only the following commands.
#7 Set Exit 0 ACmd Set BStatus {Status} Exit {BStatus}
The addition of another level of nested script provides the desired redirection and returns ACmd’s status to the outer calling script if needed. The scripts and commandos for the ‘MENU’ Rez formatter use this redirection technique while collecting the item enable flags.
Miscellaneous Notes & Bugs
Usually an entire coupled set of radio buttons in a commando dialog is a single item in the commando resource. The MPW manual tells how to make items dependent upon a single button in the set, by packing a button selection into the 4 high order bits of the item number. Actually, only the first seven buttons (low 3 bits of high 4) in a radio button item can be individually recognized using this technique.
Hidden dialog items, located outside the window rectangle of the dialog, can be useful in some commando interfaces. Suppose for example that we want to toggle between two command line options (say -op1 and -op2) using a single check box. Normally a check box can only turn a command line option on or off, but a dependency relation with a hidden radio button produces the desired effect.
/* 8 */ /* Item X */ NotDependent {}, CheckOption { NotSet, /* inside the window */ {30,30,46,100}, “Label text”, /* Command line option */ /* Use when checked */ “-op2”, “Help text” }, /* X is Item Number of check box */ OR {{ X }}, RadioButtons {{ /* Hidden outside window */ {800,800,816,816}, “Label text (never seen)”, /* Command line option */ /* Use when unchecked */ “-op1”, NotSet, “Help Text (never seen)” }},
If the two toggling options must be in the same position on the command line, be sure the two items are adjacent in the ‘cmdo’ resource, as shown above.
One minor behavior of the commando dialog varies from standard dialog behavior as described in the Apple Human Interface Guidelines book. The published guidelines say the outlined default button in a dialog should respond to the Return or the Enter key on the keyboard. The default button in the commando dialog (the DoIt button) responds to the Enter key. The return key causes the insertion point to jump from edit box to edit box (like the tab key) rather than activating the default button. This is consistent with the behavior of text windows in the shell, but contrary to standard dialog behavior. Another human interface standard bites the dust.
This article was written using MPW version 2.02. This version is still recommended for users with small systems, but the current version (as of this writing) is 3.0. The information in this article applies to both versions. The syntax for some of the resources in the type definition files provided with MPW have evolved with each version of MPW. In particular, the description of the SIZE resource is incompatible between the two versions. The Commando tool delivered with the MPW 3.0 system has a commando editor; it cannot be used to create cmdo resources, but can edit the commando dialogs after the resource is built with Rez.
The commando tool supplied with version 3.0 may not work when the name of the command contains spaces. The command name is apparently not quoted for the shell by the commando tool. The command generated by commando can be written to a window using command-option keys while clicking the commando dialog’s DoIt button however, and quotes added manually. I do not recall having seen this problem with MPW 2.02 but I don’t have that version handy to check.
Conclusion
The Rez formatters, using commandos for data entry, are the most convenient way I have found to enter most of the standard resources. Figure 4 shows some of the variety possible. Graphic resources like icons, patterns and pictures are better handled by a graphic editor like ResEdit of course. It is also much more convenient to build the dialog item lists graphically using ResEdit. The one resource which cannot be written conveniently by ResEdit or by my Rez formatters is unfortunately that for a commando interface. The MPW Reference manual suggests designing the graphics of a commando interface as a dialog item list via the DITL editor in ResEdit, then decompiling and editing the ‘DITL’ resource to produce the Rez input for the ‘cmdo’. An alternative has become available from a surprising source: the dialog editor supplied with the new version of Microsoft Excel handles cmdo-like items such as text boxes and scrolling lists, and saves the user’s graphic design as text on the clipboard.
Figure 4. More sample commandos.
The Microsoft dialog editor allows the building of commando interfaces in a fairly convenient two-step process. A shell script prompts for the usual resource ID and attributes of the ‘cmdo’, and then launches the Dialog Editor (as discussed in MacTutor Jan. 88). The user designs the appearance of the options area of a commando dialog, then quits the editor. When the shell resumes, it takes the item information and writes the equivalent Rez input. All items at this stage have no dependency. In the second step, the user edits the dependency of the items manually. The process can be repeated for subdialogs. I’ll leave the implementation of such a system as an exercise for the interested reader.
However you build them, commando interfaces bring MPW shell commands into line with Apple’s Human Interface Guidelines: the commando interface presents choices to the user, rather than requiring the user to memorize and present commands. Commandos designed with the user’s needs in mind can actually increase productivity by emphasizing the important choices, and preventing inconsistent or incorrect choices. I guess Commando is called “Commando” because it helps to bring the Macintosh “revolution” to command line shells.
Happy Commandoing!
Listings ###NewTempFile -- Open a window on a new temporary file. ###W. Powell, 1988 ###Automatically insures unique file names. Set Exit 0 Set TargMode 0 Set EchoMode 0 Unset BaseName Set NameIn 0 Set ErrGen 0 # Check calling arguments If {#} > 3 Echo “### NewTempFile -- bad arguments” >>Dev:StdErr Echo “### NewTempFile [-t] [-e | -q] [basename] “ >>Dev:StdErr Exit 1 End # Use the arguments If {#} > 0 For NewArg In {“Parameters”} If “{NewArg}” == “-t” Set TargMode 1 Else If “{NewArg}” == “-e” If {EchoMode} Echo “### NewTempFile - only one of -e, -q allowed” >>Dev:StdErr Echo “### NewTempFile [-t] [-e | -q] [basename] “ >>Dev:StdErr Exit 1 Else Set EchoMode 1 Set Quote 0 End Else If “{NewArg}” == “-q” If {EchoMode} Echo “### NewTempFile - only one of -e, -q allowed” >>Dev:StdErr Echo “### NewTempFile [-t] [-e | -q] [basename] “ >>Dev:StdErr Exit 1 Else Set EchoMode 1 Set Quote 1 End Else If {NameIn} Echo “### NewTempFile -- bad arguments” >>Dev:StdErr Echo “### NewTempFile [-t] [-e | -q] [basename] “ >>Dev:StdErr Exit 1 Else Set NameIn 1 Set BaseName “{NewArg}” End End End End # If basename not specified, use this default If ¬ {NameIn} Set BaseName TEMPzs End Unset NameIn # Note: Directory for temp files defined by variable # {TMP} defined in Startup script Set TmpCnt ‘Files “{TMP}” | Count -l‘ Set TmpCnt ‘Evaluate {TmpCnt} + 1 ‘ #Create a unique new Temporary File Loop # Until unique new file is opened # Trial filename Set uniq “{TMP}{BaseName}{TmpCnt}” # Try to create file If “{uniq}” == `Exists -f “{uniq}” ` # Not a unique name, so # Increment and try again Set TmpCnt ‘Evaluate {TmpCnt} + 1 ‘ Else # Found a good file name, try to open it. New “{uniq}” Set NewStat {Status} If {NewStat} Echo “### NewTempFile terminated” Dev:StdErr Exit {NewStat} End If {TargMode} Open -t “{uniq}” End If {EchoMode} If {Quote} Quote “{uniq}” Else Echo “{uniq}” End End Break # out of this loop End End # Successful, Window is open Exit 0 ### End file NewTempFile ############################## /* File: NewTempFile.cmdo.R */ /* Rez input for Commando interface for NewTempFile command */ #include “Cmdo.r” Resource ‘cmdo’ (200) { { 270, /* dialog box height */ “NewTempFile opens a window on a scratch file with a unique name”, { NotDependent {}, RadioButtons { {{35,35,55,160},”Active Window”, “”, Set, “Open new temporary file as the active window”, {55,35,75,160}, “Target Window”, “-t”, NotSet, “Open new temporary file as the target window”} }, NotDependent {}, RegularEntry { “Base name for file:”, {85,50,105,180}, {85,183,105,430}, “”, keepCase,””, “File name for temporary file; a number will be concatenated.” }, Or { {-4} }, CheckOption { NotSet, {30,195,50,445}, “Echo File Name without Quoting”, “-e”, “Cause name of temporary file to be written to Standard Output; don’t quote special characters” }, Or { {-3} }, CheckOption { NotSet, {50,195,70,445}, “Echo File Name with Quoting”, “-q”, “Cause name of temporary file to be written to Standard Output; quoting special characters” }, Or {{3,4}}, Redirection { StandardOutput, {117,150}, }, NotDependent {}, Redirection { DiagnosticOutput, {117,290}, }, NotDependent {}, TextBox { gray, {115,30,156,450}, “Redirection” }, NotDependent {}, TextBox { gray, {25,30,78,165}, “Open As ” }, } } } ; /* End File NewTempFile.cmdo.R */ ############################################################# ###File: NewTempFile.install ###Supporting facilities needed to use ###MPW Shell Script “NewTempFile”. ###To install the NewTempFile script in your MPW system, ###1. Place the script file “NewTempFile” into ###any directory in the {Commands} search path. ###2. Place the shell script fragments below into ###the standard MPW script files as indicated. ############################################################## ###Place the following lines into the ###“Startup” or one of the “UserStartup” files. #{TMP} - Directory that contains temporary files. Set TMP “{MPW}tmp:” Export TMP ############################################################## ###Place the following lines into the ###“Quit” script file. ###Empty the scratch directory Set OldExit {Exit} Set Exit 0 # Don’t want error messages when no windows open. Close -n ‘Files -f “{TMP}” ‘ Dev:Null Set Exit {OldExit} Delete -y -i “{TMP}” NewFolder “{TMP}” ############################################################## ###Place the following lines into an ###appropriate file for the “Help” tool. - NewTempFile [-t] [-e | -q] [basename] Create a temporary scratch file. Shell variable {TMP}, defined in Startup script, is the directory for new file. -tOpens file as target window (default active window). -e Echo the new file name without quoting. -qEcho the new file name, quoting names with spaces and special characters. Can’t use -q and -e together - ###End File NewTempFile.install ################################################# ################################### ###File RezC.WIND ### Generate Rez input for WIND Resources ### W. Powell 1988 Set Exit 0 Set rid {1} Shift 1 Echo -n “Resource ’WIND’ ({rid}” If “{1}” == “-nms” Set rname “{2}” If (“{rname}” != “”) Echo -n ,””{rname}”” End Shift 2 End If “{1}” == “-t” Set tr {2} Shift 2 Else Echo “### {0} Error: Rectangle args out of order” >>Dev:StdErr Exit 1 End If “{1}” == “-l” Set lr {2} Shift 2 Else Echo “### {0} Error: Rectangle args out of order” >>Dev:StdErr Exit 1 End If “{1}” == “-b” Set br {2} Shift 2 Else Echo “### {0} Error: Rectangle args out of order” >>Dev:StdErr Exit 1 End If “{1}” == “-r” Set rr {2} Shift 2 Else Echo “### {0} Error: Rectangle args out of order” >>Dev:StdErr Exit 1 End Set Vis “{1}” Shift 1 If “{1}” == “-const” Set RefCon “{2}” Shift 2 Else Set RefCon 0 End If “{1}” == “-title” Set Label “{2}” Shift 2 Else Set Label “” End If ( “{1}” == “-sy” ) ; Echo -n “,SysHeap” ; Shift ; End If ( “{1}” == “-pu” ) ; Echo -n “,Purgeable” ; Shift ; End If ( “{1}” == “-lo” ) ; Echo -n “,Locked” ; Shift ; End If ( “{1}” == “-Pr” ) ; Echo -n “,Protected” ; Shift ; End If ( “{1}” == “-PL” ) ; Echo -n “,PreLoad” ; Shift ; End Echo “) {“ Set ProcID “{1}” Set CloseOp “{2}” Echo “t{{tr},{lr},{br},{rr}},tt/* Bounds Rect */” Echo “t{ProcID},tt/* Window Proc */” If “{Vis}” == “-I” Echo “tinvisible,” Else Echo “tvisible,” End If “{CloseOp}” == “-goAway” Echo “tgoAway,” Else Echo “tnoGoAway,” End Echo “t{RefCon},tt/* RefCon */” Echo “t”{Label}”t” Echo “};” Exit 0 ### End File RezC.WIND #################################### /* File RezC.WIND.Cmdo.R */ /* Commando interface to build WIND Rez input */ /* W. Powell 1988 */ /* Rez definitions for Rez-building Commando interfaces */ #include “Types.R” #include “Cmdo.R” Resource ‘cmdo’ (200) { { 285, “Rezc.WIND produces Rez input for a Window resource”, { /* This include file has a standard arrangement of items * common to all resources: ID#, attributes, name, * and redirection of output from the Rezc. script */ #include “CmdoReztStart.R” /* Set up parameters for a Rectangle entry area */ #define RTop 85 #define RLeft 30 #define RTit “Window Rectangle” #define RDep {1} /* This include file has a standard arrangement of edit boxes * for input of rectangles*/ #include “CmdoRect.R” /* other items particular to this case */ /* Item 11 */ OR {{1}}, NestedDialog { 4, /* Dialog number */ {85,250,106,370}, “Window Type”, “Select style of window.” }, /* Item 12 */ OR {{1}}, RadioButtons {{ {80,380,96,460}, “Visible”,”-V”,NotSet,”Make window visible.”, {97,380,113,460}, “Invisible”,”-I”,NotSet,”Make window invisible.” }}, /* Item 13 */ OR {{1}}, RegularEntry { “RefCon:”, {123,250,139,310}, {123,315,139,430}, “”,keepCase,”-const”, “User-defined constant.\nHEX long word.” }, /* Item 14 */ OR {{1}}, RegularEntry { “Title:”, {152,30,168,90}, {152,100,168,440}, “”,keepCase,”-title”, “Title for window.” }, /* Item 15 */ AND {{6,7,8,9}}, DoItButton {}, }, /* Dialog 2 */ /* Include the standard resource attributes dialog */ #include “CmdoReztAttr.R” /* Dialog 3 */ /* Include a redirection dialog */ #include “CmdoReztRdir.R” /* Dialog 4 */ 270, “Select style of window.”, { /* Item 1 */ NotDependent {}, RadioButtons {{ {55,54,71,70}, “”,”documentProc”,NotSet,””, {55,156,71,172}, “”,”dBoxProc”,NotSet, “NOTE: This window type inhibits” “ MultiFinder context switching.”, {55,258,71,274}, “”,”plainDBox”,NotSet,””, {55,360,71,376}, “”,”altDBoxProc”,NotSet,””, {115,54,131,70}, “”,”noGrowDocProc”,NotSet,””, {115,156,131,172}, “”,”zoomDocProc”,NotSet,””, {115,258,131,274}, “”,”zoomNoGrow”,NotSet,””, {115,360,131,376}, “”,”rDocProc”,NotSet,”” }}, /* Item 2 */ NotDependent{}, RadioButtons {{ {140,100,156,210}, “Has Close Box”,”-goAway”,NotSet, “Window has a close box.”, {140,280,156,390}, “No Close Box”,”-NoGoAway”,NotSet, “Window does not have a close box.” }}, /* Item 3 */ NotDependent {}, Box { gray, {135,80,160,400} }, /* Item 4 */ NotDependent {}, TextTitle { plain, {56,71,70,137}, 3,9, “documentProc” }, NotDependent {}, TextTitle { plain, {56,173,70,234}, 3,9, “dBoxProc” }, NotDependent {}, TextTitle { plain, {56,275,70,336}, 3,9, “plainDBox” }, NotDependent {}, TextTitle { plain, {56,377,70,438}, 3,9, “altDBoxProc” }, NotDependent {}, TextTitle { plain, {116,71,130,150}, 3,9, “noGrowDocProc” }, NotDependent {}, TextTitle { plain, {116,173,130,234}, 3,9, “zoomDocProc” }, NotDependent {}, TextTitle { plain, {116,275,130,336}, 3,9, “zoomNoGrow” }, NotDependent {}, TextTitle { plain, {116,377,130,438}, 3,9, “rDocProc” }, NotDependent {}, PictOrIcon { Icon, 200, {20,70,52,102} }, NotDependent {}, PictOrIcon { Icon, 201, {20,172,52,204} }, NotDependent {}, PictOrIcon { Icon, 202, {20,274,52,306} }, NotDependent {}, PictOrIcon { Icon, 203, {20,376,52,408} }, NotDependent {}, PictOrIcon { Icon, 204, {80,70,112,102} }, NotDependent {}, PictOrIcon { Icon, 205, {80,172,112,204} }, NotDependent {}, PictOrIcon { Icon, 206, {80,274,112,306} }, NotDependent {}, PictOrIcon { Icon, 207, {80,376,112,408} }, }, } }; resource ‘ICON’ (200, “documentProc”) { $”FFFF FFFF 8000 0001 BEFF FFF1 A200 0001" $”A2FF FFF1 A200 0001 BEFF FFF1 8000 0001" $”FFFF FFFF 8000 0041 8000 0001 8000 0041" $”8000 0001 8000 0041 8000 0001 8000 0041" $”8000 0001 8000 0041 8000 0001 8000 0041" $”8000 0001 8000 0041 8000 0001 8000 0041" $”8000 0001 D555 5555 8000 0001 8000 0041" $”8000 0001 8000 0041 8000 0001 FFFF FFFF” }; resource ‘ICON’ (201, “dBoxProc”) { $”FFFF FFFF 8000 0001 8000 0001 9FFF FFF9" $”9FFF FFF9 9800 0019 9800 0019 9800 0019" $”9800 0019 9800 0019 9800 0019 9800 0019" $”9800 0019 9800 0019 9800 0019 9800 0019" $”9800 0019 9800 0019 9800 0019 9800 0019" $”9800 0019 9800 0019 9800 0019 9800 0019" $”9800 0019 9800 0019 9800 0019 9FFF FFF9" $”9FFF FFF9 8000 0001 8000 0001 FFFF FFFF” }; resource ‘ICON’ (202, “PlainDBox”) { $”FFFF FFFF 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 FFFF FFFF” }; resource ‘ICON’ (203, “AltDBoxProc”) { $”FFFF FFFE 8000 0003 8000 0003 8000 0003" $”8000 0003 8000 0003 8000 0003 8000 0003" $”8000 0003 8000 0003 8000 0003 8000 0003" $”8000 0003 8000 0003 8000 0003 8000 0003" $”8000 0003 8000 0003 8000 0003 8000 0003" $”8000 0003 8000 0003 8000 0003 8000 0003" $”8000 0003 8000 0003 8000 0003 8000 0003" $”8000 0003 8000 0003 FFFF FFFF 3FFF FFFF” }; resource ‘ICON’ (204, “noGrowDocProc”) { $”FFFF FFFF 8000 0001 BEFF FFF1 A200 0001" $”A2FF FFF1 A200 0001 BEFF FFF1 8000 0001" $”FFFF FFFF 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 FFFF FFFF” }; resource ‘ICON’ (205, “zoomDocProc”) { $”FFFF FFFF 8000 0001 BEFF FEF9 A200 0089" $”A2FF FE89 A200 0089 BEFF FEF9 8000 0001" $”FFFF FFFF 8000 0041 8000 0001 81FF 0041" $”8002 0001 8004 0041 8008 0001 8010 0041" $”8020 0001 8040 0041 8080 0001 81FF 0041" $”8000 0001 8000 0041 8000 0001 8000 0041" $”8000 0001 D555 5555 8000 0001 8000 0041" $”8000 0001 8000 0041 8000 0001 FFFF FFFF” }; resource ‘ICON’ (206, “zoomNoGrow”) { $”FFFF FFFF 8000 0001 BEFF FEF9 A200 0089" $”A2FF FE89 A200 0089 BEFF FEF9 8000 0001" $”FFFF FFFF 8000 0001 8000 0001 8000 0001" $”8000 0001 803F F001 8000 2001 8000 4001" $”8000 8001 8001 0001 8002 0001 8004 0001" $”8008 0001 8010 0001 803F F001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 FFFF FFFF” }; resource ‘ICON’ (207, “rDocProc”) { $”0FFF FFF0 3FFF FFFC 707F FFFE 777F FFFE” $”F77F FFFF F77F FFFF F07F FFFF FFFF FFFF” $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”8000 0001 8000 0001 8000 0001 8000 0001" $”4000 0002 4000 0002 3000 000C 0FFF FFF0" }; /* End File RezC.WIND.Cmdo.R */ /* File CmdoReztStart.R */ /* W. Powell 1988 */ /* Include File to generate commando input for * standard Resource ID and attributes */ /* This file is meant to be included in other Rez files * This file contains 5 Commando control items*/ /* NOTE: The cmdo dialog for resource attributes is in * include file CmdoReztAttr.R The cmdo dialog for redirection is in include file * CmdoReztRdir.R*/ /* Item 1 */ NotDependent {}, RegularEntry { “Resource ID#:”, {20,25,36,125}, {20,127,40,167}, “”, /* No default */ keepCase, “”, “Enter the resource ID number.\nUsually 128 ¾ ID ¾” “32767 (See I.M. I-108).” }, /* Item 2 */ NotDependent {}, NestedDialog { 2, /* Nested dialog number */ {20,190,40,280}, “Attributes”, “Set resource attribute bits” }, /* Item 3 */ OR { {1} }, RegularEntry { “Resource Name:”, {50,25,66,145}, {50,148,66,430}, “”, /* No default */ keepCase, “-nms”, “Enter a name for the resource (optional).” }, /* Item 4 */ NotDependent {}, NestedDialog { 3,/* Nested Dialog number */ {20,300,40,420}, “Redirection”, “Specify output redirection.\n” “Defaults to Active window.” }, /* Item 5 */ NotDependent {}, Box { Black, {73,45,74,410} }, /* End of file CmdoReztStart.R */ /* File CmdoReztAttr.R */ /* W. Powell, 1988 */ /* Include File to generate nested dialog for Rez * resource attributes */ /* This file is meant to be included in other Rez files * as a complete nested dialog. * See Also file CmdoRezID.R (assumes this is dialog 2) */ /* Dialog 2 */ /* Resource attribute stuff */ 270, “Select Attributes for the resource”, { NotDependent {}, RadioButtons { { {35,85,55,220}, “Application Heap”, “”,Set, “Load resource into application heap” , {35,260,55,400}, “System Heap”, “-sy”,NotSet, “Load resource into system heap instead” “ of application heap” }}, NotDependent {}, RadioButtons { { {55,260,75,400}, “Purgeable”, “-pu”,NotSet, “Make the resource initially purgeable.”, {55,85,75,220}, “Not Purgeable”,””,NotSet, “Make resource initially unpurgeable” }}, NotDependent {}, RadioButtons { { {75,85,95,220}, “Unlocked”,””,Set, “Resource not initially locked in memory”, {75,260,95,400}, “Locked”,”-lo”,NotSet, “Lock resource in memory when loaded” } }, NotDependent {}, RadioButtons { { {95,85,115,220}, “Unprotected”,””,Set, “Marked as changeable in resource file”, {95,260,115,400}, “Protected”,”-Pr”,NotSet, “Protect resource in file from changes” } }, NotDependent {}, RadioButtons { { {115,85,135,220}, “No Pre-Load”,””,Set, “Require explicit command to load resource” “ into memory.”, {115,260,135,400}, “Pre-load”,”-PL”,NotSet, “Load resource when resource “ “fork is opened” }} }, /* End of file CmdoAttributes.R */ /* File CmdoReztRdir.R */ /* W. Powell 1988 */ /* Redirection Dialog for Output and Error */ /* This file is meant to be included in commandos for building Rez input*/ 160, “Redirect the Standard and Diagnostic outputs”, { NotDependent {}, Redirection { StandardOutput, {15,80} }, NotDependent {}, Redirection { DiagnosticOutput, {15,270} } }, /* End of File CmdoReztRdir.R */ /* File CmdoRect.R */ /* W. Powell, 1988 */ /* Include File to generate commando input for rectangles */ /* This file is meant to be included in other Rez files * This file contains 5 Commando control items * Parameters RLeft, RTop, RTit, RDep are to be defined in * the calling source file. * RTop = vertical component of top of the RECT dialog area * RLeft= horizontal component of left of RECT input area * RTit = short title to describe rectangle * RDef = a control list enclosed in one set of {}’s. * The RECT input area has OR dependency on this * set of controls. Build more complicated * dependency with dummy items. */ #ifndef RTop #printf (“### CmdoRect.R Error:\n”) #printf (“### Variable RTop (vert. coord of top left) undefined\n”) #endif #ifndef RLeft #printf (“### CmdoRect.R Error:\n”) #printf (“### Variable RLeft (horiz. coord. of top left) undefined\n”) #endif #ifndef RDep #printf (“### CmdoRect.R Error:\n”) #printf (“### Variable RDep (list of control dependencies) undefined\n”) #endif #ifndef RTit #define RTit “” #endif OR { RDep }, RegularEntry { “Top”, {RTop+7,RLeft+10,RTop+23,RLeft+50}, {RTop+27,RLeft+10,RTop+43,RLeft+50}, “”,keepCase,”-t”, “Top coordinate of rectangle” }, OR { RDep }, RegularEntry { “Left”, {RTop+7,RLeft+60,RTop+23,RLeft+100}, {RTop+27,RLeft+60,RTop+43,RLeft+100}, “”,keepCase,”-l”, “Left coordinate of rectangle” }, OR { RDep }, RegularEntry { “Bottom”, {RTop+7,RLeft+106,RTop+23,RLeft+156}, {RTop+27,RLeft+110,RTop+43,RLeft+150}, “”,keepCase,”-b”, “Bottom coordinate of rectangle” }, OR { RDep }, RegularEntry { “Right”, {RTop+7,RLeft+162,RTop+23,RLeft+200}, {RTop+27,RLeft+160,RTop+43,RLeft+200}, “”,keepCase,”-r”, “Right coordinate of rectangle” }, NotDependent {}, TextBox { gray, {RTop,RLeft,RTop+51,RLeft+210}, RTit }, /* End of file CmdoRect.R */ ###File: RezC.STRlist ### Generate Rez input for STR# Resources ### W. Powell 1988 Set Exit 0 Set rid {1} Shift 1 Echo -n “Resource ’STR#’ ({rid}” If “{1}” == “-nms” Set rname “{2}” If (“{rname}” != “”) Echo -n ,””{rname}”” End Shift 2 End Set Str “{1}” Shift 1 If ( “{1}” == “-sy” ) ; Echo -n “,SysHeap” ; Shift ; End If ( “{1}” == “-pu” ) ; Echo -n “,Purgeable” ; Shift ; End If ( “{1}” == “-lo” ) ; Echo -n “,Locked” ; Shift ; End If ( “{1}” == “-Pr” ) ; Echo -n “,Protected” ; Shift ; End If ( “{1}” == “-PL” ) ; Echo -n “,PreLoad” ; Shift ; End Echo “) { {“ Echo -n “t”{Str}”” Loop # for more strings RezC.STRlist.more Break If {Status} == 100 End Echo “t} };” Exit 0 ### End File RezC.STRlist ############################## ### File RezC.STRlist.more ### Continuation of RezC.STRlist ### for generation of Rez input for STR# resources ### W. Powell 1988 Set Exit 0 If “{1}” == “-OK” || “{1}” == “-LAST” If {#} == 2 Echo “;” Echo -n “t”{2}”” Else Echo “;” Echo -n “t””” End End If “{1}” == “-LAST” || “{1}” == “-DONE” Exit 100 End Exit 0 ### End File RezC.STRlist.more ############################### /* File RezC.STRlist.Cmdo.R */ /* Rez input for the Rezc.STRlist Commando interface */ /* W. Powell 1988 */ /* Rez definitions for Rez-building Commando interfaces */ #include “Cmdo.R” Resource ‘cmdo’ (200) { { 240, “Rezc.STRlist produces Rez input for a String resource.\n” “New dialogs will prompt for further strings.”, { /* This include file has a standard arrangement of items * common to all resources: ID#, attributes, name, * and redirection of output from the Rezc. script*/ #include “CmdoReztStart.R” /* Item 6 */ OR {{1}}, RegularEntry { “First string:”, {80,30,96,120}, {99,30,115,450}, “”,keepCase,””, “Enter the string.\nUse \\ to escape special characters.” }, /* Item 7 */ AND {{6}}, DoItButton {}, }, /* Dialog 2 */ /* Include the standard resource attributes dialog */ #include “CmdoReztAttr.R” /* Dialog 3 */ /* Include a redirection dialog */ #include “CmdoReztRdir.R” } }; /* End File RezC.STRlist.Cmdo.R */ /* File RezC.STRlist.more.Cmdo.R */ /* Rez input for the Rezc.STRlist.more Commando interface */ /* W. Powell 1988 */ /* Rez definitions for Rez-building Commando interfaces */ #include “Cmdo.R” Resource ‘cmdo’ (200) { { 220, “Enter the next string in the STR# string list.”, { NotDependent {}, RadioButtons {{ {30,30,46,140}, “More strings”,”-OK”,NotSet, “This is not the last string in the list.” “ Continue prompting for more.” , {30,170,46,270}, “Last string”,”-LAST”,NotSet, “This is the last string in the list.” “ Don’t need to prompt for more.”, {30,300,46,410}, “Already done”,”-DONE”,NotSet, “Previous string was the last. Ignore any “ “input in this dialog.” }}, NotDependent {}, Box { gray, {25,25,50,415} }, OR {{(3<<12)+1}}, Dummy {}, OR {{-3}}, RegularEntry { “String:”, {55,30,71,100}, {74,30,90,450}, “”,keepCase,””, “Enter the string.\nUse \\ to escape special characters.” }, } } }; /* End File RezC.STRlist.more.Cmdo.R */ ######################################### ###File RezC.MENU ### Generates Rez input for Menu resource ### W. Powell 1988 Set Exit 0 Set rid {1} Echo -n “Resource ’MENU’ ({rid}” Shift 1 If “{1}” == “-nms” Echo -n “,”{2}”” Shift 2 End # Menu state and title Set enflg “{1}” Set Title “{2}” Set ProcID “{3}” Shift 3 # Resource attributes If ( “{1}” == “-sy” ) ; Echo -n “,SysHeap” ; Shift ; End If ( “{1}” == “-pu” ) ; Echo -n “,Purgeable” ; Shift ; End If ( “{1}” == “-lo” ) ; Echo -n “,Locked” ; Shift ; End If ( “{1}” == “-Pr” ) ; Echo -n “,Protected” ; Shift ; End If ( “{1}” == “-PL” ) ; Echo -n “,PreLoad” ; Shift ; End Echo “) {“ Set OldActive “{Active}” Set OldTarget “{Target}” NewTempFile If {Status} != 0 Echo “### {0} Error: Can’t open temporary file.”>>Dev:StdErr Echo “###Try closing some windows or freeing disk space” >>Dev:StdErr Exit 2 End Set tempfil “{Active}” ### Restore original target/active If “{OldTarget}” != “” Open “{OldTarget}” End Open “{OldActive}” Unset OldTarget Unset OldActive Set FlgCnt 0 Set DoneFlg 0 Set bif “” # binary item flags Loop Set FlgCnt ‘Evaluate {FlgCnt} + 1‘ RezC.MENU.sub1 >>”{tempfil}” Set State {Status} If {State} == 10 || {State} == 110 Set bif “0{bif}”# disabled item Else Set bif “1{bif}”# enabled item End If {State} >= 100 Set DoneFlg 1 Break End Break If {FlgCnt} >= 31 End If {DoneFlg} == 0 Loop RezC.MENU.sub2 >>”{tempfil}” Break If {Status} >= 100 End End If {FlgCnt} < 31 # finish building enable flags Loop Set bif “1{bif}” Set FlgCnt ‘Evaluate {FlgCnt} + 1‘ Break If {FlgCnt} >= 31 End End Echo “t{rid},tt/* Menu ID */” Echo “t{ProcID},t/* Menu DefProc ID */” Echo “t0b{bif},t/* Item enable flags */” Echo “t{enflg},tt/* Whole menu enable */” If “{Title}” == “apple” Echo “tapple,ntt{“ Else Echo “t”{Title}”,ntt{“ End Catenate “{tempfil}” Echo “tt}” Close -n “{tempfil}” Echo “t};” Exit 0 ### End File RezC.MENU ################################# ######################## ###File RezC.MENU.sub1 ###Called by RezC.MENU ###W. Powell 1988 RezC.MENU1.more Set State {Status} Exit {State} ### End File RezC.MENU.sub1 ########################### ######################## ###File RezC.MENU.sub2 ###Called by RezC.MENU ###W. Powell 1988 RezC.MENU2.more Set State {Status} Exit {State} ### End File RezC.MENU.sub2 ########################### ####################################### ### File RezC.MENU1.more ### Called by RezC.MENU to generate partial Rez input ###for one menu item or hierarchical menu. ###W. Powell 1988 Set Exit 0 If “{1}” == “-DONE” # Done, no input Exit 100 End Echo “t”{1}”,” Shift 1 If “{1}” == “-icon” Echo “tt{2},t/* Icon */” Shift 2 Else Echo “ttnoIcon,t/* Icon */” End If “{1}” == “-key” Echo “tt”{2}”,t/* Cmd Key */” Shift 2 Else If “{1}” == “hierarchicalMenu” Echo “tthierarchicalMenu,t” Shift 1 Else Echo “ttnoKey,t/* Cmd Key */” End If “{1}” == “-mark” If “{2}” == “noMark” || “{2}” == “check” Echo “tt{2},t/* Marking Character */” Shift 2 Else Echo “tt”{2}”,t/* Marking Character */” Shift 2 End Else If “{1}” == “-sub” Set dmv “{2}” Shift 2 Set chars ‘Echo -n “{dmv}” | Count -c ‘ If {chars} == 0 Set dmv “000” Else If {chars} == 1 Set dmv “00{dmv}” Else If {chars} == 2 Set dmv “0{dmv}” End Echo “tt”\0D{dmv}”,t/* SubMenu ID */” Else Echo “ttnoMark,t/* Marking Character */” End If “{1}” == “enabled” Set EStat 0 Else if “{1}” == “disabled” Set EStat 10 Else Set EStat 20 # Not allowed End Shift 1 If “{1}” == “-LAST” Set EStat ‘Evaluate {EStat} + 100‘ End Shift 1 If “{1}” == “+” Shift 1 End Set TheStyle “” For style In {Parameters} Set TheStyle “{TheStyle} {style}” End Echo “tt/* Typeface style */” Echo -n “tt{TheStyle} “ If {EStat} <= 10 Echo “,” End Exit {EStat} ### End File RezC.MENU1.more ############################# ### File RezC.MENU2.more ### Called by RezC.MENU to generate partial Rez input ###for one menu item or hierarchical menu. ###W. Powell 1988 Set Exit 0 If “{1}” == “-DONE” # Done, no input Exit 100 End Echo “t”{1}”,” Shift 1 If “{1}” == “-icon” Echo “tt{2},t/* Icon */” Shift 2 Else Echo “ttnoIcon,t/* Icon */” End If “{1}” == “-key” Echo “tt”{2}”,t/* Cmd Key */” Shift 2 Else If “{1}” == “hierarchicalMenu” Echo “tthierarchicalMenu,t” Shift 1 Else Echo “ttnoKey,t/* Cmd Key */” End If “{1}” == “-mark” If “{2}” == “noMark” || “{2}” == “check” Echo “tt{2},t/* Marking Character */” Shift 2 Else Echo “tt”{2}”,t/* Marking Character */” Shift 2 End Else If “{1}” == “-sub” Set dmv “{2}” Shift 2 Set chars ‘Echo -n “{dmv}” | Count -c ‘ If {chars} == 0 Set dmv “000” Else If {chars} == 1 Set dmv “00{dmv}” Else If {chars} == 2 Set dmv “0{dmv}” End Echo “tt”\0D{dmv}”,t/* SubMenu ID */” Else Echo “ttnoMark,t/* Marking Character */” End Set EStat 0 If “{1}” == “-LAST” Set EStat 100 End Shift 1 If “{1}” == “+” Shift 1 End Set TheStyle “” For style In {Parameters} Set TheStyle “{TheStyle} {style}” End Echo “tt/* Typeface style */” Echo -n “tt{TheStyle} “ If {EStat} <= 10 Echo “,” End Exit {EStat} ### End File RezC.MENU2.more ############################# /* File RezC.MENU.Cmdo.R */ /* Commando interface to build MENU Rez input */ /* W. Powell 1988 */ /* Rez definitions for Rez-building Commando interfaces */ #include “Types.R” #include “Cmdo.R” Resource ‘cmdo’ (200) { { 265, “RezC.MENU produces Rez input for a Menu resource.\n” “NOTE: Input of menu items continues in subsequent dialogs.”, { /* This include file has a standard arrangement of items * common to all resources: ID#, attributes, name, * and redirection of output from the Rezc. script */ #include “CmdoReztStart.R” /* other items particular to this case */ /* Item 6 */ OR {{1}}, RadioButtons {{ {132,160,148,235}, “Enabled”,”enabled”,NotSet,”Entire menu is enabled.”, {132,250,148,325}, “Disabled”,”disabled”,NotSet,”Entire menu is disabled.” }}, /* Item 7 */ AND {{1,-8}}, RegularEntry { “Menu Title:”, {85,30,101,110}, {85,115,101,330}, “”,keepCase,””, “Title for menu.\nClick the apple for DA menu.” }, /* Item 8 */ OR {{1}}, CheckOption { NotSet, {85,340,101,440}, “•”,”apple”,”Click here to get apple DA menu.” }, /* Item 9 */ OR {{1}}, RegularEntry { “Proc ID#:”, {112,45,128,105}, {112,115,128,235}, “”,keepCase,””, “Menu Definition Proc ID # of this menu.\nNOTE:” “ Enter nothing to get default text menus.” }, /* Item 10 */ OR {{-9}}, RadioButtons {{ {40,1000,41,1001}, “”,”textMenuProc”,NotSet,”” }}, /* Item 11 */ OR {{7,8}}, DoItButton {}, /* Item 11 */ OR { {1} }, TextTitle { plain, {132,50,148,155}, systemFont, systemSize, “Entire menu is:” }, }, /* Dialog 2 */ /* Include the standard resource attributes dialog */ #include “CmdoReztAttr.R” /* Dialog 3 */ /* Include a redirection dialog */ #include “CmdoReztRdir.R” } }; /* End File RezC.MENU.Cmdo.R */ /* File RezC.MENU1.more.Cmdo.R */ /* Commando interface to build MENU Rez input */ /* W. Powell 1988 */ /* Rez definitions for Rez-building Commando interfaces */ #include “Types.R” #include “Cmdo.R” Resource ‘cmdo’ (200) { { 295, “RezC.MENU1 produces Rez input for one item in a “ “MENU resource.\n” “NOTE: Input of menu items continues in subsequent dialogs.”, { /* other items particular to this case */ /* Item 1 */ OR {{-((3<<12)+16)}}, RegularEntry { “Item Text:”, {25,30,41,110}, {25,115,41,430}, “”,keepCase,””, “Text of menu item.” }, /* Item 2 */ OR {{1}}, RegularEntry { “Icon #”, {50,40,66,90},{69,40,85,90}, “”,keepCase,”-icon”, “Index number for icon.\nIndex = [ICON ID #] - 256” }, /* Item 3 */ AND {{1,-4}}, RegularEntry { “-Key”, {50,130,66,180},{69,130,85,180}, “”,keepCase,”-key”, “Command key equivalent.” }, /* Item 4 */ OR {{1}}, CheckOption { NotSet,{125,80,141,220}, “Hierarchical Menu”,”hierarchicalMenu”, “Check here if item is a hierarchical menu.”} ; /* Item 5 */ AND {{1,-6,-4}}, RegularEntry { “Mark”, {50,220,66,270},{69,220,85,270}, “”,keepCase,”-mark”, “Mark the item with this character.\nClick the “ ““Check” item to mark with a check.” }, /* Item 6 */ AND {{1,-4}}, CheckOption { NotSet,{90,215,106,277}, “Check”,”-mark check”,”Mark item with check.” }, /* Item 7 */ OR {{4}}, RegularEntry { “SubMenu ID:”, {125,250,141,350}, {125,355,141,405}, “”,keepCase,”-sub”, “Resource ID of Hierarchical submenu.” }, /* Item 8 */ OR {{1}}, NestedDialog { 2,/* Dialog number */ {57,303,75,353}, “Style” , “Select type style for item’s text.”}, /* Item 9 */ OR {{1}}, RadioButtons {{ {67,380,83,455}, “Enabled”,”enabled”,NotSet,”Menu item is initially enabled.”, {83,380,99,455}, “Disabled”,”disabled”,NotSet,”Menu item is initially disabled.” }}, /* Item 10 */ NotDependent {}, TextBox { gray, {57,375,104,460},”Item is:” }, /* Item 11 */ AND {{4,7}}, Dummy {}, /* Item 12 */ OR {{-4,11}}, Dummy {}, /* Item 13 */ AND { {1,12} }, Dummy {}, /* Item 14 */ OR {{13,(3<<12)+16}}, DoItButton {}, /* Item 15 */ NotDependent {}, Box { gray, {117,45,149,435} }, /* Item 16 */ NotDependent {}, RadioButtons {{ {162,105,178,160}, “More items”,”-OK”,NotSet, “Continue prompting for items with more dialogs.”, {162,185,178,270}, “Last item”,”-LAST”,NotSet, “This is the last item on the menu. “ “Don’t need to prompt for more.”, {162,295,178,345}, “Done”,”-DONE”,NotSet, “Previous string was the last. Ignore any “ “input in this dialog.” }}, /* Item 17 */ NotDependent {}, Box { black, {159,90,181,390} }, }, /* Dialog 2 */ 205, “Text style for menu item.”, { /* Item 1 is hidden */ AND {{-3,-4,-5,-6,-7,-8,-9}}, RadioButtons {{ {30,1000,50,1001}, “”,”plain”,NotSet,”” }}, /* Item 2 */ NotDependent {}, CheckOption { Set,{20,100,36,200}, “Plain”,””,””}, OR {{-2}}, CheckOption { NotSet,{36,100,52,200}, “Bold”,”+ bold”,””}, OR {{-2}}, CheckOption { NotSet,{52,100,68,200}, “Italic”,”+ italic”,””}, OR {{-2}}, CheckOption { NotSet,{68,100,84,200}, “Underline”,”+ underline”,””}, OR {{-2}}, CheckOption { NotSet,{20,280,36,380}, “Outline”,”+ outline”,””}, OR {{-2}}, CheckOption { NotSet,{36,280,52,380}, “Shadow”,”+ shadow”,””}, OR {{-2}}, CheckOption { NotSet,{52,280,68,380}, “Condense”,”+ condense”,””}, OR {{-2}}, CheckOption { NotSet,{68,280,84,380}, “Extend”,”+ extend”,””}, }, } }; /* End File RezC.MENU1.more.Cmdo.R */ /* File RezC.MENU2.more.Cmdo.R */ /* Commando interface to build MENU Rez input */ /* W. Powell 1988 */ /* Rez definitions for Rez-building Commando interfaces */ #include “Types.R” #include “Cmdo.R” Resource ‘cmdo’ (200) { { 295, “RezC.MENU2 produces Rez input for one item in a “ “MENU resource.\n” “NOTE: Input of menu items continues in subsequent dialogs.”, { /* other items particular to this case */ /* Item 1 */ OR {{-((3<<12)+17)}}, RegularEntry { “Item Text:”, {25,30,41,110}, {25,115,41,430}, “”,keepCase,””, “Text of menu item.” }, /* Item 2 */ OR {{1}}, RegularEntry { “Icon #”, {50,40,66,90},{69,40,85,90}, “”,keepCase,”-icon”, “Index number for icon.\nIndex = [ICON ID #] - 256” }, /* Item 3 */ AND {{1,-4}}, RegularEntry { “-Key”, {50,130,66,180},{69,130,85,180}, “”,keepCase,”-key”, “Command key equivalent.” }, /* Item 4 */ OR {{1}}, CheckOption { NotSet,{125,80,141,220}, “Hierarchical Menu”,”hierarchicalMenu”, “Check here if item is a hierarchical menu.”} ; /* Item 5 */ AND {{1,-6,-4}}, RegularEntry { “Mark”, {50,220,66,270},{69,220,85,270}, “”,keepCase,”-mark”, “Mark the item with this character.\nClick the “ ““Check” item to mark with a check.” }, /* Item 6 */ AND {{1,-4}}, CheckOption { NotSet,{90,215,106,277}, “Check”,”-mark check”,”Mark item with check.” }, /* Item 7 */ OR {{4}}, RegularEntry { “SubMenu ID:”, {125,250,141,350}, {125,355,141,405}, “”,keepCase,”-sub”, “Resource ID of Hierarchical submenu.” }, /* Item 8 */ OR {{1}}, NestedDialog { 2,/* Dialog number */ {57,303,75,353}, “Style” , “Select type style for item’s text.”}, /* Item 9 */ NotDependent {}, RadioButtons {{ {67,380,83,455}, “Enabled”,””,NotSet, “Items 32 and greater must always be enabled.” }}, /* Item 10 */ OR {{-9}}, RadioButtons {{ {83,380,99,455}, “Disabled”,””,NotSet, “Items 32 and greater must always be enabled.” }}, /* Item 11 */ NotDependent {}, TextBox { gray, {57,375,104,460},”Item is:” }, /* Item 12 */ AND {{4,7}}, Dummy {}, /* Item 13 */ OR {{-4,12}}, Dummy {}, /* Item 14 */ AND { {1,13} }, Dummy {}, /* Item 15 */ OR {{14,(3<<12)+17}}, DoItButton {}, /* Item 16 */ NotDependent {}, Box { gray, {117,45,149,435} }, /* Item 17 */ NotDependent {}, RadioButtons {{ {162,105,178,160}, “More items”,”-OK”,NotSet, “Continue prompting for items with more dialogs.”, {162,185,178,270}, “Last item”,”-LAST”,NotSet, “This is the last item on the menu. “ “Don’t need to prompt for more.”, {162,295,178,345}, “Done”,”-DONE”,NotSet, “Previous string was the last. Ignore any “ “input in this dialog.” }}, /* Item 18 */ NotDependent {}, Box { black, {159,90,181,390} }, }, /* Dialog 2 */ 205, “Text style for menu item.”, { /* Item 1 is hidden */ AND {{-3,-4,-5,-6,-7,-8,-9}}, RadioButtons {{ {30,1000,50,1001}, “”,”plain”,NotSet,”” }}, /* Item 2 */ NotDependent {}, CheckOption { Set,{20,100,36,200}, “Plain”,””,””}, OR {{-2}}, CheckOption { NotSet,{36,100,52,200}, “Bold”,”+ bold”,””}, OR {{-2}}, CheckOption { NotSet,{52,100,68,200}, “Italic”,”+ italic”,””}, OR {{-2}}, CheckOption { NotSet,{68,100,84,200}, “Underline”,”+ underline”,””}, OR {{-2}}, CheckOption { NotSet,{20,280,36,380}, “Outline”,”+ outline”,””}, OR {{-2}}, CheckOption { NotSet,{36,280,52,380}, “Shadow”,”+ shadow”,””}, OR {{-2}}, CheckOption { NotSet,{52,280,68,380}, “Condense”,”+ condense”,””}, OR {{-2}}, CheckOption { NotSet,{68,280,84,380}, “Extend”,”+ extend”,””}, }, } }; /* End File RezC.MENU2.more.Cmdo.R */
![](/file/12652/www.mactech.com.tar/www.mactech.com/sites/all/themes/custom_front/img/search_text.gif)
- SPREAD THE WORD:
- Slashdot
- Digg
- Del.icio.us
- Newsvine