TweetFollow Us on Twitter

Rom Ref DA
Volume Number:3
Issue Number:10
Column Tag:Advanced Mac'ing

Rom Reference DA for Inside Mac in C

By Frank Alviani, Contributing Editor, Odesta Corp. MPW Guru

Wearing out yer copy of IM?

After you’ve been programming the Mac for a while, you find that you’re starting to wear out your copy of Inside Macintosh. It’s not that you’re looking up the hundreds of calls in order to figure out what they do, it’s just that no human being can remember that many parameter sequences. With the storage capacity available nowadays, this is rather silly - we should be letting the Mac do the lookup for us - and that is exactly the purpose of the ROMRef DA.

This desk acccessory is NOT a help facility (altho one could be built from it rather easily) but only a compilation of the format for every call in volumes 1-3 of IM. The advantage is that looking up a call places a copy of the call, with all parameters, directly on the clipboard, where it can be simply pasted into the program.

I used the Clock DA by Don Melton as a skeleton for ROMRef, and it proved mighty helpful; thanks oodles, Don!! Two versions are included: one operates in ‘C’ format, while the other is in Pascal format. The ‘C’ version is set up to put the calls in the format used by Consulair C (4.53 was used to develop this), while the Pascal version is non-specific (I don’t work in Pascal).

Operation: is quite simple. The data file should be in the “blessed folder” or with the editor. When the DA is invoked, it puts a menu up. Select “Lookup” and a selection box appears listing all of the toolbox managers in alphabetical order:

Fig. 1 Our own RomRef Data Base Manager!

Once you have selected a manager, a second window is displayed with all of the calls for that manager again listed in alphabetical order:

When a call is selected, any of the 1st four buttons on the right will place the call on the clipboard. Either of the accept buttons will cause the call to replace the former contents; either of the append buttons will cause the call to be appended to the previous contents. The “continue” option allows you to return to the manager selection window for another call.

Fig. 2 Getting the rom call on the clipboard

Two entries on the menu affect how the call will be formatted on the clipboard. “Show Memory Mashers” causes a comment to be placed before the call if the call selected can possibly cause memory to be re-arranged. “Disable Typecasting” is available because the default is to have every variable in a call shown with its type; you may not always want this.

Internals: This DA does NOT use the list manager, since I wanted it to work with 64K ROM machines. It turned out to be very illuminating about how to work with (and around) the dialog manager.

One advantage of the approach taken by Don’s DA is in the simplicity of debugging. The locking of the DA when a menu routine is invoked allowed me to debug exactly as if it were a normal application, with the code locked in the heap. Having function names embedded by the compiler allowed TMON (best thing since peanut butter on hot toast!) to work to its fullest and kept me from going absolutely berserk in the early stages. I found that the scrolling selection window was the most complex part of the program to debug. I used the DA Sampler for testing.

Dialog windows within a Desk Accessory: are almost identical to those in a normal application except for one subtlety that drove me crazy for several days...

Macintosh Revealed mentions a bit in the event record that is used to indicate to an application if a DA window has just closed. According to Apple, applications should not depend on this - but MacWrite does! (it crashed with the famed ID=02 bomb every time I closed a ROMRef window..) Therefore, I have to set the windowType field of the dialog box window record to “dialogKind” when starting processing (so the Dialog Manager will recognize it) and reset it to a DA window just before closing the window (so application programs won’t croak in surprize). With the windowType fields properly set, ROMRef now works with all of the editors I have tried it with, including MacWrite and MacAuthor. (For unknown reasons I honestly haven’t pursued, Word doesn’t crash, but ROMRef doesn’t affect its clipboard after the first lookup. If you do all your program editing in Word and track this down, please let me know what’s wrong)

Scrollbars within the Dialog Manger: The scrolling selection window is composed of two user items: the text box and the scrollbar box. The scrollbar is declared to RMaker as a user item and actually created in the application with NewControl. Using a scrollbar within the dialog manager turns out to be a truly awesome pain-in-the-touche, whereas simply using the dialog manager to detect a click in the scrollbar rectangle becomes very easy to deal with.

When a click is detected within the scrollbar box, we simply use GetMouse() to retrieve the current position of the mouse, and use the standard control manager functions. The list being displayed is a text edit record (CRs end lines) and so the amount to scroll is a simple function of number-of-lines-scrolled times the lineheight.

One matter that added a little complexity to scrolling was dealing with trying to scroll beyond the limits of the list. The scrollbar maximum is set so that the bottom line of the list is at the bottom of the window; however, you must be aware of when you’re at the limits and ignore attempts to scroll further.

A filter function is used to deal with keyboard events. The cursor keys on a Mac+ keyboard work as expected, and typing an alphabetic character causes the DA to start searching the list for the first entry starting with that character (or the first entry following if necessary). I don’t have full type-ahead, as in the standard file selection box, but this was easy to implement and still useful. As per the user interface guidelines, the enter and return keys return the “accept” button.

The same lookup routine is used for both dialog windows and can easily be extracted for general use elsewhere; I’ve already adapted it for multiple use in an application I’me working on professionally.

Data Management: Since the actual processing in the DA is rather simple, how to manage the tons of data became the real challenge. After discarding several fairly complex indexing schemes initially, I settled on using the Resource Manager, which worked out nicely. There are 3 basic resource types involved:

(1) Name Lists: The list of manager names, and the lists of routine names in each manager, are stored as ‘ROMN’ resources.

(2) ROM Calls: Each ROM call is stored as a ‘ROMC’ resource. Each variable is prefixed by its type in a simple condensed format.

(3) Abbreviations: This is the list of expansions for each of the data type abbreviations used in the ROM calls.

