Apple II
Technical Notes
_____________________________________________________________________________
                                                  Developer Technical Support

Apple IIgs
#81:    Extended Control Ecstasy

Written by:    C.K. Haun                                             May 1990

This Technical Note discusses special features and concerns that should be 
considered when using the extended controls introduced in System Software 5.0.
_____________________________________________________________________________

Introduction

The extended controls introduced in System Software 5.0 allow the application 
programmer a great deal more freedom in designing and controlling 
applications.  The new features enhance the functionality of the controls and 
TaskMaster, but can cause confusion and consternation if you are careless with 
the new parameter block .  This Note also includes a discussion of the 
multipart nature of many of the extended controls and some pointers for 
writing extended custom controls.

Counting The Costs

One of the major stumbling blocks seen when programming the new extended 
controls is bad parameter counts.  Extended controls introduce parameter 
blocks and parameter counts to the Control Manager.  You need to fully 
understand the parameters required and the resulting parameter count for each 
control you create, or you can experience program problems that may be very 
confusing and difficult to track down.

Remember also that the Control Manager does not understand "skipping 
parameters."  If you are creating an extended radio button and you want key 
equivalents, but not a color table, you cannot ignore the color table 
parameter field.  There is no way to tell the Control Manager to "skip" a 
field during control creation; make sure you initialize all the fields to 
values that are meaningful--either a real pointer, handle, resource ID, or 
zeroes.  In this case, if you try to "skip" the color table and do not zero 
out the color table parameter field, the resulting radio button wears ugly 
colors you do not expect.

As you can imagine, miscounting parameters in other extended controls can 
produce confusing results, so the parameter count is the first place you 
should check when you're having difficulties creating extended controls.

For Rez users, the Types.Rez file contains extended control templates that 
automatically generate the correct count value, so programmers creating all 
their controls with the Resource Compiler should not have these problems.

Silly Little Bits

The other area of the new parameter block model that is giving folks trouble 
is the moreflags field.  This field hones the definition given by the 
reference fields and can cause you much grief if misused.  Make sure to set 
the reference bits to the values you require.  The bit settings have been 
standardized across all the extended controls, with %00 indicating a pointer, 
%01 indicating a handle, and %10 indicating a resource.  Remember also to set 
the bits for all the references you have--strings, color tables, or whatever 
else may be ambiguously referenced in the control.

If you accidentally use the wrong bit pattern, you can experience strange bugs 
ranging from garbled text to SysFailMgr caused by a nonexistent resource being 
referenced.  Again, Rez users can use the equates for all the reference 
specifiers in the Types.Rez file to avoid confusion and evil bugs.

The Parts are Greater than the Whole

To create some new extended controls, like pop-up menu controls and LineEdit 
controls, functions of different tool sets were combined.  Pop-up menu 
controls are a combination of the Control Manager and the Menu Manager, 
LineEdit controls are a blending of the Control Manager and the LineEdit tool 
set, and other new control types follow the same pattern.

This means that, at times, you have to go further into the documentation to 
find information.  Getting the text out of an LineEdit extended control is a 
multi-step process that is a good example of this type of problem.

MyLineEdit dc     i2'8'                   ; parameter count
           dc     i4'1'                   ; id number 1
           dc     i2'10,10,23,90'         ; control rectangle
           dc     i4'editLineControl'     ; process reference
           dc     i2'0'                   ; flags
           dc     i2'fCtlCanBeTarget+fCtlWantEvents+fCtlProcRefNotPtr'
                                          ; moreflags
           dc     i2'0'                   ; refcon
           dc     i2'15'                  ; maximum characters allowed
           dc     i4'0'                   ; no default text
MyLineEditHandle ds 4                     ; handle for the created control

           pea    0
           pea    0
           pea    0                       ;verb, single Extended control
           pushlong #MyLineEdit
           pushlong mywindowgrafport      ; window that control will reside in
           _NewControl2
           pla
           sta    MyLineEditHandle        ; save the control handle
           pla
           sta    MyLineEditHandle+2


When you want to get the text back out of that control later, you begin to 
experience what it means to have a control that is an amalgam of various 
tools.  You would start by using the control handle returned by NewControl2:

