TweetFollow Us on Twitter

Menu Definition
Volume Number:2
Issue Number:8
Column Tag:Pascal Procedures

Menu Definition Routines

By Darryl Lovato, TML Systems, Inc.

Introduction

Hello, as promised, we will cover Menu Definition Routines this month. What is a Menu Definition Routine? It is a procedure that defines a particular type of menu. The routine controls the way menus are drawn, and how items within it are selected. In general, Menu Definition routines define a given menu's appearance and behavior. The standard type of Macintosh menu is pre-defined for you and it is stored in the system file. You may however, want to define your own type of menu. The pattern selection menu in MacDraw is a good example of a non-standard menu.

The menu definition procedure I decided to use for an example doesn't create a non-standard menu but it shows exactly how the standard menu definition works! The standard definition routine was written in 68000 Assembler, by Andy Hertzsfield (my Hero) but ours will be written in TML Pascal (with the exception of one routine, which couldn't be written with Pascal, so I wrote it in 68000 Assembler). There isn't any noticeable speed difference between the standard Menu Def and our imitation.

An example of a non-standard Menu

The Pascal definition and general outline of a Menu definition procedure follows:

{1}

procedure MyMenu(message : integer;
 theMenu :  MenuHandle;
 var menuRect :  Rect;
 hitPt :  Point;
 var whichItem : Integer);

procedure DoDrawMessage(aMenu :   MenuHandle;
 aRect :  Rect);
  begin
  ...{draw the menu in menurect}
  end;

procedure DoChooseMessage(aMenu : MenuHandle;
 aRect :  Rect;
 aPt :  Point;
 var aItem :   Integer);
  begin
  ...{see what item aPt is in and select it}
  end;

procedure DoSizeMessage(aMenu : MenuHandle);
  begin
  ...{calculate the width and height of aMenu}
  end;

begin
  case message of
    mDrawMsg :
      DoDrawMessage(theMenu, menuRect);
    mChooseMsg :
      DoCooseMessage(theMenu, menuRect,
 hitPt, whichItem);
    mSizeMsg :
     DoSizeMessage(theMenu);
  end;
end;

The Parameters

The message parameter tells type of operation to perform. It can be one of the following values:

mDrawMsg - Draw the menu.

mChooseMsg - Choose a item.

mSizeMsg - Calculate the menu's height & width.

The 'theMenu' parameter is a MenuHandle to the menu we are to perform the action on.

The 'menuRect' is the rectangle in which the menu is in. It is in global coordinates.

The 'hitPt' parameter is the point (again, in global coordinates) that the mouse was pressed. It is only valid during a 'mChooseMsg'.

The 'whichItem' parameter holds the item number that is currently selected. You pass the result of your hit test back to the menu manager in this parameter.

The DoSizeMessage Procedure

When we are passed the mSizeMsg message, we need to calculate the width and height of the menu passed in theMenu parameter. The results are returned in the menu records Width and Height fields respectively. For a menu which has only one size, MacDraw's pattern selection menu, for example, this is real easy- just assign the width and height fields their constant values. For your example, which has variable widths and heights, it is a little harder.

The way we do this is have a variable that holds the cumulative vertical distance and another which holds the greatest horizontal distance. We loop through each item, first getting all its attributes (icon, text, cmd key...). Then we add the current items height to the cumulative height variable (36 if it has a icon, 16 otherwise). We must also find the items width; this is done by checking for icons, cmd keys, the items string width, etc. If this items width is greater than all others we have encountered so far, then we update the greatest width variable. When we have done this for all items in the menu, we return the results in the menu record fields Width and Height.

The DoDrawMessage Procedure

The DoDrawMessage is called when we receive a mDrawMsg from the menu manager. In response to this, we draw the menu items in theRect. When we are called, the current port will be the WindowMgrPort and the boarder around the menu will already be drawn. Again, we just go through a loop, looking at every item. If the item has an icon, we draw it and bump the location of where the text will go down half the size of the icon. We draw the markChar, if any. Then we draw the items text, and finally, the items keyboard equivalent, if any.

The DoChooseMessage Procedure

When we receive a mChooseMsg we call the DoChooseMessage and pass it the following parameters. The 'aPt' parameter is the mouse location that we need to check for. The 'whichItem' parameter is the item number of the last item that was choosen from this menu (initially 0). First we check to see if the point is in the menus rect, if not, we return 0. Otherwise, we see if the point is in an enabled item, if not, we return 0. If it was in an enabled item, we need to unhilite the old item (unless they are the same), hilite the new item (again, unless they are the same), and return the item it was in.

Getting the Menu Manager to Use our Def

Now that we have our definition routine defined, how do we get the Menu Manager to use our definition routine instead of the standard one (even thought they act the same)? One method of doing this follows:

1. Get the handle to the menu by calling NewMenu or GetNewMenu.