Since we are dealing with a large number of resources (there are 640 calls in the data file, plus the name lists) and the data had to be as compact as possible if it was going to be useful, I used several tricks to save space.

At the start of a ROMN (name list) resource, before the text data, there are 2 16-bit integers. The first gives the number of lines in the data; this is convenient for setting the scrollbar maximum. The second field gives the starting resource number for the calls listed. The calls for a manager are numbered sequentially from the number listed in the ROMN resource, so the resource ID for a call is simply its relative position in the list plus the “base” resource number. This avoided having to store the resource ID with each individual name (and saved about 1.5K). It also means that additional calls and managers can be added at any time; simply choose an “unused” range for the new manager.

ROM Call Formatting: As mentioned above, the ROM call prototypes are stored in a simple compressed format. Each call is preceeded by a 1-byte flags field; currently, all it indicates is whether or not the call is a “memory masher”.

Abbreviations in a call are indicated by bytes with a value of $80 or more. These abbreviations fall into 2 classes: $80 - $BF are non-VAR datatypes, while the range of $C0 - $FF is identical to the lower range, but are considered VAR types. An abbrev- iation is shifted to the range $0-$3F and used to index into a table; this table is simply a “rom abbreviation” (ROMA) resource that was loaded during initialization and detached.

The expansion of an abbreviation is the only difference between the ‘C’ and Pascal versions (other than the names of the datafiles opened). Being initially written for ‘C’, the processing is simpler for that: simply look up the abbreviation and substitute, formatting it as (type *) if it is a ‘var’ variable. The expansion for Pascal is more complex, since the VAR and datatype are on opposite ‘ends’ of the variable name.

Clipboard manipulation: this is pretty conventional, except for the appendScrap function. This assumes there is only 1 data type on the clipboard. Following the data type (a 4 byte field) is the length; I copy the existing text to a working buffer, append the new text, and copy the new text back to the scrap, updating the length. Simply doing 2 PutScraps will append the text, but not update the length, making the new text unaccesable. It would not be much more complicated to deal with multiple data types on the clipboard.

Data File Construction: This was, not surprisingly, the most laborious part of the project, and changed several times while under construction.

Heavy use is made of macros and assembler variables. Macros are created for each datatype, and generate the abbrev- iation byte preceeding each formal parameter. Changing the text in the ROMA resource corresponding to a given macro will change the expansion. I wasn’t entirely consistant with some of the subtly different (but functionally identical) datatypes, since the typecasting is generally only a reminder and not left in the working program.

Assembler variables are used to automatically generate the resource IDs in ascending sequence; the variable at the beginning of a sequence is set to allow for “pre-incrementing”.

The sources for the data file are for the ‘C’ format calls. The only real difference between the ‘C’ and Pascal forms is that Consulair ‘C’ requires all structures to be referenced by pointers, even those that are not VAR variables in the Pascal sense. Thus, converting the data file to Pascal conventions will simply involve removing the VAR status of most structures and rebuilding.

Construction: is fairly conventional. The DA is built exactly as in Don Melton’s article, using his files (with 1 header file renamed to reflect a change between Consulair versions). See MacTutor Vol. 2 No. 4 (April, 1986).

The data files are in assembler; they are assembled and then linked to form the final data file. Assembling the data files is quick, but linking seems to take forever. On a Mac+ with no RAM disk, linking the data file takes 8 minutes, although the assembly only takes about 1. Don’t worry...

Miscellaneous: I want to thank Don Melton again for his DA article; I had been having no luck with DAs until then. I also want to highly recommend MEdit, by Mathias Aebi; it allows you to build editing macros to automate repetitive tasks. When I decided to change approaches to the data file, it allowed me to reformat about 80K of source in less than 1 hour!

It should not be difficult to adapt ROMRef into an online help facility for the toolbox. After the routine had been selected, the routine that currently expands the rom call would bring up a small dialog box and display the help text instead. I think the text would be rather terse, since the amount involved would be even larger than the current file; most likely, a hard disk would be required to work with adequate information. A different set of abbreviations could be built to compress the most common words in the database, and the ‘VAR’ mechanism would be un-needed. If anyone does use ROMRef to build such a DA, please put it out for the public to use!!

/*  A ROM Reference Desk Accessory  */
/*          Frank Alviani           */
/*           Version 1.1            */
/*       8:36:39 PM  8/5/86         */
/*                                  */
/*  Thanks to Don Melton for making */
/*  this a whole bunch easier!      */

#Options R=4 Z K
#include <MacDefs.h>
#include <QuickDraw.h>
#include <Control.h>
#include <TextEdit.h>
#include <Dialog.h>
#include <Menu.h>
#include <Events.h>
#include <Desk.h>
#include <DeskAccessory.c>
#include <Resource.h>

/* MODIFIED DEFINITIONS

*** IMPORTANT *** Other alternate elements of the OpParamType union structure 
are not defined here!!!

The CntrlParam structure also must be defined because OSIO.h is not included. 
However, it remains unaltered. */

#define OsType long
union __OP
    { 
    struct
        {
        short menuID;
        short menuItem;
        } menuData;
    Ptr event;
    };

#define OpParamType union __OP

struct __CP
    {
    struct __CP *ioLink;
    short ioType;
    short ioTrap;
    Ptr ioCmdAddr;
    ProcPtr ioCompletion;
    short ioResult;
    char *ioNamePtr;
    short ioVRefNum;
    short ioRefNum;
    short CSCode;
    OpParamType csp;
    };

#define CntrlParam struct __CP

typedef struct
    {
    char typeName[4];
    } ResType;

