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
$111.78
Apple Inc.
-0.87
MSFT
$47.66
Microsoft Corpora
+0.14
GOOG
$516.35
Google Inc.
+5.25

MacTech Search:
Community Search:

Software Updates via MacUpdate

NeoOffice 2014.6 - 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
LibreOffice 4.3.5.2 - Free Open Source o...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
CleanApp 5.0.0 Beta 5 - Application dein...
CleanApp is an application deinstaller and archiver.... Your hard drive gets fuller day by day, but do you know why? CleanApp 5 provides you with insights how to reclaim disk space. There are... Read more
Monolingual 1.6.2 - Remove unwanted OS X...
Monolingual is a program for removing unnecesary language resources from OS X, in order to reclaim several hundred megabytes of disk space. It requires a 64-bit capable Intel-based Mac and at least... Read more
NetShade 6.1 - Browse privately using an...
NetShade is an Internet security tool that conceals your IP address on the web. NetShade routes your Web connection through either a public anonymous proxy server, or one of NetShade's own dedicated... Read more
calibre 2.13 - Complete e-library manage...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital librarian... Read more
Mellel 3.3.7 - Powerful word processor w...
Mellel is the leading word processor for OS X and has been widely considered the industry standard since its inception. Mellel focuses on writers and scholars for technical writing and multilingual... Read more
ScreenFlow 5.0.1 - Create screen recordi...
Save 10% with the exclusive MacUpdate coupon code: AFMacUpdate10 Buy now! ScreenFlow is powerful, easy-to-use screencasting software for the Mac. With ScreenFlow you can record the contents of your... Read more
Simon 4.0 - Monitor changes and crashes...
Simon monitors websites and alerts you of crashes and changes. Select pages to monitor, choose your alert options, and customize your settings. Simon does the rest. Keep a watchful eye on your... Read more
BBEdit 11.0.2 - Powerful text and HTML e...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more

Latest Forum Discussions

See All

Galaxy Trucker Pocket (Games)
Galaxy Trucker Pocket 1.0.8 Device: iOS iPhone Category: Games Price: $2.99, Version: 1.0.8 (iTunes) Description: Galaxy Truckers Wanted!================================================================= (5/5) "Galaxy Trucker isn’t... | Read more »
Make your own Tribez Figures (and More)...
Make your own Tribez Figures (and More) with Toyze Posted by Jessica Fisher on December 19th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
So Many Holiday iOS Sales Oh My Goodness...
The holiday season is in full-swing, which means a whole lot of iOS apps and games are going on sale. A bunch already have, in fact. Naturally this means we’re putting together a hand-picked list of the best discounts and sales we can find in order... | Read more »
It’s Bird vs. Bird in the New PvP Mode f...
It’s Bird vs. Bird in the New PvP Mode for Angry Birds Epic Posted by Jessica Fisher on December 19th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Telltale Games and Mojang Announce Minec...
Telltale Games and Mojang Announce Minecraft: Story Mode – A Telltale Games Series Posted by Jessica Fisher on December 19th, 2014 [ permalink ] | Read more »
WarChest and Splash Damage Annouce Their...
WarChest and Splash Damage Annouce Their New Game: Tempo Posted by Jessica Fisher on December 19th, 2014 [ permalink ] WarChest Ltd and Splash Damage Ltd are teaming up again to work | Read more »
BulkyPix Celebrates its 6th Anniversary...
BulkyPix Celebrates its 6th Anniversary with a Bunch of Free Games Posted by Jessica Fisher on December 19th, 2014 [ permalink ] BulkyPix has | Read more »
Indulge in Japanese cuisine in Cooking F...
Indulge in Japanese cuisine in Cooking Fever’s new sushi-themed update Posted by Simon Reed on December 19th, 2014 [ permalink ] Lithuanian developer Nordcurrent has yet again updated its restaurant simulat | Read more »
Badland Daydream Level Pack Arrives to C...
Badland Daydream Level Pack Arrives to Celebrate 20 Million Downloads Posted by Ellis Spice on December 19th, 2014 [ permalink ] | Read more »
Far Cry 4, Assassin’s Creed Unity, Desti...
Far Cry 4, Assassin’s Creed Unity, Destiny, and Beyond – AppSpy Takes a Look at AAA Companion Apps Posted by Rob Rich on December 19th, 2014 [ permalink ] These day | Read more »

Price Scanner via MacPrices.net

Holiday sale: 13-inch 128GB MacBook Air for $...
 Best Buy has the 2014 13-inch 1.4GHz 128GB MacBook Air on sale for $849.99, or $150 off MSRP, on their online store. Choose free home shipping or free local store pickup (if available). Price valid... Read more
13-inch 2.6GHz Retina MacBook Pro on sale for...
Best Buy has lowered their price on the 2014 13″ 2.6GHz/128GB Retina MacBook Pro to $1149.99 on their online store for a limited time. That’s $150 off MSRP and the lowest price available for this... Read more
Kodak Returns to CES With New Consumer Produ...
Former photography colossus Kodak is returning to CES for the first time in three years where the Kodak booth (#21818 South Hall 1) will showcase a wide range of innovative, imaging-related products... Read more
Invaluable Launches New Eponymously -Named A...
Invaluable, the world’s largest online live auction marketplace, hhas announced the official launch of the Invaluable app for iPad, now available for download in the iTunes App Store. Invaluable... Read more
IDC Reveals Worldwide Mobile Enterprise Appli...
International Data Corporation (IDC) last week hosted the IDC FutureScape: Worldwide Mobile Enterprise Applications and Solutions 2015 Predictions Web conference. The session provided organizations... Read more
Hello Vino Wine App Launches “Safe Ride Home”...
Hello Vino has announced addition of a new “Get a Safe Ride Home” feature in its Food & Drink app with a direct connection to Uber, the technology platform that connects users with rides. The... Read more
DEVON-technologies Releases DEVONthink To Go...
Coeur d’Alene, Idaho based DEVON-technologies, LLC has updated DEVONthink To Go, its mobile companion to DEVONthink, to version 1.5. The update includes an iOS 8 extension, compatibility with the... Read more
The Apple Store offering free next-day shippi...
The Apple Store is now offering free next-day shipping on all in stock items if ordered before 12/23/14 at 10:00am PT. Local store pickup is also available within an hour of ordering for any in stock... Read more
It’s 1992 Again At Sony Pictures, Except For...
Techcrunch’s John Biggs interviewed a Sony Pictures Entertainment (SPE) employee, who quite understandably wished to remain anonymous, regarding post-hack conditions in SPE’s L.A office, explaining “... Read more
OtterBox Defender Series Case For iPad mini 3...
With their innovative Touch ID technology and ultrathin profile, the latest tranche of Apple iPads are more desirable than ever, and OtterBox has just announced the Defender Series custom-engineered... Read more

Jobs Board

*Apple* Store Leader Program (US) - Apple, I...
…Summary Learn and grow as you explore the art of leadership at the Apple Store. You'll master our retail business inside and out through training, hands-on experience, Read more
Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the 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
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.