Menu Command Unit
Volume Number: 7
Issue Number: 9
Column Tag Pascal Procedures
Related Info: Menu Manager
Menu Command Handler Unit
By David T. Craig, Kansas City, MO
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
[David has been involved with the Macintosh on the software side since its
introduction in 1984. Currently he works as a Macintosh programmer for a small
custom application development company in Kansas City, Kansas.]
Introduction
This unit manages menu commands in a manner similar to Apple’s MacApp
“command menu” mechanism. Each application menu item should contain a unique
“command number”, an integer value in the range 1 to 32767. This module scans the
installed menus, parses the command numbers from each menu item, and stores the
item command numbers in a table. When a menu item is selected, this module should be
called to return the command number of the selected item. The parsed menu command
number is also removed from the menu item.
Having each menu item define its own unique command value simplifies the job of
the application programmer. Instead of using the menu id and menu item values for
menu handling, the programmer needs only to use the unique command numbers. Using
command numbers allows the programmer to move menu items around in the resource
file without having to change the application source code. Users also benefit since they
too can move menu items around via ResEdit as long as they don’t alter the item’s
command number.
A menu item has a command number if the menu contains the character “#”
followed by the command number. An example follows for a typical file menu (format
compatible with Apple’s MPW Rez tool):
#1
New#1",noicon,nokey,nomark, plain;
"Open...#2",noicon,"O",nomark,plain;
"-",noicon,nokey,nomark,plain;
"Quit#3", noicon,"Q",nomark,plain;
Note that the command number must exist at the menu item’s end.
Using this Unit
This module contains several routines which completely control access to menu
command numbers.
Routine MC_Build_Menu_Command_Table builds the menu command table for an
application. Call this at the start of an application after the application menus have
been installed. This routine takes a pointer to a list of menu handles which define all
the application menus. In Pascal a simple array of MenuHandle is adequate.
Once you are completely finished with all the menus call routine
MC_UnBuild_Menu_Command_Table. This should generally be called when the
application quits.
Routine MC_Fetch_Menu_Command should be called when the user selects a
menu item via either the ROM MenuSelect or ROM MenuKey routines. This routine
returns the command number for the selected menu item.
Routine MC_Fetch_Menu_ID_and_Item returns the menu id and item numbers
for a menu command number. Once this routine is used you may use the command’s id
and item numbers with the many routines supported by the Apple Menu Manager.
Routine MC_Version returns the version number and compilation date and time
of this module.
Applications supporting menus that change may also use this module (MicroSoft
Word is an example of an application with changing menus). Whenever the menus
change you must deallocate the built menu command table and rebuild the new menu
command table.
WARNING: The caller of these routines must not make any assumptions about the
contents of a menu command table. This data structure, which is referenced thru a
handle, must be considered off limits since its internal layout may change. Use only the
public routines in this module and you will have no problems.
Unit Interface Routines
PROCEDURE MC_Version (VAR version_phrase: Str255);
PROCEDURE MC_Build_Menu_Command_Table
(menu_list: Ptr;
menu_count: INTEGER;
VAR command_table: Handle;
VAR good_build: BOOLEAN);
PROCEDURE MC_UnBuild_Menu_Command_Table
(VAR command_table: Handle;
VAR good_unbuild: BOOLEAN);
PROCEDURE MC_Fetch_Menu_Command
(command_table: Handle;
menu_info: LONGINT;
VAR menu_command: INTEGER);
PROCEDURE MC_Fetch_Menu_ID_and_Item
(command_table: Handle;
menu_command: INTEGER;
VAR menu_id: INTEGER;
VAR menu_item: INTEGER);
Listing: UMenuCommand.p
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ • • }
{ • ---------------------------------------------- • }
{ • APPLE MACINTOSH MENU COMMAND PARSER MODULE • }
{ • ---------------------------------------------- • }
{ • • }
{ • Author ...... David T. Craig • }
{ • Address ..... 736 Edgewater, Wichita, Kansas 67230 • }
{ • Date ........ 1989/1990 • }
{ • Version ..... 1.0.0 • }
{ • Language .... Apple MPW and Think Pascal 3.0 • }
{ • Computer .... Apple Macintosh • }
{ • • }
{ • Copyright ... NOT Copyright (C) 1990 by David T. Craig • }
{ • • }
{ • PURPOSE: • }
{ • • }
{ • This module manages menu commands similar to Apple's MacApp
"command menu" mechanism. • }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ • • }
{ • Modification Notes • }
{ • • }
{ • Originally written in Lisa Pascal on a Lisa, ported to MPW and
thento Think Pascal. • }
{ • • }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ • NOT COPYRIGHT 1990 BY DAVID T. CRAIG • }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
UNIT UMenuCommand;
{ ########################################################## }
INTERFACE
{ ########################################################## }
{$DECL for_MPW}
{$SETC for_MPW:=FALSE}
{$DECL for_THINK}
{$SETC for_THINK:=TRUE}
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ • EXTERNAL MODULES • }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{$IFC for_MPW}
USES
MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf, Traps, PasLibIntf;
{$ENDC}
{$IFC for_THINK}
USES
MemTypes, QuickDraw, OSIntf, ToolIntf, Packages;
{$ENDC}
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ • COMPILER DIRECTIVES • }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{$IFC for_MPW}
{$R+}
{ array, string, & subrange range checking [MPW PASCAL 3.0] }
{$OV+}
{ integer overflow checking [MPW PASCAL 3.0] }
{$SC+}
{ short-circuit boolean evaluation [MPW PASCAL 3.0] }
{$ENDC}
{$IFC for_THINK}
{$R+}
{ array, string,& subrange range checking [THINK PASCAL 3.0] }
{$N+}
{ routine name inclusion for debugger [THINK PASCAL 3.0] }
{$V+}
{ integer overflow checking [THINK PASCAL 3.0] }
{$ENDC}
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ • PUBLIC MODULE INTERFACE • }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
CONST
MC_c_NoCommand = 0; { menu command value for NO COMMAND }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
{ • Routine ... MC_Version }
{ • Purpose ... Return the version number and compilation date of
the module }
{ • Input ..... (none) }
{ • Output .... version_phrase - version number and compilation date
info }
{ • Notes ..... Use this if you are interested in having this
information. }
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
PROCEDURE MC_Version (VAR version_phrase: Str255);