typedef struct {
long        scrapSize;
Handle      scrapHandle;
short       scrapCount;
short       scrapState;
char        *scrapName;
} ScrapStuff, *ScrapStuffPtr;

#define NULL 0
#define FALSE 0
#define TRUE 1
#define geneva      3
#define NAMES_IN_BOX 7
#define TIX ((long *) 0x16A)

#define ACCEPT 1
#define ACCEPT_CONT 2
#define APPEND 3
#define APPEND_CONT 4
#define CANCEL 5
#define NBOX 7
#define SBAR 8

#define FRONT_WINDOW -1

/* SETUP DA HEADER AND GLUE ROUTINES
*** IMPORTANT *** Invoke this macro BEFORE declaring any global variables 
or defining any Mac C functions!!!

Macro parameters:
    1       Name of desk accessory (enclose text in single quotes)
    2       Resource ID of desk accessory (12-31 inclusive)
    3       Flags
    4       Delay
    5       Event Mask
    6       Request for global variable allocation: NeedGlobals or NoGlobals
*/

#asm

 DeskAccessory ‘ROM Ref’,12,$0400,0,$0142,NeedGlobals

#endasm

/* GLOBAL VARIABLES */
short     ownedID;
short     no_casting; /* 0=typecast 1=don’t typecast */
short     mem_mash;   /* 1=include comment */
short      selection;
MenuHandle hRRMenu;
DialogPtr  abtDlgPtr, mgrDlgPtr, rtnDlgPtr;
long       lastClick;
short      lastPick;     /* double-click test */
short      data_refNum;  /* vol ref num data file */
short      old_v;        /* for arrow-scrolling */
ControlHandle   rtnScrlH, namScrlH; 
 /* scroll bar in routine window */
ControlHandle   vScrlH;   
 /* “generic” for ModalDialog filterProc */
Handle   abTblH;   /* handle to abbreviation table */
TEHandle hTE;      /* for names selection routine */
Rect     textR, TERect;
char     call[256];    /* sample here */
ScrapStuffPtr   sInfo;

/*~Open/Close/Control~ -- Open Routine -- */
short open(pb, dce)
CntrlParam      *pb;
DeviceControl   *dce;
{
GrafPtr         oldPort;
short           item, type, err, def_vol;
ControlHandle   ctlH;
Ptr             tPtr;
short           pbCall();

 ownedID = 0xC000 - (32 * (1 + dce->dCtlRefNum));
 dce->dCtlMenu = ownedID;

  if (!dce->dCtlWindow)
   { hRRMenu = GetMenu(ownedID);
     HNoPurge(hRRMenu);

     if (!(mgrDlgPtr = (DialogPtr) NewPtr(sizeof(DialogRecord))))
          return -1;
     mgrDlgPtr = GetNewDialog(ownedID, mgrDlgPtr, FRONT_WINDOW);
     GetDItem(mgrDlgPtr, SBAR, &type, &namScrlH, &textR);  /* scrollbar 
*/
     namScrlH = NewControl(mgrDlgPtr, &textR, “\px”, FALSE, 0, 0, 0, 
scrollBarProc, 0); 
     if (!(rtnDlgPtr = (DialogPtr) NewPtr(sizeof(DialogRecord))))
          return -1;
     rtnDlgPtr = GetNewDialog(ownedID+1, rtnDlgPtr, FRONT_WINDOW);   
 
     GetDItem(rtnDlgPtr, SBAR, &type, &rtnScrlH, &textR);  /* scrollbar 
*/
     rtnScrlH = NewControl(rtnDlgPtr, &textR, “\px”, FALSE, 0, 0, 0, 
scrollBarProc, 0);  
     GetDItem(rtnDlgPtr, NBOX, &type, &ctlH, &textR);  /* get scrollBOX 
rect */
     TERect = textR;
     InsetRect(&TERect, 2, 2);
     if (!(abtDlgPtr = (DialogPtr) NewPtr(sizeof(DialogRecord))))
          return -1;
     abtDlgPtr = GetNewDialog(ownedID+2, abtDlgPtr, FRONT_WINDOW);
        /* open data file */ 
     if ((data_refNum = OpenResFile(“\pRom Reference Data”)) == -1)
          return -1;
     if ((abTblH = GetResource(‘ROMA’, 1)) == NULL)   /* get abb. table 
*/
          return -1;
     no_casting = 0; mem_mash = 0;
     activate();
  }
  return 0;
}

/* -- Close -- */
short close(pb, dce)
CntrlParam      *pb;
DeviceControl   *dce;
{
    deActivate();
    ReleaseResource(hRRMenu);
    ReleaseResource(abTblH);
    DisposeDialog(mgrDlgPtr);
    DisposeDialog(rtnDlgPtr);
    DisposeDialog(abtDlgPtr);
    dce->dCtlWindow = (WindowPtr) NULL;
    CloseResFile(data_refNum);  /* close data file */
    return 0;
}

/* -- Control -- */
short control(pb, dce)
CntrlParam      *pb;
DeviceControl   *dce;
{
EventRecord     *theEvent;

    switch (pb->CSCode)
      { case accEvent:
          theEvent = (EventRecord *) pb->csp.event;
          if (theEvent->what ==activateEvt)
              if (theEvent->modifiers & activeFlag)
                activate();
          break;
        case accMenu:
          doMenu(pb, pb->csp.menuData.menuItem, dce);
          break;
    }
  return 0;
}

activate()
{
  (*hRRMenu)->menuID = ownedID;
  InsertMenu(hRRMenu, 0);
  DrawMenuBar();
}

