Finder Icons
Volume Number: 5
Issue Number: 1
Column Tag: Pascal Procedures
Finder Icon Controls 
By Jean de Combret, Grenoble, France
Finder-like icon-controls
How to write, debug and use ‘MDEF’ and ‘CDEF’ resources.
Jean de Combret is a former river-hydraulics engineer, who worked with
mathematical models human-unfriendly programs. He thinks the Mac could be a
solution to make such programs more friendly and has therefore set up “Diadème
Ingénierie” and written “ONDULA”. He is a member of “Macintosh Alpes Club”, as
well as Didier Guillon, Jörg Langowski [hum... thanks! -JL] and a lot of other
interesting folks.
While developing my application, it appeared to me I needed an object-interface,
somewhat like the Finder’s one, with icons, hierarchy ( folders contain other icons),
actions (by double-clicking, classifying, throwing away or choosing in a menu). So I
decided to write my own objects, and the best way I found to do it was to make them
user-controls.
VarCodes
All icons of the family I’ve created bear the same appearance: an icon, and an
underlying name. But each member of the family has different properties, which may
be done by giving different “varCodes” to each variant. I choose a system of additive
varCodes, although not all combinations have sense:
moveable=1;
means the control may be dragged inside its window (like all icons in the
Finder);
doubleClickable=2;
means the control may generate an action by double-clicking it: it should then
take an “open” appearance (like folders, disks and trash icons that generate a window,
or like application icons that start-up applications);
trash=4;
means the control may “swallow up” another one released over its head. It should
highlight while the mouse, dragging the control to be swallowed up, is still down and
pointing to it (like trash, folders and disks icons in the Finder)
menu=8;
is a new type of control icon I’ve imagined : it should generate a pop-up menu of
icons when pressed. This is an alternate technique to the palette menus and tear off
menus. The menu is by the way bound to a window.
Some examples of possible combinations are listed below:
• a folder would be declared “movable + doubleClickable + trash” and its varCode
would therefore be 7;
• a growing menu of icons would be “menu + trash” i.e. 12 (“menu” for removing
or choosing items, “trash” to add items);
• an application icon would be declared “movable + doubleClickable” i.e. 3.
In fact, “menu” is exclusive of “movable” or “doubleClickable”.
Menu definition procedure and pop-up menus
Before building our custom control definition procedure, we must first build our
custom icons menus. At that point, the two first problems are
• to write a ‘MDEF’ code resource ;
• to make it work with pop-up menus.
Inside Macintosh indicates p.I-362 how to write ‘MDEF’s for pull-down menus.
In my alpha release of the fifth volume (for which the French Macintosh Development
Support failed to send me updates), I don’t find anything about pop-up menus nor about
custom menus. I just found two significant pieces of information in the Color Menu
Manager interface in my LightSpeed Pascal libraries -a new trap declared as
{1}
PROCEDURE PopUpMenuSelect (menu : MenuHandle;
top , left , popUpItem : INTEGER) : LONGINT;
inline $A80B;
and a constant :
mPopUpMsg=4; ( sic )
This latter statement appeared later to be false. I learned by disassembling the
standard code resource ‘MDEF’ 0 of the new system file, that only values ranging from
0 to 3 are accepted as messages, and that the one corresponding to pop-up menu
treatments is 3:
mPopUpMsg=3; ( right value )
By the way I learned that the routine responds to this new message by calculating
“menuRect”, given “menu”, “top”, “left” and “popUpItem” parameters of
PopUpMenuSelect transmitted respectively through the “theMenu”, “hitPt” and
“ whichItem” parameters from the menu definition procedure declaration :
{2}
PROCEDURE MyMenu (message : INTEGER;
theMenu : MenuHandle;
VAR menuRect : Rect;
hitPt : Point;
VAR whichItem : INTEGER);
Since I wrote most of this article, all of this has been confirmed by TechNote
#172 from the November 1987 release. It just took 6 months to get it!
Before getting TechNote #172, I wasn’t quite sure I hadn’t made a mistake, but
now I’m sure: hitPt is not a point! Instead it receives “left” and “top” inverted from
PopUpMenuSelect.
I also tried the trap with standard text menus. The two hints I shall give follow: (
I found the second by decompiling the ROM patches; next time I’ll first have a look to
Inside Macintosh p.351!)
• pass -1 as beforeID parameter to InsertMenu (the same as for hierarchical
menus) to indicate that theMenu is in the current menu list, but is not to be
drawn in the menu bar.
• pass a positive non-zero integer as MenuID to NewMenu or nothing will ever
appear on the screen (you may also store it in the ‘MENU’ resource read by
GetMenu, of course).
Debugging A Code Resource (Part 1)
I shall indicate two techniques to test and debug code resources under LightSpeed
Pascal. The first one, used here, is the roughest and should never be used for anything
else than debugging. I learned the second one from the best Macintosh programming
journal I know (I mean the April issue of MacTutor p.17 and p.30), and I should give
an example of the use I made of it further in this article.
The problem is to access and debug the source text of a code resource while
running a shell program that calls it via Menu Manager routines (or Control Manager
routines for ‘CDEF’s). Normally the code resources is compiled separately and
accessed through a handle to the ‘MDEF’ resource. The Menu Manager routines use to
lock the ‘MDEF’ resource upon entry, dereference the handle, jump to its beginning
and unlock it upon exit.
My technique consists in declaring the unit with the ‘MDEF’ source text in the
uses statement of a small debugging-purpose shell program, and I create a new menu
as follows :
{3}
myMenu := GetMenu(128);
myProcPtr := @main;
myMenu^^.menuProc := @myProcPtr;
This way, the handle and its dereferenced pointer point to the stack, not at a
masterpointer or a block within the heap. The HLock and HUnLock procedures may act
on the high order bit of these pointers, it has no influence on the addresses
(nevertheless be aware of TechNote #2 item 11). The Memory Manager never knows
about the block and never tries to move it.
With this trick, you may freely use all the debugging facilities of LightSpeed
Pascal: the Observe and LightsBug windows, the Step mode
Once all the bugs inside the ‘MDEF’ code have been fixed (or at least seam to),
you build your ‘MDEF’ code resource. I gave mine a ResID of 128. Under ResEdit, you
can see that the compiler gave to this resource a default attribute “purgeable”, you’d
never ask it to give. Instead I changed it to “locked” and “preload”, in order to have it
always under the hand (a disk access while pulling a menu is not user-friendly) and to
keep it in the low region of the application heap.
New Meaning of ‘MENU’ Resource
The ‘MDEF’ and ‘CDEF’ are not the only user resources I wrote for my
application. I like the flexibility of building all sort of data resources as well as
compiling code resources. In the current example, my menu consists of icons,
described by their names and their positions in the menu rectangle. It’s slightly
different from the standard ‘MENU’ resource information. But in order to use the Menu
Manager routines, I preferred interpreting the same ‘MENU’ resources in a different
way, rather than create a completely new resource type. Description of the resource
format given p.I-364 of Inside Macintosh should be replaced by :
Number of bytes Contents
2 bytes MenuId
2 bytes Placeholder for menu width
2 bytes Placeholder for menu height
2 bytes Resource ID of ‘MDEF’
2 bytes Place holder for ‘MDEF’ handle
4 bytes EnableFlags
n+1 bytes Title as Pascal string
for each menu item :
m+1 bytes Text of item as Pascal string
2 bytes Vertical coordinate of icon center
2 bytes Horizontal coordinate of center
1 byte 0, indicating end of menu items
(it is also a Pascal null string)
Note that this description occupies the same number of bytes that normal text
menus do, which ensures the ability to use the standard procedures.
This description is almost the same as the one you can teach to ResEdit; I created a
new ‘TMPL’ resource in the ResEdit file itself, which I gave the name ‘MPOP’.
However, in order to use the GetMenu routine, my menu resources shall not be of type
‘MPOP’ but of type ‘MENU’. This is accomplished by creating a new ‘MENU’ resource
and opening it with the “Open as” command to indicate we wish to use the ‘MPOP’
format instead of the ‘MENU’ one to edit our resources (shortcut for “Open as” is
shift-option-double-clicking).
The ‘TMPL’ resource describes the structure of the ‘MPOP’ resource, somewhat
like a Pascal record type describes the structure of a Pascal record variable (for more
details see the MPW chapter about ResEdit) :
Label Type
MenuID DWRD
width DWRD
height DWRD
procID DWRD
filler DWRD
enableFlags HLNG
title PSTR
***** LSTZ
menuItem PSTR
center.v DWRD
center.h DWRD
***** LSTE
Reading A Resource
In fact this new syntax allowed by ResEdit gives more generality and compactness
than Pascal records do: strings in Pascal records always occupy 256 bytes in memory,
even if only 10 are actually used. Consequently, Pascal is not able to decipher such
resources. So I had to write some inline assembly routines for this purpose. These
routines read a chosen type beginning at a given address that might be odd and return a
Pascal formatted value on the stack. For strings it returns a StringHandle on the stack,
pointing to a string of the actual size in the heap. I give here three of these inline
routines :