Scratch    equ    $0                      ; some scratch space
Scratch2   equ    $4

           lda    MyLineEditHandle        ; move the ControlHandle to
           sta    Scratch                 ; some direct page space
           lda    MyLineEditHandle+2
           sta    Scratch+2
           lda    [Scratch]
           tax
           ldy    #2
           lda    [Scratch],y             ; and dereference it, putting it 
           sta    Scratch+2               ; back in some dpage space to 
           stx    Scratch                 ; use it.

That gives you the pointer to the control record.  Stored in the control 
record is the handle of the LineEdit item that is actually controlling the 
text processing:

           pea    0                       ; make space for the text handle to 
           pea    0                       ; be returned
           ldy    #octlData               ; offset to the ctlData section
                                          ; of the ControlRecord
           lda    [Scratch],y             ; where the handle for the actual 
           tax                            ; LineEdit item was stored
           iny
           iny
           lda    [Scratch],y
           pha
           phx
           _LEGetTextHand                 ; ask for the handle for the text 
           pla                            ; in this LineEdit control
           sta    Scratch2                ; and now you have the handle to the 
           pla                            ; text you want.
           sta    Scratch2+2

The main point is that when you are using extended controls, you often cannot 
use the Control Manager to do everything that needs to be done.  You also need 
to understand and use the supplementary or "hidden" tool sets.

Here's another example, using a pop-up menu extended control, and in this case 
we define a font pop-up that contains all the font names currently available.

MyPopUpControl dc i2'9'                   ; parameter count of 9 
           dc    i4'1'                    ; control ID of 1
           dc    i2'2,2,0,0'              ; Position, upper left corner of the 
                                          ; window, let Control Manager 
                                          ; calculate full size
           dc    i4'popUpControl'         ; def proc for PopUp
           dc    i2'0'                    ; flags
           dc    i2'fCtlWantEvents+fCtlProcRefNotPtr'
                                          ; more flags
           dc    i4'0'                    ; ref con
           dc    i2'0'                    ; title width, will be calculated
           dc    i4'mymenu'               ; pointer to actual menu structure
           dc    i2'500'                  ; initial value, item number of item
                                          ; to be displayed in popup at 
                                          ; creation


mymenu     dc    i2'0'                    ; version number, should be 0
           dc    i2'200'                  ; menu ID number
           dc    i2'0'                    ; menu flags
           dc    i4'mymenutitle'          ; pointer to menu title
           dc    i4'mymenuitem1'          ; first menu item
           dc    i4'mymenuitem2'          ; second menu item
           dc    i4'0'                    ; null terminator, end of menu
mymenutitle str 'Font'

mymenuitem1 dc i2'0'                      ; version number
           dc i2'500'                     ; item number
           dc i2'0'                       ; no hot keys
           dc i2'0'                       ; not checked
           dc i2'0'                       ; item flags, no special drawing
           dc i4'mymenuitem1title'
mymenuitem1title str 'Plain'

mymenuitem2 dc i2'0'                      ; version number
           dc i2'501'                     ; item number
           dc i2'0'                       ; no hot keys
           dc i2'0'                       ; not checked
           dc i2'1'                       ; item flags, bold face this one
           dc i4'mymenuitem2title'
mymenuitem2title str 'Bold'

Now create this control:

           dc     i2'501'                 ; item number
           pea    0
           pea    0
           pushlong mywindow              ; target window grafptr
           pea    0                       ; verb, single control pointer
           pushlong #MyPopUpMenu
           _NewControl2
           pulllong mypopuphandle         ; save the handle

This pop-up menu control created is not associated with the menu bar across 
the top of the desktop.  You can consider each of your pop-up menu controls as 
separate menu bars, so if you want to perform Menu Manager calls on a pop-up 
menu control, you need to set the menu to point at your pop-up menu control.  
In this example, to add all the fonts available to the pop-up menu you would:

           pea    0
           pea    0                       ; space to hold current bar
           _GetMenuBar                    ; get the handle to the current 
                                          ; menu bar
           pushlong mypopuphandle
           _SetMenuBar
           pea    200                     ; id number of this menu
           pea    502                     ; first font family ID number to use
           pea    0                       ; fontspecbits
           _FixFontMenu
           pea    0
           pea    0
           pea    200
           _CalcMenuSize                  ; re-size the popup menu
           _SetMenuBar                    ; restore the previous menu as the 
                                          ; current menu