deActivate()
{
    DeleteMenu(ownedID);
    DrawMenuBar();
}

/*~Menu Stuff~ -- Handle Menu Invocations -- */
doMenu(pb, menuItem, dce)
CntrlParam      *pb;
short           menuItem;
DeviceControl   *dce;
{
short       theItem;
GrafPtr     tGPtr;

    switch (menuItem)
      { case 1:     /* ABOUT */
       dce->dCtlFlags &= 0xFBFF; /* clear dCtlEnable */
       dce->dCtlFlags ^= 0x4000; /* set dNeedLock */

       ((WindowPeek) abtDlgPtr)->windowKind = 2;  /* dialogkind */
       ShowWindow(abtDlgPtr);
       BringToFront(abtDlgPtr);
       SetPort(abtDlgPtr);
       ModalDialog(NULL, &theItem);
       ((WindowPeek) abtDlgPtr)->windowKind = dce->dCtlRefNum;
       HideWindow(abtDlgPtr);

       dce->dCtlFlags ^= 0x0400; /* set dCtlEnable */
       dce->dCtlFlags &= 0xBFFF; /* clear dNeedLock */
          break;
      case 2:     /* LOOKUP CALLS */
       dce->dCtlFlags &= 0xFBFF; /* clear dCtlEnable */
       dce->dCtlFlags ^= 0x4000; /* set dNeedLock */

       findRtn(dce);

       dce->dCtlFlags ^= 0x0400; /* set dCtlEnable */
       dce->dCtlFlags &= 0xBFFF; /* clear dNeedLock */
          break;
      case 3:     /* DISABLE TYPECASTING */
       if (no_casting)       /* was NO, now YES */
          { no_casting = 0;
            CheckItem(hRRMenu, 3, FALSE);
          }
        else
          { no_casting = 1;
            CheckItem(hRRMenu, 3, TRUE);
          }
         break;
      case 4:     /* INCLUDE ‘MASHES MEMORY’ COMMENT */
          if (mem_mash)
            { mem_mash = 0;
              CheckItem(hRRMenu, 4, FALSE);
            }
          else
            { mem_mash = 1;
              CheckItem(hRRMenu, 4, TRUE);
            }
          break;
        case 5:     /* CLOSE */
          close(pb, dce);
          break;
      }
    HiliteMenu(0);
}

/*~Lookup Code~ -- Heart of the DA -- */
findRtn(dce)
DeviceControl   *dce;
{
short       the_manager, item, base_res_no, pick;
long        scrap_err, call_len;
short       BoxPick();

  get_mgr:
    /* use “select manager” dialog */
    dce->dCtlWindow = 0;
    /* get titles for selected manager */
    SetPort(mgrDlgPtr);
    item =  BoxPick(mgrDlgPtr, namScrlH, 99, &the_manager, &base_res_no);
    HideWindow(mgrDlgPtr);
    if (item == CANCEL) return;
      
    /* get titles for selected manager */
    SetPort(rtnDlgPtr);
    item =  BoxPick(rtnDlgPtr, rtnScrlH, the_manager+1, &pick, &base_res_no);
    if (item < CANCEL )
      { expandCall(base_res_no+pick, &call_len);
        if (call_len)
          { if (item < APPEND )
              { ZeroScrap();
                scrap_err = PutScrap((long) call_len, ‘TEXT’, call);
              }
            else
              AppendScrap((long) call_len, ‘TEXT’, call);
          }
      }

    ((WindowPeek) rtnDlgPtr)->windowKind = dce->dCtlRefNum;
    HideWindow(rtnDlgPtr);

    if (item == ACCEPT_CONT || item == APPEND_CONT)     
 /* keep it up! */
      goto get_mgr;
}

/* -- assumes port is properly set before entry -- */
   /* -- returns item_no from modal dialog box -- */
short BoxPick(dPtr, scrlH, resNo, sel, base)
DialogPtr       dPtr;
ControlHandle   scrlH;
short           resNo;
short           *sel;   /* zero-based! */
short           *base;
{
short       filter();
Handle      nameListH;  /* handle to names-list res */
long        call_len, nameList_len, ticks;
short       res_ct, done, item, l_no, sel_st, sel_en;
Point       pt;

  if ((nameListH = GetResource(‘ROMN’, resNo)) == NULL)
      { SysBeep(60);
        return CANCEL;
      }
    nameList_len = SizeResource(nameListH);
    HLock(nameListH);
    res_ct = *((short *) *nameListH);   
 /* ct of call resources */
    *base = *((short *) *nameListH+1);  
 /* starting call res # is 2nd short! */

    hTE = TENew(&TERect, &TERect);
    (*hTE)->txFont = geneva;
    (*hTE)->crOnly = -1;        /* CR breaks only */
    (*hTE)->txSize = 12;
    TESetText(*nameListH+4, nameList_len-4, hTE);
    TECalText(hTE);
    TESetSelect((*hTE)->lineStarts[0], (*hTE)->lineStarts[1], hTE);

    ((WindowPeek) dPtr)->windowKind = 2;
    ShowWindow(dPtr);
    BringToFront(dPtr);
    FrameRect(&textR.top);
    TEUpdate(&TERect.top, hTE);
    TEActivate(hTE);
    ShowControl(scrlH);
    SetCtlMin(scrlH, 0);
    if ((*hTE)->nLines > NAMES_IN_BOX)   
 /* set up scrollbar */
      SetCtlMax(scrlH, (*hTE)->nLines-NAMES_IN_BOX);
    else
      SetCtlMax(scrlH, 0);
    SetCtlValue(scrlH, 0);

    done = FALSE; selection=0;
    old_v = 0;
    vScrlH = scrlH;
    while (!done)
      { ModalDialog(filter, &item);   
 /* filter for keystrokes only */
        switch (item)
          { case ACCEPT:
            case ACCEPT_CONT:
            case APPEND:
            case APPEND_CONT:
            case CANCEL:
              done = TRUE;
              break;
            case NBOX:
              GetMouse(&pt);
              ticks = *TIX;
              l_no = (pt.v - textR.top) / (*hTE)-> lineHeight; /* relative 
line# */
              selection = GetCtlValue(scrlH) + l_no;
              if ((lastClick + 30) > ticks)
                { item = ACCEPT;  
 /* double click in same item */
                  done = TRUE;
                  break;
                }
              sel_st = (*hTE)->lineStarts[selection];
              if (selection >= res_ct)
                sel_en = 32767;
              else
                sel_en=(*hTE)->lineStarts[selection+1];
              TESetSelect(sel_st, sel_en, hTE);
              TEActivate(hTE);
              lastPick = selection;
              lastClick = ticks;
              break;
            case SBAR:
              nameScroll(dPtr);
              break;
          }
      }
    TEDispose(hTE);
    HUnlock(nameListH);
    ReleaseResource(nameListH);
    *sel = selection;
    return item;
}