2. Put a new handle in the menuProc field of the menu record.

3. Make that point to the address of our MenuDefRoutine.

myMenuHdl := GetNewMenu(...);
myMenuHdl^^.menuProc := NewHandle(0);
myMenuHdl^^.menuProc^ := Ptr(@TheMenuProc);

Other Points of Interest

The assembly routine we use in this example simply returns the keyboard equivalent of a menu item. Since there is no standard trap to do this, and it can't be done with Pascal, no- wait a minuite...it can be done with Pascal. But it is a lot easier with assembly, so there! Anyway, it simply walks through the menu record until it finds 'theItem', and it gets its keyboard equivalent and returns it. It's Pascal declaration is :

procedure GetItemKey(theMenu : MenuHandle;
 theItem : Integer;
 var theChar : Char); external;

This is only one type of menu def, the number of possible menu definition routines that can be made are as big as your imagination, and, of course, available memory. For example, in addition to the MacDraw type MDEF I have done for the TML Examples Disks, I have done a Hierarchical Menu Definition routine. The way it works is this: to define a sub-menu in a menu, you simply add the string '|XXX' to the item you want to have the sub-menu. The XXX is the resource id of the menu you want to be the sub menu of the item. So, when I am supposed to draw the menu or calculate the menu's size, I strip out the '|XXX' string. Where it gets fancy is when you get the choose message, and you move onto an item that has a submenu ('|XXX' in its string). When this happens, I call a Pascal version of Mike Shuster's PopUpSelect routine [published in MacTutor December 1985 issue and available as a back issue for $4] for the menu with the res ID XXX. If the same conditions occur in the PopUpSelect routine, which calls the Definition Routine, I call it again. Can you say RECURSION ? I knew you could.

A good use for this type of Menu Def is a Character Menu, its items are Font, Size, and Style. When you move the mouse over one of these items, a list of fonts, a list of available sizes, or a list of styles appear in the sub menu. The advantage of this is that it only took one place in the menu bar to implement 3 separate menus.

Next Month...

Next month we will cover the wonderful world of Window Definition Routines. We will go through an example that shows how the standard window definition routine works. I would suggest reading the Window Manager section of Inside Macintosh, especially the section on "Defining Your Own Windows". If you have any questions/suggestions or other form of abuse, drop me a line in care of MacTutor. Or better yet, buy the TML Examples Disks, there is 3 MDEF Examples in them. Its been real...