Controls That Are Not Controls

The new picture extended control is not a "full-fledged" control; it has been 
provided to simplify your programming tasks.  The picture control does not 
support normal mouse hit testing and highlighting.  Think of it as a built-in 
extension to your content drawing routine, and not as a control.  It is 
provided to allow you to refresh your whole window with a single DrawControls 
call, instead of drawing the controls and then drawing pictures.  The icon 
button extended control has been provided as the graphic full-function 
control.  If you need or want a fully functional control that uses a picture, 
you should consider writing your own custom control procedure.

It's Not Dirty, It's Text

There has been some confusion about determining if a TextEdit record has been 
changed.  The documentation has been a little vague, and the process itself 
has mislead some people.  Here is The Truth:  there is a TextEdit dirty flag, 
and you can use it and rely on it to tell you when a TextEdit record has 
changed.

The TextEdit dirty flag is bit 6 (fRecordDirty in the E16.TextEdit interface 
file) of the ctlFlag byte.  This has caused some confusion because the ctlFlag 
byte is at offset $12 in the control definition template, and it is at offset 
$10 in the TextEdit or Control record.  Just remember that it is not in the 
same place in the record as it is in the template.

If it is set, then the TextEdit or Control record has been changed since the 
last time the dirty bit was cleared.  The dirty bit is clear initially when 
you create the TextEdit or Control record.  Anytime after that, if the user 
enters text into the TextEdit record, TextEdit sets the dirty flag.  It is up 
to your application to clear the dirty flag; TextEdit has no way of knowing 
when you've saved or cleared data.

Custom Extended Controls

Custom controls can also benefit from all the advantages of extended controls.  
You can create a custom control that uses a template, can be a resource, has a 
definition procedure that is a resource, and responds to all the new control 
calls.  If you write an extended custom control or upgrade a previously-
written custom control, there are new messages and changes to existing 
messages of which you need to be aware.  These changes are documented in 
volume 3 of the Apple IIgs Toolbox Reference. 

Putting your custom control definition procedure in a resource can 
significantly enhance the functionality of the custom control.  You may find 
it easier to add to all of your programs and you do not have to manage the 
code space required. If you do write a custom control definition procedure and 
want to store it as a resource, here are some hints for success.

First, the code you store in your resource fork must be fully compiled and 
linked code.  The code resource converter uses the System Loader to load the 
code, so the code must be executable code, not object code.

Second, be sure to set the fixed and convert bits of the resource attributes 
for your code resource.  The fixed bit needs to be set so your code does not 
move once it's been loaded and relocated.  The convert bit must be set to tell 
the Resource Manager to call the code resource converter when it loads this 
resource. The resource type for control definition procedures is rCtlDefProc, 
$800C.

Third, keep in mind that this definition procedure may be purged and reloaded 
whenever the Memory Manager needs the space.  This means that you cannot store 
any information in your definition procedure if you want to keep track of it 
between calls to the definition procedure.  If you do, and your definition 
procedure gets purged and reloaded, you lose that data.

If you need data space for your custom control, use the control record as your 
stash.  You can easily either use the fields already provided in the control 
record, or you can expand the control record to as much space as you need 
(within sensible limits) and store your data there.

Warning:  Control definition procedures are initially loaded with 
          purge level zero.  When they are released, they are given 
          purge level three.  If they are then reloaded, the Resource 
          Manager does not change the purge level back to zero--your 
          definition procedure may then be purged (even while 
          executing) unless its handle is locked.  The solution is to 
          lock your definition procedure handle within the procedure:

                   myPosition    pea    0              ; space for result
                                 pea    0
                                 pushLong #myPosition
                                 _FindHandle
                                 _HLock

          and unlock your handle with HUnlock on exit.  This keeps 
          your procedure safe, while not creating "code islands," 
          which clog up memory.

Conclusion

The extended controls provided in System Software 5.0 and later are a great 
leap forward for programmers.  They relieve the application of much of the 
tedious detail code that relates to housekeeping, not the guts of application 
programming.  Used in combination with the enhanced TaskMaster, you can have 
an application's visual interface up and running a lot faster, leaving you 
more time to work on the heart of your application.


Further Reference
_____________________________________________________________________________
  o  Apple IIgs Toolbox Reference, Volumes 1 through 3.