/* -- Append to scrap,updating scrapCount-Memory Only -- */
/* assumes only 1 data type in desk scrap */
AppendScrap(len, type, str)
long        len;
long        type;   /* 4-char string */
char        *str;
{
long        sSize, dSize;

        sInfo = (ScrapStuffPtr)0x960;
        if (sInfo->scrapState <= 0) return;     
 /* can’t do anything */
        sSize = GetHandleSize(sInfo->scrapHandle);
        dSize = *((long *)(*sInfo->scrapHandle) + 1);   
 /* get existing len */
        SetHandleSize(sInfo->scrapHandle, sSize + len); 
 /* make room */
       *((long *)(*sInfo->scrapHandle) + 1) = dSize + len;
   BlockMove(str, (*sInfo->scrapHandle + 8 + dSize), len);
}

/*~Scrolling~ -- Filter Events, Handle Scrolling, etc. -- */
short filter(dPtr, ePtr, item)
DialogPtr       dPtr;
EventRecord     *ePtr;
short           *item;
{
#asm
    link        A6,#0           ;no locals
    movem.l     D1-D2,-(sp)     ;save
    move.l      16(A6),D0
    move.l      12(A6),D1
    move.l      8(A6),D2
    jsr         md_filter       ;call C routine
    movem.l     (SP)+,D1-D2
    unlk        A6
    move.l      (SP)+,A0        ;return addr
    add.l       #12,sp
    move.b      D0,(SP)         ;return condition
    jmp         (A0)
#endasm
}

/* uses global “vScrlH” to access vertical scrollbar in MD window */
short md_filter(dPtr, ePtr, item)
DialogPtr       dPtr;
EventRecord     *ePtr;
short           *item;
{
short           part, new_v, i, j, k, dV;
short           sel_st, sel_en, delta;
char            ch, ch2, key;
Ptr             tPtr, base;
short           nameScroll();

    switch(ePtr->what)
      { case mouseDown:
          return FALSE; /* handle normally */
          break;
        case autoKey:
        case keyDown:   /* select by 1st letter, cursor keys, etc. */
          ch = ePtr->message & 0xFF;
          if (ch==0x03 || ch==0x0D)   /* ent or ret */
            { *item = 1;    /* accept */
              return TRUE;
            }
          /* check for up/down arrow keys */
          if (old_v <= GetCtlMax(vScrlH))   
 /* don’t update if in last paneful */
            old_v = GetCtlValue(vScrlH);
          j = GetCtlMax(vScrlH);
          TEDeactivate(hTE);
          TESetSelect(0, 0, hTE);
          key = (ePtr->message & 0xFF00) >> 8;
          if (key == 0x4D) /* up arrow on Mac+ */
            { i = old_v-1;
              if (i < 0) i = 0;
              goto qa1;
            }
          if (key == 0x48) /* down arrow on Mac+ */
            { i = old_v + 1;
              goto qa1;
            }
/* look up 1st entry starting with given key or higher */
          ch &= (~0x20);   /* force uppercase */
          HLock((*hTE)->hText);     
 /* lock text for examination */
          base = *(*hTE)->hText;
          for (i=0;i<j;i++)
            { tPtr = base + (*hTE)->lineStarts[i];
              ch2 = *tPtr & (~0x20);    
 /* 1st char of line, upper-cased */
              if (ch2 >= ch)            
 /* found desired line */
                break;
            }
          HUnlock((*hTE)->hText);
        qa1:
          if (i <= j)   /* in normal range, scroll */
            { dV = (old_v - i) * (*hTE)->lineHeight;
              SetCtlValue(vScrlH, i);
              TEScroll(0, dV, hTE);
            }
          
          if (i >= GetCtlMax(vScrlH)+NAMES_IN_BOX)
            { i = GetCtlMax(vScrlH)+NAMES_IN_BOX-1;   
 /* can’t go too far */
              sel_en = 32767;
              k = (*hTE)->nLines-1;
              sel_st = (*hTE)->lineStarts[k];
            }
          else
            { sel_en = (*hTE)->lineStarts[i+1];
              sel_st = (*hTE)->lineStarts[i];
            }
          TESetSelect(sel_st, sel_en, hTE);
          old_v = i;
          selection = i;    
 /* in global so ACCEPT works */
          TEActivate(hTE);
          return TRUE;
          break;
        default:
          return FALSE;
          break;
      }
}