Pascal Source Code
{################################################
#
#RegMDEF.Pas
#
#     (Regular Menu Definition Routine Example)    
#      ( just like apples, except in Pascal )
#
#This program was written by Darryl Lovato.              
#Copyright (c) 1986 by TML Systems.   
#
#################################################}

program RegMDEF;

{------------------------- Compiler Directives ---------------------------}

  {$B+    } { Tell the linker to set the bundle bit}
  {$T APPL RMDF  } {  type to Appl and creator to RMDF}
  {$I MemTypes.ipas} { Include the Memory Declarations}
  {$I QuickDraw.ipas}{ Include  QuickDraw Declarations}
  {$I OSIntf.ipas} { Include the OS Declarations}
  {$I ToolIntf.ipas} { Include the Toolbox Declarations}
  {$L RegMDEFRsrc} { Tell the linker to link the resources}
  {$U RegMDEFGlue} { link our assembly code in too...}
 
{--------------------------- Global Constants ----------------------------}

  const
    appleMenu = 300; { Resource ID of the Apple menu}
    fileMenu = 301;{ Resource ID of the File menu}
    editMenu = 302;{ Resource ID of the Edit menu}    
    
    beginMenu = 300; { Res ID of first menu in menu bar}
    endMenu = 302; { Res ID of last menu in menu bar}
    RegMenu = 500; { Res ID of our regular menu}

{--------------------------- Global Variables ------------------------------}

  var
   { The menus in menu bar}
    myMenus : array[beginMenu..endMenu] of MenuHandle;
    Finished : Boolean; { Set to true when were done}
    screenPort : GrafPtr; { the window mngr port}
    MyRegMenu : MenuHandle; { my regular menu handle}

{--------------------- Assembly Procedures ----------------------------}

procedure GetItemKey(theMenu : MenuHandle;
 theItem : Integer;
 var theChar : Char); external;

{------------------- ChkOnOffItem procedure --------------------------}

procedure ChkOnOffItem(MenuHdl:MenuHandle; item, first,        
 last:Integer);
var
  i: integer;
begin
  for i := first to last do
    begin
      if item = i then
        CheckItem(MenuHdl, i, true) {check it on in menu}
      else
        CheckItem(MenuHdl, i, false); {check it off in menu}
    end;
end;
    
{----------------------- MenuDef Procedure -----------------------------}

procedure MyMenuDef(message : Integer; { what do  we do?}
 theMenu : MenuHandle;    { what menu ?}
 var menuRect : Rect;{ in what rect?}
 hitPt : Point;  { where's mouse?}
 var whichItem : Integer);{ what item is it?}

{--------------------- semi-global constants ----------------------------}

  const
    MBarHeight = 20;

{----------------------- DimRect procedure ------------------------------}

  procedure DimRect(theRect : Rect);
    begin
      PenPat(gray);
      PenMode(patBic);
      PaintRect(theRect);
      PenNormal;
    end;

{--------------------- GetItemsRect Function ---------------------------}
 
   function GetItemsRect(myMenu : MenuHandle;
       myRect : Rect;
       theItem : Integer) : Rect;
    var
      Index : Integer;
      currentRect : Rect;
      itemIcon : Byte;
    begin
      currentRect.bottom := myRect.top; { initialize current rect}
      currentRect.left := myRect.left;
      currentRect.right := myRect.right;
      for index := 1 to theItem do
 begin
   GetItemIcon(myMenu,index,itemIcon);

   currentRect.top := currentRect.bottom; { update rect }
   if itemIcon <> 0 then
     currentRect.bottom := currentRect.top + 36
   else 
     currentRect.bottom := currentRect.top + 16;
 end;
      GetItemsRect := currentRect; { return result}
    end;
 
{--------------- DoDrawMessage Procedure -----------------------}

  procedure DoDrawMessage(myMenu : MenuHandle;
   myRect : Rect);
    const
      MBarHeight = 20;
    var
      currentItem : Integer;
      currentRect : Rect;
      itemString : str255;
      itemIcon : Byte;
      itemMark : Char;
      itemStyle : Style;
      itemKey : Char;
      thePoint : Point;
      theIcon : Handle;
      iconRect : Rect;
      NewVert : Integer;

    begin
      currentRect.bottom := myRect.top; { initialize  current rect}
      currentRect.left := myRect.left;
      currentRect.right := myRect.right;
      for currentItem := 1 to CountMItems(myMenu) do{ all  items}
        begin
   GetItem(myMenu,currentItem,itemString);{ get info }
   GetItemIcon(myMenu,currentItem,itemIcon);
   GetItemMark(myMenu,currentItem,itemMark);
   GetItemStyle(myMenu,currentItem,itemStyle);
   GetItemKey(myMenu,currentItem,itemKey);

   currentRect.top := currentRect.bottom; { update rect }
   if itemIcon <> 0 then
     currentRect.bottom := currentRect.top + 36
   else 
     currentRect.bottom := currentRect.top + 16;
   
   if itemString = '-' then { special case '-' item}
     begin
       PenPat(Gray);
       moveTo(currentRect.left,currentRect.top + 8);
       Line(currentRect.right,0);
       PenPat(Black);
     end
   else { draw the other item stuff}
     begin  {get baseline}
       NewVert := ((currentRect.bottom - currentRect.top)
 DIV 2);
       NewVert := currentRect.top + 4 + NewVert; 
       MoveTo(currentRect.left + 2,newVert);
       
       if itemMark <> Chr(0) then
         DrawChar(itemMark);
       
       if itemIcon <> 0 then { draw the icon}
         begin
   iconRect.top := currentRect.top + 2;
   iconRect.bottom := iconRect.top + 32;
   iconRect.left := currentRect.left + 13;
   iconRect.right := iconRect.left + 32;
   theIcon := GetIcon(256 + itemIcon);
   PlotIcon(iconRect,theIcon);
   GetPen(thePoint);
              MoveTo(currentRect.left + 47,thePoint.v); 
 end
       else { otherwise, just move over a bit}
         begin
   GetPen(thePoint);
   MoveTo(currentRect.left + 13,thePoint.v); 
 end;

      TextFace(itemStyle);
      DrawString(itemString);
      TextFace([]);
      
      if itemKey <> Chr(0) then { draw key equiv}
        begin
  GetPen(thePoint);
  MoveTo(currentRect.right - 24,thePoint.v);
  DrawChar(Chr($11)); { draw cmd char symbol}
  DrawChar(itemKey); { and the cmd key}
        end;
 
      if (BitAnd(myMenu^^.enableFlags,1) = 0) then{disabled!}
        DimRect(currentRect);
      if (BitAnd(BitShift(
 myMenu^^.enableFlags,-currentItem),1) = 0) then
        DimRect(currentRect);
 
    end; { of if itemString = '-' then..else..}
 end;
    end; { of DoDrawMessage}

{------------- DoChooseMessage Procedure ---------------------}
  
  function DoChooseMessage(myMenu : MenuHandle;
   myRect : Rect;
 myPoint : Point;
 oldItem : Integer) : Integer;
    var
      theItem : Integer;
      ItemsRect : Rect;
    begin
      if PtInRect(myPoint,myRect) then
        begin
   theItem := 1;
   repeat
            ItemsRect := GetItemsRect(myMenu, myRect, theItem);
     theItem := theItem + 1;
   until PtInRect(myPoint,itemsRect);
   theItem := theItem - 1; { undo last increment}

   if (BitAnd(myMenu^^.enableFlags,1) = 0) or 
     (BitAnd(BitShift(
 myMenu^^.enableFlags,-theItem),1) = 0) then
       begin
         theItem := 0;
       end;

   if theItem <> oldItem then {de-select old, select new}
     begin
       if oldItem <> 0 then { deselect old}
 InvertRect(GetItemsRect(
 myMenu, myRect,oldItem));
       if theItem <> 0 then
    InvertRect(GetItemsRect(myMenu, myRect,theItem));
     end;
   DoChooseMessage := theItem; { return result}
 end
      else { it was not in our menu}
        begin
   if oldItem <> 0 then { we need to de-select old item}
     InvertRect(GetItemsRect(myMenu, myRect,oldItem));
   DoChooseMessage := 0; { return result}
 end;
    end;

{----------------- DoSizeMessage Procedure -----------------------}

  procedure DoSizeMessage(var myMenu : MenuHandle);
    var
      MaxWidth : integer; { keep track of the maximum width}
      TotalHeight : integer;{ keep track of the total height}
      currentItem : integer;{ the menu item we are looking at}
      itemString : Str255;{ text of the curren menu item}
      itemIcon : Byte;  { resource id of the menu items icon}
      itemMark : char;  { the items mark}
      itemStyle : Style;  { the items character style}
      itemKey : Char;{ the keyboard equiv}
      tempWidth : Integer;{ the current items width}
      
    begin
      MaxWidth := 0; { initailize width}
      TotalHeight := 0; { initialize height}
      for currentItem := 1 to CountMItems(myMenu) do 
 begin
   GetItem(myMenu,currentItem,itemString); { get text}
   GetItemIcon(myMenu,currentItem,itemIcon); {get icon}
   GetItemMark(myMenu,currentItem,itemMark); { char}
   GetItemStyle(myMenu,currentItem,itemStyle); { style}
   GetItemKey(myMenu,currentItem,itemKey); { get key}
   
   tempWidth := 13; { indent a bit}
   if itemIcon <> 0 then
     tempWidth := tempWidth + 35; { make room for  icon}
   TextFace(itemStyle); { set to items style}
   tempWidth := tempWidth + StringWidth(itemString) + 4;
   TextFace([]); {return to normal}
   if itemKey <> Chr(0) then
     tempWidth := tempWidth + 30;

   if tempWidth > MaxWidth then
     MaxWidth := tempWidth;
   if itemKey <> chr(0) then
     tempWidth := tempWidth + 20;
   
   if itemIcon <> 0 then
     TotalHeight := totalHeight + 36 { add lots of space}
   else
     TotalHeight := totalHeight + 16; { add enough for text}
 end;
      with myMenu^^ do
        begin
   menuWidth := MaxWidth; { save result in menu record}
   menuHeight := TotalHeight; { ditto...}
 end;
    end;

{----------- Case on message and call procedure ------------------}

begin
  case message of
    mSizeMsg :
      begin
        DoSizeMessage(theMenu);
      end;
    mDrawMsg : 
      begin
        DoDrawMessage(theMenu,menuRect);
      end;
    mChooseMsg :
      begin
        whichItem := DoChooseMessage(
 theMenu,menuRect,hitPt,whichItem);
      end;
  end;
end;

{---------------- process the menu selection ------------------------}

  procedure ProcessMenu(CodeWord : LongInt);

    var
      menuNum : Integer; { Res ID of the menu Selected}
      itemNum : Integer;{ The item number selected}
      nameHolder : str255; { the name of the desk acc.}
      dummy : Integer; { just a dummy}
      AboutRecord : DialogRecord;{ the actual object}
      AboutDlog : DialogPtr; { a pointer to my dialog}

    begin
      menuNum := HiWord(CodeWord); { get the menu number}
      itemNum := LoWord(CodeWord); { get the item number}
      if itemNum > 0 then { ok to handle the menu?}
        begin
   case MenuNum of
     appleMenu :
       begin
         case ItemNum of
   1:
     begin
       AboutDlog := GetNewDialog(
 3000,@AboutRecord,Pointer(-1));
       ModalDialog(nil,dummy);
       CloseDialog(AboutDlog);
     end;
   2:begin
     end;
   otherwise
     begin
       GetItem(myMenus[appleMenu],
 ItemNum,NameHolder);
       dummy := OpenDeskAcc(NameHolder);
     end;
 end;
       end;
     fileMenu :
       begin
         Finished := true;
       end;
     editMenu :
       begin
         if not SystemEdit(ItemNum - 1) then
   begin
     {we dont support any other editing}
   end;
       end;
     RegMenu : 
       begin
         if ItemNum <> 0 then
   begin
     if itemNum > 3 then
       ChkOnOffItem(MyRegMenu, ItemNum, 4, 9);
   end;
       end;
   end; { of case menuNum of}
 end;   { of if CodeWord...}
   HiliteMenu(0);
    end;{ of process menu}

{-------------------------- Main Event loop -------------------------------}

  procedure MainEventLoop;

    type
      trickType = packed record{ to get around pascal's typing }
        case boolean of
   true :
     (I : LongInt);
   false :
     (chr3, chr2, chr1, chr0 : Char);
 end;

    var
      Event : EventRecord;{ Filled by Get next event}
      windowLoc : integer;{ the mouse location}
      mouseLoc : point; { the area it was in }
      theWindow : WindowPtr;{ Dummy, have no windows}
      trickVar : trickType; { because of pascal's typing}
      CharCode : Char;  { for command keys}
    begin
      repeat{ do this until we selected quit}
 SystemTask;{ Take care of desk accessories}
 if GetNextEvent(everyEvent,Event) then
   begin
     case event.what of { case out on the event type}
       mouseDown : { we had a mouse-down event     }
 begin
   mouseLoc := Event.where;{ wheres the mouse}
   windowLoc := FindWindow(mouseLoc,
 theWindow); 
   case windowLoc of { now case on the location}
     inMenuBar :
       ProcessMenu(MenuSelect(MouseLoc)); 
     inSysWindow:
       SystemClick(Event,theWindow); {In desk acc}
   end;
 end;
       keyDown,AutoKey :  { we had the user hit a key}
         begin
   trickVar.I := Event.Message;  { fill the longWord     }
   CharCode := trickVar.chr0;{ and pull off low-byte}
  if BitAnd(Event.modifiers,CmdKey) = CmdKey then 
     ProcessMenu(MenuKey(CharCode));
 end;
     end; { of case event.what...}
   end; { end of if Get Next event}
      until(Finished);    { end of repeat statement}
    end;{ of main event loop}

{----------------- SetUp Everything -------------------------------}

  procedure SetUpThings;

    type
      ProcHdl = ^ProcPtr;

    var
      index : integer;    { used in a for loop     }
     
    begin
      for index := beginMenu to endMenu do
        begin
   myMenus[index] := GetMenu(index);{ Get next menu}
 end;
      AddResMenu(myMenus[appleMenu],'DRVR'); 
      for index := beginMenu to endMenu do
 InsertMenu(myMenus[index],0);{ Insert the menu    }

    { #*#*#*#*#* here is the non-standard menu*#*#*#*#*#*#*# }

      MyRegMenu := GetMenu(500); { make a new Menu}
      MyRegMenu^^.menuProc := NewHandle(0);
      MyRegMenu^^.menuProc^ := Ptr(@MyMenuDef);

      Insertmenu(MyRegMenu,0);{ and add it to the menu list}
      CalcMenuSize(MyRegMenu);{ and calculate its size}
      DrawMenuBar; { Now draw the menu bar   }
      ChkOnOffItem(MyRegMenu, 4, 4, 9);{check  item in  menu}
    end;

{-------------------- Initialize Everything ----------------------------}

  procedure InitThings;
    begin
      InitGraf(@thePort); { create grafPort for screen}
      MoreMasters; { create bunch of master Ptr's}
      MoreMasters; {  wont need to worry about}
      MoreMasters; { heap fragmentation later!}
      MaxApplZone; { make sure we have lots!}
      InitFonts; { Startup the Font manager}
      InitWindows; { Startup the Window manager}
      InitMenus; { Startup the Menu manager}
      TEInit;    { initialize text edit}
      InitDialogs(nil);   { initialize dialogs     }
      InitCursor;{ make the cursor an arrow}
    end;

{--------------------- Main Program Seg ------------------------------}

begin
  InitThings;
  SetUpThings;
  Finished := false;
  MainEventLoop;
end.
Assembly Source Code
;###############################################
;#
;# procedure GetItemKey(theMenu : MenuHandle;
;# theItem : Integer;
;# var theChar : Char);
;#
;#------------------------------------------------------------------------------
;#
;# This assembly proc returns the current command key 
;# which is assigned to theItem.
;#
;################################################

;--------------------------- Equates -----------------------------------

; menuinfo data structure

menuID  equ 0  ; unique id for menu bar [word]
menuWidth equ  2 ; menu Width [word]
menuHeightequ  4 ; menu Height [word]
menuDefHandle  equ 6 ; menu definition proc [handle]
menuEnableequ  $A; enable flgs, one bit/item [long]
menuDataequ $E ; menu item string [string]
menuBlkSize equ  $E; menu block plus dataString

; menu string data structure

itemIconequ 0  ; icon byte
itemCmd equ 1  ; command key byte
itemMarkequ 2  ; checkmark character byte
itemStyle equ  3 ; style byte

.Trap _CountMItems $A950 ; trap word 

;--------------------------- XREF's ------------------------------------

 xdef GetItemKey ; so the linker will find us

;------------------------ Entrance -----------------------------------

GetItemKey
 link A6,#0 ; create new stack frame
 movem.l A0-A4/D0-D3,-(SP) ; save registers

;---------------------- Pop Parameters -------------------------------

 clr.l  D2; make sure it is empty
 clr.l  D1; ditto...
 clr.l  D0; ditto...

 clr.w  -(SP)    ; make room for result
 move.l 14(A6),-(SP); push MenuHandle
 _CountMItems    ; how many are in this menu?
 move.w (SP)+,D3 ; pop result

 move.l 14(A6),A4; fetch the menu handle
 move.w 12(A6),D1; fetch the item number
 movea.l8(A6),A3 ; fetch ptr to the char Ptr(word)

 cmp.w  D1,D3  ; num of Menu Items < theItem?
 blt  BadItem    ; yep, exit

;-------------------- Find the Cmd Key --------------------------------

 move.l (A4),A4  ; get menu ptr
 lea  menuData(A4),A4; now A4 points to menu title
 move.b (A4),D2  ; get length of menu title
 add.b  #1,D2    ; skip length byte

; (A4,D2) now points to the first menu items title (length byte)

nextItem
 sub.b  #1,D1    ; decrement count
 beq    GotItem  ; if 0, return its cmd char
 move.b (A4,D2),D0 ; get length of the title
 add    D0,D2  ; and skip it
 add    #5,D2    ; skipe item attrib& length byte
 bra    nextItem ; and look at the next item

;------------------------ Got the Item ----------------------------------

GotItem
 move.b (A4,D2),D0 ; get length of title
 add    D0,D2  ; and skip it
 add    #1,D2    ; skip length byte, too...
 clr.w  D0; make sure its empty
 move.b  itemCmd(A4,D2),D0
  ; get the key equivalent
 move.w D0,(A3)  ; and return it
 bra    Exit; and exit

;------------------- No Item Found ---------------------------------

BadItem
 clr.w  (A3); return no cmd char and exit
 
;-------------------- Clean Up & Exit --------------------------------

Exit
 movem.l(SP)+,A0-A4/D0-D3 ; restore registers
 unlk   A6; restore stack frame
 movea.l(SP)+,A0 ; save return address
 adda.l #10,SP ; clean up stack
 jmp    (A0); ... and return
Link File For TML Pascal
!PAS$Xfer

/Globals -4
RegMDEF
Pascal System:PAS$Library
OSTraps
ToolTraps
Pascal System:RegMDEFGlue
/Resources
Pascal System:RegMDEFRsrc
/Bundle
/Type 'APPL' 'RMDF'
$ 
Resource File For RMaker
*
*   Resource listing: "RegMDEFRsrc".
*

RegMDEFRsrc


TYPE RMDF=STR 
 ,0
Window Definition Procedure 

TYPE BNDL      ,128
RMDF  0
ICN#
0 128  1 129
FREF
0 128  

Type DLOG
     ,3000 (4)
New Dialog
56 74 312 444
Visible GoAway 
1
0
3000

Type DITL
     ,3000
8
*   1
BtnItem Enabled
200 239 237 324
Okay

*   2
StatText Disabled
16 83 34 284
MacLanguage Series™ Pascal

*   3
StatText Disabled
34 69 50 293
Advanced Programming Examples

*   4
StatText Disabled
61 52 77 307
- Standard Menu Definition Example -

*   5
StatText Disabled
90 6 139 368
Written by Darryl Lovato.++
\0DSpecial thanks to Robert Ulrich.++
\0DCopyright © 1986 by TML Systems. ++
All rights reserved. 

*   6
StatText Disabled
147 7 180 364
Complete source code for this example ++
(and others) is available from:

*   7
StatText Disabled
183 60 250 198
TML Systems, Inc. ++
\0DP.O. Box 361626 ++
\0DMelbourne, Fl 32936\0D(305) 242-1873

*   8
IconItem Enabled
14 21 46 53
3000

Type MENU
     ,500 (4)
Junk
Icon Item^1
(Disabled Item
(-
keyboard Equiv Item/K
Shadowed Item<S
Outlined Item<O
Underlined Item<U
Italic Item<I
Bold Item<B

     ,300 (4)
\14
About Regular MDEF...
(-

     ,301 (4)
File
Quit/Q

     ,302 (4)
Edit
Undo/Z
(-
Cut/X
Copy/C
Paste/V
Clear

Type ICON = GNRL
     ,257 (4)
FF7FFFFF
816AAAAB
E7555555
247EAAAB
24015555
247CAAAB
24827F55
250101AB
25391C55
2527633F
E7208080
812088E7
FF271465
01392255
F9011455
E482888D
E47C80A5
9A0063A1
99FE1D31
E6678129
E66679E7
99999C00
99999BFF
E6666667
E6666667
99999999
99999999
E6666667
E6666667
99999999
99999999
FFFFFFFF

     ,3000 (36)
3FFFFFFC
40000002
81C1FFC1
82210041
FE3F007F
92290049
91C9FFC9
90080009
90081C09
90C82209
9127E3F9
9F302201
91281C01
90C80001
90081F01
90086081
93C18041
94223020
9C2FC810
94247F0F
93C23007
90010007
90008007
90006007
93C01FE7
9420001F
9C3FE007
84200000
83C00000
80000001
40000002
3FFFFFFC

Type ICN# = GNRL
     ,128
2
00000000
7FFFFFFE
47E00002
47E00002
7FFFFFFE
54001556
6DC01AAA
55DF9556
6DC01AAA
54001556
6DC01AAA
555ED556
6DC01AAA
54001556
6EAABAAA
54001556
6FFFFAAA
56073556
6FFFFAAA
54001556
6DEEDAAA
54001556
6DF81AAA
54001556
6FFFFAAA
55555556
6AAAAAAA
55555556
6AAAAAAA
55555556
7FFFFFFE
00000000
*
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
 
AAPL
$99.02
Apple Inc.
+1.35
MSFT
$43.97
Microsoft Corpora
-0.53
GOOG
$590.60
Google Inc.
+1.58

MacTech Search:
Community Search:

Software Updates via MacUpdate

OS X Yosemite Wallpaper 1.0 - Desktop im...
OS X Yosemite Wallpaper is the gorgeous new background image for Apple's upcoming OS X 10.10 Yosemite. This wallpaper is available for all screen resolutions with a source file that measures 5,418... Read more
Acorn 4.4 - Bitmap image editor. (Demo)
Acorn is a new image editor built with one goal in mind - simplicity. Fast, easy, and fluid, Acorn provides the options you'll need without any overhead. Acorn feels right, and won't drain your bank... Read more
Bartender 1.2.20 - Organize your menu ba...
Bartender lets you organize your menu bar apps. Features: Lets you tidy your menu bar apps how you want. See your menu bar apps when you want. Hide the apps you need to run, but do not need to... Read more
TotalFinder 1.6.2 - Adds tabs, hotkeys,...
TotalFinder is a universally acclaimed navigational companion for your Mac. Enhance your Mac's Finder with features so smart and convenient, you won't believe you ever lived without them. Tab-based... Read more
Vienna 3.0.0 RC 2 :be5265e: - RSS and At...
Vienna is a freeware and Open-Source RSS/Atom newsreader with article storage and management via a SQLite database, written in Objective-C and Cocoa, for the OS X operating system. It provides... Read more
VLC Media Player 2.1.5 - Popular multime...
VLC Media Player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, MP3, OGG, ...) as well as DVDs, VCDs, and various streaming protocols. It... Read more
Default Folder X 4.6.7 - Enhances Open a...
Default Folder X attaches a toolbar to the right side of the Open and Save dialogs in any OS X-native application. The toolbar gives you fast access to various folders and commands. You just click... Read more
TinkerTool 5.3 - Expanded preference set...
TinkerTool is an application that gives you access to additional preference settings Apple has built into Mac OS X. This allows to activate hidden features in the operating system and in some of the... Read more
Audio Hijack Pro 2.11.0 - Record and enh...
Audio Hijack Pro drastically changes the way you use audio on your computer, giving you the freedom to listen to audio when you want and how you want. Record and enhance any audio with Audio Hijack... Read more
Intermission 1.1.1 - Pause and rewind li...
Intermission allows you to pause and rewind live audio from any application on your Mac. Intermission will buffer up to 3 hours of audio, allowing users to skip through any assortment of audio... Read more

Latest Forum Discussions

See All

Traps n’ Gemstones Review
Traps n’ Gemstones Review By Campbell Bird on July 28th, 2014 Our Rating: :: CASTLEVANIA JONESUniversal App - Designed for iPhone and iPad Fight mummies, dig tunnels, and ride a runaway minecart to discover ancient secrets in this... | Read more »
The Phantom PI Mission Apparition Review
The Phantom PI Mission Apparition Review By Jordan Minor on July 28th, 2014 Our Rating: :: GHOSTS BUSTEDUniversal App - Designed for iPhone and iPad The Phantom PI is an exceedingly clever and well-crafted adventure game.   | Read more »
More Stubies Are Coming Your Way in a Ne...
More Stubies Are Coming Your Way in a New Update Posted by Jessica Fisher on July 28th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
The Great Prank War Review
The Great Prank War Review By Nadia Oxford on July 28th, 2014 Our Rating: :: PRANKING IS SERIOUS BUSINESSUniversal App - Designed for iPhone and iPad Though short, The Great Prank War offers an interesting and fun mix of action and... | Read more »
Marvel Contest of Champions Announced at...
Marvel Contest of Champions Announced at Comic-Con Posted by Jennifer Allen on July 28th, 2014 [ permalink ] Announced over the weekend at San Diego Comic-Con was the fairly exciting looking Marvel Contest of Champions. | Read more »
Teenage Mutant Ninja Turtles Review
Teenage Mutant Ninja Turtles Review By Jennifer Allen on July 28th, 2014 Our Rating: :: DULL SWIPINGUniversal App - Designed for iPhone and iPad The pizza power is weak when it comes to this Teenage Mutant Ninja Turtles game.   | Read more »
Exploration Focused Puzzle Game Beatbudd...
Exploration Focused Puzzle Game Beatbuddy Set to Make Transition from PC to iOS this September Posted by Jennifer Allen on July 28th, 2014 [ permalink ] | Read more »
PlanetHD
PlanetHD By Nadia Oxford on July 28th, 2014 Our Rating: :: SPACE MADNESSUniversal App - Designed for iPhone and iPad PlanetHD will keep players busy for a while, though its unpredictable physics are a handful to deal with.   | Read more »
This Week at 148Apps: July 21-25, 2014
Another Week of Expert App Reviews   At 148Apps, we help you sort through the great ocean of apps to find the ones we think you’ll like and the ones you’ll need. Our top picks become Editor’s Choice, our stamp of approval for apps with that little... | Read more »
Reddme for iPhone - The Reddit Client (...
Reddme for iPhone - The Reddit Client 1.0 Device: iOS iPhone Category: News Price: $.99, Version: 1.0 (iTunes) Description: Reddme for iPhone is an iOS 7-optimized Reddit client that offers a refreshing new way to experience Reddit... | Read more »

Price Scanner via MacPrices.net

iOS 8 and OS X 10.10 To Support DuckDuckGo As...
Writing for Quartz, Dan Frommer reports that Apple’s forthcoming iOS 8 and OS X 10.10 operating systems version updates will allow users to select DuckDuckGo as their default search engine. He notes... Read more
U.K. Hospital Using iPods and iPads To Record...
British news journal GazetteLive’s. Ian McNeal notes that the old “an apple a day keeps the doctor away” proverb is being turned on its head at http://southtees.nhs.uk/hospitals/james-cook/ James... Read more
13-inch 2.5GHz MacBook Pro on sale for $1099,...
Best Buy has the 13″ 2.5GHz MacBook Pro available for $1099.99 on their online store. Choose free shipping or free instant local store pickup (if available). Their price is $100 off MSRP. Price is... Read more
Roundup of Apple refurbished MacBook Pros, th...
The Apple Store has Apple Certified Refurbished 13″ and 15″ MacBook Pros available for up to $400 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free. Their prices... Read more
Record Mac Shipments In Q2/14 Confound Analys...
A Seeking Alpha Trefis commentary notes that Apple’s fiscal Q3 2014 results released July 22, beat market predictions on earnings, although revenues were slightly lower than anticipated. Apple’s Mac’... Read more
Intel To Launch Core M Silicon For Use In Not...
Digitimes’ Monica Chen and Joseph Tsai, report that Intel will launch 14nm-based Core M series processors specifically for use in fanless notebook/tablet 2-in-1 models in Q4 2014, with many models to... Read more
Apple’s 2014 Back to School promotion: $100 g...
 Apple’s 2014 Back to School promotion includes a free $100 App Store Gift Card with the purchase of any new Mac (Mac mini excluded), or a $50 Gift Card with the purchase of an iPad or iPhone,... Read more
iMacs on sale for $150 off MSRP, $250 off for...
Best Buy has iMacs on sale for up to $160 off MSRP for a limited time. Choose free home shipping or free instant local store pickup (if available). Prices are valid for online orders only, in-store... Read more
Mac minis on sale for $100 off MSRP, starting...
Best Buy has Mac minis on sale for $100 off MSRP. Choose free shipping or free instant local store pickup. Prices are for online orders only, in-store prices may vary: 2.5GHz Mac mini: $499.99 2.3GHz... Read more
Global Tablet Market Grows 11% in Q2/14 Notwi...
Worldwide tablet sales grew 11.0 percent year over year in the second quarter of 2014, with shipments reaching 49.3 million units according to preliminary data from the International Data Corporation... Read more

Jobs Board

Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Sr. Product Leader, *Apple* Store Apps - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.