void nameScroll(dPtr)
DialogPtr   dPtr;
{
short           part, new_part, old_v, new_v, dV;
ControlHandle   ctlH;
Point           pt;
void            scroll_up(), scroll_dn();

    GetMouse(&pt);
    if (part = FindControl(&pt, dPtr, &ctlH))
      { old_v = GetCtlValue(ctlH);
        switch (part)
          { case inThumb:
              new_part = TrackControl(ctlH, &pt, NULL);
              if (new_part == part)   /* redraw box */
                { TEDeactivate(hTE);
                  new_v = GetCtlValue(ctlH);
                dV = (old_v - new_v) * (*hTE)->lineHeight;
                  TEScroll(0, dV, hTE);
                }
              break;
            case inUpButton:
              TrackControl(ctlH, &pt, scroll_up);
              break;
            case inDownButton:
              TrackControl(ctlH, &pt, scroll_dn);
              break;
            case inPageUp:
              new_v = old_v - (NAMES_IN_BOX-1);
              if (old_v-new_v < 0)
                { dV = old_v * (*hTE)->lineHeight;    
 /* stop at beginning */
                  SetCtlValue(ctlH, 0);
                }
              else
                { dV = (NAMES_IN_BOX-1) * (*hTE)->lineHeight;
                  SetCtlValue(ctlH, new_v);
                }
              TEScroll(0, dV, hTE);
              break;
            case inPageDown:
              new_v = old_v + (NAMES_IN_BOX-1);
              if (new_v > GetCtlMax(ctlH))
                { dV = -(GetCtlMax(ctlH) - old_v) * (*hTE)->lineHeight;
                  SetCtlValue(ctlH, GetCtlMax(ctlH));
                }
              else
                { dV = -(NAMES_IN_BOX-1) * (*hTE)->lineHeight;
                  SetCtlValue(ctlH, new_v);
                }
              TEScroll(0, dV, hTE);
              break;
          }
        selection = new_v = GetCtlValue(ctlH);
        TESetSelect((*hTE)->lineStarts[new_v], (*hTE)->lineStarts[new_v+1], 
hTE);
        TEActivate(hTE);
      }
}

void my_scroll_up(theControl, part)
ControlHandle   theControl;
short           part;
{
short   v;

    if (part == inUpButton)   /* */
      { v = GetCtlValue(theControl);
        if (v == 0) return;
        SetCtlValue(theControl, v-1);
        TEScroll(0, (*hTE)->lineHeight, hTE);
      }
    return;
#asm
scroll_up:
    MOVE.L  (SP)+,A0        ;RETURN
    MOVE.W  (SP)+,D1        ;PART
    MOVE.L  (SP)+,D0        ;CTL HANDLE
    MOVE.L  A0,-(SP)
    MOVEM.L A3-A4/D3-D7,-(SP)
    JSR     my_scroll_up
    MOVEM.L (SP)+,A3-A4/D3-D7
    RTS
#endasm
}

void my_scroll_dn(theControl, part)
ControlHandle   theControl;
short           part;
{
short   v;

    if (part == inDownButton)
      { v = GetCtlValue(theControl);
        if (v == GetCtlMax(theControl)) return;
        SetCtlValue(theControl, v+1);
        TEScroll(0, -(*hTE)->lineHeight, hTE);
      }
    return;
#asm
scroll_dn:
    MOVE.L  (SP)+,A0        ;RETURN
    MOVE.W  (SP)+,D1        ;PART
    MOVE.L  (SP)+,D0        ;CTL HANDLE
    MOVE.L  A0,-(SP)
    MOVEM.L A3-A4/D3-D7,-(SP)
    JSR     my_scroll_dn
    MOVEM.L (SP)+,A3-A4/D3-D7
    RTS
#endasm
}

/*~Prototype Expansion~ -- Resource -> usable call -- */
void expandCall(res_no, len)
short       res_no;
long        *len;
{
Handle      rHndl;
short       i, j, isVar;
long        rSize;
unsigned char   *rPtr, ch, abb[32];

    if ((rHndl = GetResource(‘ROMC’, res_no)) == NULL)
      { SysBeep(30);
         *len = 0; *call = NULL;
         return;
      }
    rSize = SizeResource(rHndl);
    HLock(rHndl);
    rPtr = (unsigned char *) *rHndl;
    HLock(abTblH);      /* lock abb. table */

    /* deal with “memory mashing” */
    j=0;
    if (mem_mash) 
      { if (*(rPtr++))   /* this one moves memory */
          appStr(“/* mashes memory */ “, call, &j)
      }
    else
      rPtr += 1;    /* just skip flag */

    for (i=1;i<rSize;i++)    
 /* copy into output, expanding abbreviations */
      { if (*rPtr < 0x80)   /* normal char */
          { call[j++] = *(rPtr++);
            continue;
          }
        if (no_casting == NULL)
          { if (*rPtr >= 0xC0)   /* “var” */
              { isVar = 1; ch = *rPtr - 0x40;
              }
            else
              { isVar = 0; ch = *rPtr;
              }
            call[j++] = ‘(‘;
            findabb(ch, abb);     /* lookup typecast */
            appStr(abb, &(call[j]), &j);
            if (isVar)
              { call[j++] = ‘ ‘; call[j++] = ‘*’;
              }
            call[j++] = ‘)’;
          }
        rPtr += 1;
      }

    appStr(“;\n”, &(call[j]), &j);
    *len = j;
    HUnlock(rHndl);
    HUnlock(abTblH);
    ReleaseResource(rHndl);
}

void appStr(src, target, tLen)
char    *src;    /* string copied FROM, null-terminated */
char    *target; /* string appended TO */
short   *tLen;   /* initial length of target; updated */
{
long    ct=0;
Ptr     tp;

    tp = src;
    while (*(tp++))
      ct++;
    BlockMove(src, target, ct);
    *tLen = *tLen + ct;
}

void findabb(c, dest)
unsigned char   c;
unsigned char   *dest;
{
short   i,j;
Ptr     tPtr;

    tPtr = *abTblH;
    j = c - 0x80;
    for (i=0;i<j;i++)
      while (*(tPtr++));
    while (*tPtr)
      *(dest++) = *(tPtr++);
    *dest = NULL;
}



*   Resource file for the ROM Ref DA
*   Frank Alviani
*   3:50:20 PM  6/6/86

RomRef_DA:Rels:RomRef.rsrc


* Menus
Type MENU
  ,-16000
ToolBox
About Myself..
Lookup Calls
Disable Typecasting
Show Memory Mashers
Close

*
*   Manager Selector box    (#1)
*
TYPE DLOG
  ,-16000
x
77 62 239 451 
InVisible NoGoAway
1 
0
-16000

TYPE DITL
  ,-16000
8
BtnItem Enabled
68 265 94 383 
Accept

BtnItem Enabled
*38 264 64 383
1000 1000 1001 1001
Accept/Continue

BtnItem Enabled
*68 265 94 383 
1000 1000 1001 1001
Append

BtnItem Enabled
*98 265 124 383 
1000 1000 1001 1001
Append/Continue

BtnItem Enabled
98 265 124 383 
Cancel

StatText Disabled
6 8 22 251 
Select a ROM Manager

* TextBox
UserItem Enabled
34 10 151 223 

* ScrollBox
UserItem Enabled
34 222 151 238 

*
*  Routine Selector box  (#2)
*
TYPE DLOG
  ,-15999
x
77 62 239 451 
InVisible NoGoAway
1 
0
-15999

TYPE DITL
  ,-15999
8
BtnItem Enabled
8 264 34 383 
Accept

BtnItem Enabled
38 264 64 383 
Accept/Continue

BtnItem Enabled
68 265 94 383 
Append

BtnItem Enabled
98 265 124 383 
Append/Continue

BtnItem Enabled
128 265 154 383 
Cancel

StatText Disabled
6 8 22 251 
Copy a sample call to the clipboard

* TextBox
UserItem Enabled
34 10 151 223 

* ScrollBox
UserItem Enabled
34 222 151 238 

*
*   About box   (#3)
*
type DLOG
,-15998
x
48 62 314 451 
InVisible NoGoAway
1
0
-15998

type DITL
,-15998
15
BtnItem Enabled
238 301 264 380 
OK!

StatText Disabled
10 69 26 319 
ROM Ref: Online Toolbox Call Samples

StatText Disabled
36 10 52 384 
ROM Ref allows you to put 1 or more sample ROM calls

StatText Disabled
52 10 68 384 
on the clipboard to be pasted directly into the program.

StatText Disabled
68 10 84 384 
When you select ‘lookup’, you are presented with a list

StatText Disabled
85 10 101 384 
of ROM managers.  When you pick one, a list of all the

StatText Disabled
101 10 117 384 
calls is presented. ‘Accept’ puts the selected call on the

StatText Disabled
118 10 134 384 
clipboard and quits;  ‘accept/continue’ then returns to 

StatText Disabled
135 10 151 384 
the manager list. ‘Append’ adds the selected call to the

StatText Disabled
152 10 168 384 
clipboard so several can be copied at once.  Typecasting

StatText Disabled
169 10 185 384 
can be disabled. A comment can be added for every call

StatText Disabled
186 10 202 384 
that can scramble memory.

StatText Disabled
215 10 231 106 
Frank Alviani

StatText Disabled
231 10 247 114 
425 McAlister

StatText Disabled
248 10 264 159 
Waukegan, Ill  60085
 
AAPL
$102.60
Apple Inc.
+1.54
MSFT
$46.72
Microsoft Corpora
-0.34
GOOG
$582.15
Google Inc.
-5.22

MacTech Search:
Community Search:

Software Updates via MacUpdate

GarageSale 6.8 - Create outstanding eBay...
GarageSale is a slick, full-featured client application for the eBay online auction system. Create and manage your auctions with ease. With GarageSale, you can create, edit, track, and manage... Read more
ScreenFlow 4.5.3 - Create screen recordi...
Save 5% with the MacUpdate coupon code: 68031AE15F -- Buy now! ScreenFlow is powerful, easy-to-use screencasting software for the Mac. With ScreenFlow you can record the contents of your entire... Read more
NeoOffice 2014.3 - Mac-tailored, OpenOff...
NeoOffice is a complete office suite for OS X. With NeoOffice, users can view, edit, and save OpenOffice documents, PDF files, and most Microsoft Word, Excel, and PowerPoint documents. NeoOffice 3.x... Read more
Typinator 6.2 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more
PopChar X 6.7 - Floating window shows av...
PopChar X helps you get the most out of your font collection. With its crystal-clear interface, PopChar X provides a frustration-free way to access any font's special characters. Expanded... Read more
Evernote 5.6.0 - Create searchable notes...
Evernote allows you to easily capture information in any environment using whatever device or platform you find most convenient, and makes this information accessible and searchable at anytime, from... Read more
Monosnap 2.2.2 - Versatile screenshot ut...
Monosnap allows you to save screenshots easily, conveniently, and quickly, sharing them with friends and colleagues at once. It's the ideal choice for anyone who is looking for a smart and fast... Read more
Tunnelblick 3.4beta36 - GUI for OpenVPN...
Tunnelblick is a free, open source graphic user interface for OpenVPN on OS X. It provides easy control of OpenVPN client and/or server connections. It comes as a ready-to-use application with all... Read more
SoftRAID 5.0.4 - High-quality RAID manag...
SoftRAID allows you to create and manage disk arrays to increase performance and reliability. SoftRAID's intuitive interface and powerful feature set makes this utility a must have for any Mac OS X... Read more
Audio Hijack Pro 2.11.3 - 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

Latest Forum Discussions

See All

Sword King Review
Sword King Review By Jennifer Allen on September 23rd, 2014 Our Rating: :: WEAK, SO WEAKUniversal App - Designed for iPhone and iPad Ever wanted to tap on a screen and assume you’ve killed a monster or two? Probably not, but just... | Read more »
Pangea Software Unveil Bundles and iOS 8...
Pangea Software Unveil Bundles and iOS 8 Updates Posted by Ellis Spice on September 23rd, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Race Team Manager Review
Race Team Manager Review By Jennifer Allen on September 23rd, 2014 Our Rating: :: LIGHT RACINGUniversal App - Designed for iPhone and iPad Want to be in charge of a racing team but not be overwhelmed by tactics and options? Race... | Read more »
Kobojo Works with Creative Minds from Fi...
Kobojo has announced details for their newest game, Zodiac – a 2D persistent online RPG. Kobojo has put together a crack team of developers including composer Hitoshi Sakimoto and scenario writer Kazushige Nojima, whose work includes many of the... | Read more »
PlayHaus Review
PlayHaus Review By Amy Solomon on September 23rd, 2014 Our Rating: iPad Only App - Designed for the iPad PlayHaus is a interesting, stylish app for young children, full of cause-and-effect interactions.   | Read more »
Astropolo Review
Astropolo Review By Amy Solomon on September 23rd, 2014 Our Rating: Universal App - Designed for iPhone and iPad Astropolo is a space-themed children’s app with a great sense of style.   | Read more »
New E*TRADE Update Includes Touch ID and...
New E*TRADE Update Includes Touch ID and Home Screen Widget for iOS 8 Posted by Jessica Fisher on September 23rd, 2014 [ permalink ] | Read more »
Cupcake Carnival Review
Cupcake Carnival Review By Jennifer Allen on September 23rd, 2014 Our Rating: :: SAME OLDUniversal App - Designed for iPhone and iPad Cupcake Carnival does all the right match-3 things but it’s a format we’ve seen a little too... | Read more »
This Week at 148Apps: September 15-19, 2...
Expert App Reviewers   So little time and so very many apps. What’s a poor iPhone/iPad lover to do? Fortunately, 148Apps is here to give you the rundown on the latest and greatest releases. And we even have a tremendous back catalog of reviews; just... | Read more »
Kitty Powers’ Matchmaker – Tips, Tricks,...
Hey There, Kittens: | Read more »

Price Scanner via MacPrices.net

Razer DeathAdder Chroma Gaming Mouse Upgraded...
Razer has announced the launch of their new Razer DeathAdder Chroma gaming mouse. Even if you’re not a gamer, the DeathAdder bears considering. I’m a fan of the hard-wired tracking accuracy,... Read more
Check Apple prices on your device with iTracx
MacPrices is proud to offer readers a free iOS app (iPhones, iPads, & iPod touch) and Android app (Google Play and Amazon App Store) called iTracx, which allows you to glance at today’s lowest... Read more
Refurbished 2013 MacBook Pros available for u...
The Apple Store has Apple Certified Refurbished 13″ and 15″ MacBook Pros available starting at $929. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz MacBook Pros (4GB RAM/... Read more
New iPhones Score Big in SquareTrade Breakabi...
SquareTrade has announced the iPhone 6 and its larger sibling, iPhone 6 Plus, performed impressively in Breakability testing, and each carries the top Breakability Score in their respective category... Read more
10 Million + First Weekend Sales Set New iPho...
Apple has announced it sold over 10 million new iPhone 6 and iPhone 6 Plus models, a new record, just three days after the launch on September 19. iPhone 6 and iPhone 6 Plus are now available in the... Read more
Betty Crocker Launches New Cookbook for iOS
Betty Crocker, a General Mills brand, an established food industry leader, has announced its free digital cookbook app has been refreshed to make cooking with iPhone, iPad and iPod touch even easier... Read more
Apple restocks some refurbished 2014 MacBook...
The Apple Store has restocked some Apple Certified Refurbished 2014 MacBook Airs, with prices starting at $769. An Apple one-year warranty is included with each MacBook, and shipping is free. These... Read more
13-inch 128GB MacBook Air on sale for $949, s...
B&H Photo has the new 2014 13″ 1.4GHz/128GB MacBook Air on sale for $949.99 including free shipping plus NY tax only. Their price is $50 off MSRP. B&H will also include free copies of... Read more
Apple offering free $25 iTunes Gift Card with...
The Apple Store is offering a free $25 iTunes Gift Card with the purchase of a $99 Apple TV for a limited time. Shipping is free. Read more
Apple refurbished iPod touch available for up...
The Apple Store has Apple Certified Refurbished 5th generation iPod touches available starting at $149. Apple’s one-year warranty is included with each model, and shipping is free. Most colors are... Read more

Jobs Board

Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, 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
Project Manager / Business Analyst, WW *Appl...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Position Opening at *Apple* - Apple (United...
…customers purchase our products, you're the one who helps them get more out of their new Apple technology. Your day in the Apple Store is filled with a range of Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.