Debug DA Window
Volume Number: | | 6
|
Issue Number: | | 9
|
Column Tag: | | C Workshop
|
Code Debugging Window ![](img001.gif)
By Alexander S. Colwell, Redondo Beach, CA
Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.
Introduction
A friend of mine called me the other day about developing several 4th Dimension externals and ask for suggestions to make his life easier developing software on the Macintosh. As usual, I recommended buying Inside Macintosh Volumes 1, 2, 4, and 5, several other how-to-do programming books, get all of the Macintosh Technical Notes, and buy THINK C compiler or MPW with Pascal + MacApp and/or C depending on the programming project involved. In this case, my favorite is the THINK C compiler.
However, the major problem I encountered from programmers who have worked on VAXes and IBM main-framers is the ability to perform simple debugging techniques using a print statement such as C printf function. Most of these programmers usually do not want to deal with the 680XX assembly code using TMON or MacBugs as a debugging tool. The THINK C or MPW SADE symbolic debugger will help alleviate debugging their applications, but will not be much help on resource code debugging. So, in response to this problem, I thought this would be a good DA for resource code debugging and an article in MacTutor magazine.
So, What good would the Debugger Window DA be?. The THINK C symbolic debugger is an excellent tool at finding tough logic problems in your code. But programming on the Macintosh is much like real-time programming. Problems dont show up very easily while using the symbolic debugger. Most bugs occur the nth execution time, but you would not know when that may occur. For example, tough bugs usually occur only in certain combinations of procedure/function calls. Hence, simple print statements showing the flow of the module calls can be used to determine when the problem occurs or when the program crashes the Mac. Then the symbolic debugger would be used to finish the debugging process. On the other hand, a symbolic debugger does not work on resource codes such as MDEF, WDEF, XCMD, 4DEX, and device drivers to name a few.
The ideal debugging print statement should look like the printf function statement found in the C language. Hence, a DbgPrint procedure would be used to perform in a similar manner as fprintf function. For example,
/* 1 */
DbgPrint(dbgHdl, WDEF: message - %d\n, message);
would be used to output the WDEFs message codes in the Round Window DA demo as shown in Figure 1. The dbgHdl is the debugger resource handle used to communicate between the two DAs. The remainder arguments are the format string and its arguments to generate text stream output to the Debugger Window DAs display.
![](img003.gif)
Figure 1. Sample Debugger Window with another DA
Debugger Interface
The trick in getting debugging outputs delivered to the Debugger Window DA is the use of the Resource Manager. By using a resource data block, it can be used as a clearing house between DA and other resource codes. The DA will fill in the necessary information into the resource data for the other resource codes to determine if it can send the debugging outputs and to which DA. (I tend to think this resource data block is like a VAX/VMS shareable image for you VAX hackers).
The other trick is really quite simple. It requires defining a new DA control message (ie. accDbgPrint = 128 control message). Here is an interesting point: there is really no reason that desk accessory control messages cannot handle other messages defined by Inside Macintosh Volume I in Desk Manager Chapter such as accEvent, accRun, accCursor, accMenu, accUndo, accCut, etc. This brings up several interesting possiblities for a DA and other applications, resource codes, and/or DAs communications.
Lets talk about the resource data block structure and its communication between DA and others.
/* 2 */
/* Debugger error types */
typedef enum {
dbgNoOvrFlw, /* No, overflow */
dbgTableOvrFlw,/* Table overflow */
dbgDataOvrFlw, /* Data buf overflow */
dbgBufOvrFlw /* Buf size overflow */
} DBGERROR;
/* Debugger interface data structure */
typedef struct {
short daRefNbr;
DBGERROR bufError;
long bufTableIdx;
long bufNextIdx;
long bufDataIdx;
long bufTableSize;
long bufDataSize;
long **bufTable;
char **bufData;
} DBGINTERFACE;
The daRefNbr variable is used to point to the Debugger Window DA. For every opened desk accessory, it has an associated reference number that identifies it from other DA or device drivers. If the variable is ZERO then the DA is not open and cannot accept any debugging outputs.
The remaining variables are primarily used for asynchronous debugging output operation. These variables are used in a ring-buffer fashion, where the bufTable variable is table of index offsets into the bufData holding the debugging output data streams. The bufTableIdx and bufNextIdx variables are indexes into the bufTable. The bufTableIdx is used by the Debugger Window DA to catch-up to the bufNextIdx incremented by the other resource codes. Finally, the bufTableSize and bufDataSize are handle sizes of the bufTable and bufData handles respectively. Please refer to DebuggerDA.c and Debugger.c source code on these variables implementation.
Now, why would anybody want to do synchronous or asynchronous debugging outputs? Suppose, you are trying to debug VBL or asynchronous I/O completion in your PBCall? They require no Memory Manager ROM call operations during its interrupt level processing. Therefore, it would require buffering for the DAs communication.
The DBGERROR enum type is used to inform the DA that there has been a buffer overflow and there will be some data loss for asynchronous debugging processing. For example, the VBL could generate so much debugging outputs and overflow the buffer before the DA has a chance to display the text data streams. If this happens alot, then one could increase the table and data buffer sizes. But, you are always constrained by the size of available memory. Nothing is perfect.
Module Descriptions
The Debugger Window DA debugging outputs are broken-up into two parts: synchronous or asynchronous. The DbgPrint procedure is used for synchronous operations, while the DbgBufPrint is used for asynchronous operations. The DbgPrint and DbgBufPrint arguments are similar to the C language fprintf function. The first argument is the debugger resource handle which is used to communicate between the DA and other resource codes. The second argument is the format string, and the third and henceforth arguments are the parameters for the format string that is used to output debugging data stream to the DA. The primary responsibility of these procedures is to check if the DA is available to accept debugging outputs, and then make the necessary operations to send the debugging outputs to the DA for display.
The DbgGetRefHdl function will retrieve the debugger resource data to be used to communicate with the Debugger Window DA. If it returns a non-NIL resource handle then the DA is opened. This routine must not be called at non-interrupt level. For example, it cannot be called during a VBL. So, you must pass the debugger resource handle at the end of the VBLTask data structure. Refer to Round Window.c source code.
The DbgPrint procedure calls the DA directly via the Control toolbox function. This is where the resource code makes a direct call to the DA and passing the necessary information to be displayed in the DAs window.
The DbgBufPrint procedure moves its arguments into a data buffer and schedule a DAs accRun action (ie. schedule DA wake-up). Normally, a DA will be invoked for periodic actions specified by its delay timer defined in the Device Control Entry data block. During the DAs idle processing loop it will check if there is debugging outputs to be displayed.
The DbgBufPrint must know how many bytes are on the stack (ie. the arguments) to be copied into the data buffer for later processing by the DA. This problem reminds me of my college professor famous saying : Know thy Compiler. This commandment is critical in making the DbgBufPrint procedure to work with THINK C compiler. Upon careful examination of THINK C code generation, it always has an ADD instruction after the DbgBufPrints JSR instruction. Note: MPW C does not always have an ADD instruction after the DbgBufPrints JSR instruction. Sometime, MPW C has ADD instruction or LEA instruction but it depends on the previous procedure/function calls arguments. Hence, you cannot use this function with MPW C compiler.
The DbgBufPrint procedure will analyze the return address of its caller that points to the ADD instruction and decodes the number of bytes it must pop-off the stack when the DbgBufPrint returns control back to the caller. This way it knows how many bytes to copy from the stack to the data buffer for later processing by the DA. This is really a weird code. One must understand how the compiler works in order to supply the module interface equivalent to the fprintf function. Anyway, this stuff works!
Debugger Window DA Files
The DA requires the standard ANSI-A4 and MacTraps libraries as shown in Figure 2. Note: the PE/DA.p project file is not part of the standard THINK C software package purchased by your friendly software dealer. Hence, you may obtain the PE/DA.p project file from the LightSpeed CAPPS software package.
The PE/DA.p project file is a general purpose RAM-base text editor. I use this to perform simple text output that is not limited to 32K of memory as the TextEdit ROM routines.
Round Window DA Demo
Figure 1 shows an example how the Debugger Window DA is used to debug several things concurrently with the Round Window DA demo. The Round Window DA sends its debugging output statements from its event message handlers, its WDEF window message handlers, and VBL messages to the Debugger Window DA.
This demonstrates how to use the Debugger Window DA via the DbgPrint and DbgBufPrint procedures. The DA demo will start-up a VBL using a resource code containing the VBL code and use its own WDEF window definition. The VBL will call DbgBufPrint procedure to display its every module invocation during the VBL processing. (Again, VBL resource code must use asynchronous debugging outputs since it is at interrupt level.) And, the WDEF window definition will call DbgPrint procedure to display every window message code. Finally the DA demo will call DbgPrint procedure to display every event it receives.
![](img004.gif)
Figure 2. Debugger Window DA files
Wrapping It Up
The use of the resource data as a common data block between DAs, resource codes, and applications would have interesting possibilities other than this DA demonstration. However the future System 7.0 version would eliminate this technique using InterApplication Communications Architecture (IAC). I would be able to send the equivalent printf debugging commands via the extended Event Managers Program-to-Program Communication (PPC) protocol. This would greatly reduce the code overhead in the Debugger.c source file communications between the DA and the resource code. But I had written this DA since late 1988 and had been using it ever since.
/*
* Source - Debugger.h
* Author - Alexander S. Colwell,
* Copyright (C) 1988, 1989
* Purpose - This is the Debugger Window DA
* include file definition.
*/
#ifndef _Debugger_
#define _Debugger_
/* Debugger resource info */
#define debuggerType Dbgr /* Debugger resource type*/
#define debuggerName \pDebugger Reference/* Res name*/
typedef enum { /* Debugger error types */
dbgNoOvrFlw, /* No, overflow */
dbgTableOvrFlw, /* Table overflow */
dbgDataOvrFlw, /* Data buffer overflow */
dbgBufOvrFlw /* Buffer size overflow */
} DBGERROR;
typedef enum { /* Debugger types */
accDbgPrint = 128, /* Perform print action*/
accDbgDump /* Perform dump action */
} DBGTYPE;
typedef struct { /* Debugger Interface def*/
short daRefNbr; /* DAs reference number */
DBGERROR bufError; /* Buffer error indicator*/
long bufTableIdx; /* Buffer index */
long bufNextIdx; /* Next buffer index */
long bufDataIdx; /* Buffer data index */
long bufTableSize; /* Buffer idx table size */
long bufDataSize; /* Buffer data hdl size */
long **bufTable; /* Buffer index table */
char **bufData; /* Buffer data handle */
} DBGINTERFACE;
typedef DBGINTERFACE *DBGPTR;
typedef DBGPTR *DBGHDL;
DBGHDL DbgGetRefHdl(); /* Debugging proto-types */
void DbgPrint(/* DBGHDL dbgRefHdl, char *fmt, var-args... */);
void DbgBufPrint(/* DBGHDL dbgRefHdl, char *fmt, var-args... */);
void DbgDump(DBGHDL dbgRefHdl, char *buffer, long size);
void DbgBufDump(DBGHDL dbgRefHdl, char *buffer, long size);
long DbgStrLen(char *str);
#endif
/*
* Source - DebuggerDA.c
* Author - Alexander S. Colwell,
* Copyright (C) 1988, 1989
* Purpose - This is the Debugger Window desk
* accessory to simplify debugging resource
* codes, DAs or applications that does not
* have a debugging output window. This
* requires System 4.1 or greater version.
*/
#include Debugger.h /* DA Debugger defs */
#include <Color.h> /* Color Manager defs */
#include <CType.h> /* C Type defs */
#include <StdArg.h> /* Standard Argument defs*/
#include <SetUpA4.h> /* Desk Accessory defs */
#include <PE.h> /* Program Edit defs */
/* Misc definitions */
#define NIL (0L) /* NIL pointer */
#define abs(a) (a<0?-a:a) /* Absolute macro func */
#define min(a,b) (a<b?a:b) /* Minumim macro function*/
#define max(a,b) (a<b?b:a) /* Maximum macro function*/
/* Trap definitions */
#define SysEnvironsTrap 0xa090/* System Enviorment */
#define UnknownTrap 0xa89f/* Unknown trap instr */
/* Limit definitions */
#define maxColumns 132 /* Maximum # of columns */
/* Resource ID #s */
#define windID 0 /* Window ID # */
#define infoID 0 /* Info dialog ID # */
#define errorID 1 /* Error dialog ID # */
#define strID 0 /* String STR ID # */
#define errID 1 /* Error STR ID # */
#define optionsID 0 /* Options ID # */
#define debuggerID 0 /* Debugger ID # */
typedef enum { /* Menu commands */
Info = 1, /* On-line information */
NullItem2,
StartOutput, /* Start/Stop output */
Quit /* Quit from DA */
} MENU;
typedef enum { /* String ID #s */
itmStartOutput = 1, /* Start Output item */
itmStopOutput, /* Stop Output item */
bufTableOvrFlw, /* Table overflow */
bufDataOvrFlw, /* Data buffer overflow */
bufBufOvrFlw /* Buffer size overflow */
} STRID;
/* Resource types */
#define optionType Opts /* Option definition type*/
typedef enum { /* Error messages */
errFailOpenDA = 1, /* Fail to open DA */
errNoGlobals, /* Fail to alloc globals */
errLowMemory, /* Low memory error */
errOldSystem, /* Old System file */
errLisaClone, /* Lisa clone Macintosh */
errOriginalMac /* Original 128/512 Mac! */
} ERROR;
typedef struct { /* Options definitions */
short maxTextSize; /* Maximum text size */
short fontFamily; /* Font ID family */
short fontSize; /* Font size */
short spacesPerTab; /* # of spaces per tab */
long bufTableSize; /* Buffer table size */
long bufDataSize; /* Buffer data size */
} OPT;
typedef OPT *OPTPTR;
typedef OPTPTR *OPTHDL;
/* Global variables */
short alreadyOpen = FALSE;/* DA open flag */
SysEnvRec sysEnv; /* System enviroment */
DCtlPtr dce; /* Device control entry */
WindowPtr wp = NIL; /* My window pointer */
Rect originalRect;/* Original rect area */
PEHandle peHdl = NIL; /* PE handle */
short active = FALSE;/* Active flag */
ControlHandle hScrollBar = NIL;/* Horz scroll bar */
ControlHandle vScrollBar = NIL;/* Vert scroll bar */
DBGHDL dbgHdl = NIL;/* Debugger handle */
OPTHDL optHdl = NIL;/* Options handle */
short cursorMode = FALSE;/* Cursor mode */
MenuHandle menu = NIL; /* Menu handle */
short menuID = 0; /* Menu ID # */
long **bufTable = NIL;/* Buffer idx tbl hdl*/
char **bufData = NIL;/* Buffer data handle */
short outputEnable = TRUE;/* Output flag */
char PrintOutputBuf[1024];/* Print buffer */
pascal void DoTextScroll(); /* Define forwared refa */
pascal void DoClickScroll();
pascal void DoHighLite();
void DoPrintChar();
DialogTHndl DoDlgCenter();
main(p,d,n)
cntrlParam *p; /* Parameter block */
DCtlPtr d; /* Device control entry */
short n; /* Entry point selector */
{
WindowPtr savePort; /* Save cur window port */
short saveResFile; /* Save cur resource file*/
if (d->dCtlStorage == 0) { /* Check if got globals! */
if (n == 0) { /* Check if Opening */
DoError(errNoGlobals); /* Opps, fail get globals*/
CloseDriver(d->dCtlRefNum);/* Close the DA */
}
}
else { /* Got globals then cont */
RememberA4(); /* Remember A4 register */
GetPort(&savePort); /* Get cur window port */
if (wp) /* Check if ptr valid */
SetPort(wp); /* Set port to my window */
dce = d; /* Save DCE ptr */
dce->dCtlFlags &= ~dCtlEnable;/*Set not re-entrant*/
switch(n) { /* Handle request: */
case 0: /* Open */
DoOpen(); break;
case 2: /* Control */
DoControl(p->csCode,p->csParam); break;
case 4: /* Close */
DoClose(); break;
}
dce->dCtlFlags |= dCtlEnable;/* Enable it again */
SetPort(savePort); /* OK, lets restore it */
}
return(0); /* Return default success*/
}
DoOpen()
{
short rom; /* Working ROM id */
short machine; /* Working Mac id */
Rect wRect; /* Working wind rect area*/
Point pt; /* Working point */
register PEPtr pePtr; /* Working edit pointer */
DBGPTR dbgPtr; /* Working debugger ptr */
register short canDoIt; /* Working can do it flag*/
register short errCode = errFailOpenDA;/*Error code*/
dce->dCtlFlags |= dNeedLock|dNeedGoodBye;/*Set flags*/
if (wp) /* Check if there window */
if (wp != FrontWindow()) /* Check if not in front */
SelectWindow(wp); /* Bring our window front*/
if (!alreadyOpen) { /* Check if require inits*/
Environs(&rom,&machine); /* Get Macs evniroment */
if (machine == macXLMachine) {/* Check if Lisa */
canDoIt = FALSE; /* Its a Lisa computer*/
errCode = errLisaClone; /* Set error message */
}
else if (rom >= 0x0078) /* Its Mac II */
canDoIt = TRUE; /* Its Mac II computer */
else if (rom >= 0x0076) /* Its Mac SE */
canDoIt = TRUE; /* Its Mac SE computer */
else if (rom >= 0x0075) { /* its 128K rom */
if (MemTop > (char *)(1024L * 512L))/* Mac 512KE? */
canDoIt = TRUE; /* Its Mac 512K Enhanced*/
else /* Must be Mac Plus */
canDoIt = TRUE; /* Its Mac Plus computer */
}
else if (rom >= 0x0069){ /* Its 64K rom, its old*/
canDoIt = FALSE; /* Its original Mac! */
errCode = errOriginalMac;/* Set error message */
}
if (canDoIt) { /* OK, we can do it! */
/* Check if its valid */
if ((long)NGetTrapAddress(SysEnvironsTrap,OSTrap) !=
(long)NGetTrapAddress(UnknownTrap,ToolTrap)) {
SysEnvirons(1,&sysEnv); /* Get system enviroment */
if (sysEnv.systemVersion >= 0x0410) {/* Latest? */
wp = GetNewWindow(GetResourceID(windID),NIL,-1L);
if (wp) { /* Check if got window */
ShowWindow(wp); /* OK, lets show it */
SetPort(wp); /* Set port to our window*/
alreadyOpen = TRUE; /* Set open DA indicator */
/*Save window association*/
((WindowPeek)wp)->windowKind = dce->dCtlRefNum;
dce->dCtlWindow = wp;/* Tell device where I am */
originalRect = wp->portRect;/* Save orig area */
LocalToGlobal(&originalRect.top);
LocalToGlobal(&originalRect.bottom);
/* Check if create scroll*/
wRect.left = wp->portRect.left - 1;
wRect.top = wp->portRect.bottom - 15;
wRect.right = wp->portRect.right - 14;
wRect.bottom = wp->portRect.bottom + 1;
hScrollBar = NewControl(wp,&wRect,,FALSE,
0,0,0,scrollBarProc,0L);
/* Check if create scroll*/
wRect.left = wp->portRect.right - 15;
wRect.top = wp->portRect.top - 1;
wRect.right = wp->portRect.right + 1;
wRect.bottom = wp->portRect.bottom - 14;
vScrollBar = NewControl(wp,&wRect,,FALSE,
0,0,0,scrollBarProc,0L);
/* Get options defs */
optHdl = (OPTHDL)(GetResource(optionType,
GetResourceID(optionsID)));
/* Get debugger defs */
dbgHdl = (DBGHDL)(GetResource(debuggerType,
GetResourceID(debuggerID)));
TextFace(0); /* Set Plain style font*/
if (optHdl) { /*Check if got option hdl*/
TextSize((*optHdl)->fontSize);
TextFont((*optHdl)->fontFamily);
}
else { /* Nope, set to default */
TextSize(9);
TextFont(monaco);
}
wRect.left = wp->portRect.left;/* Set edit view*/
wRect.top = wp->portRect.top + 5;
wRect.right = wp->portRect.right - 15;
wRect.bottom = wp->portRect.bottom - 15;
if (peHdl = PENew(&wRect)) {/* Check if got it */
pePtr = *peHdl; /* Set edit pointer */
/* Set auto scroll hook */
pePtr->clikLoop = (ProcPtr)DoClickScroll;
if (sysEnv.hasColorQD)/* Check if has color */
pePtr->highHook = (ProcPtr)DoHighLite;
pePtr->viewOrgH = -5;/* Set horizontal offset */
pePtr->viewOrgV = 0; /* Set vertical offset */
/*Set # of spaces per tab*/
(*peHdl)->tabWidth = CharWidth( ) *
(*optHdl)->spacesPerTab;
DoRestoreClippings();/* Restore text clipping */
}
menuID = GetResourceID(menuID);/* Get menu ID */
if (menu = GetMenu(menuID)) {/* Check if got it*/
(**menu).menuID = menuID;/* Reset default ID */
dce->dCtlMenu = menuID;/* Set device menu ID */
if (!dbgHdl) /*Check if fail to get it*/
DisableItem(menu,StartOutput);/* Disable it */
}
else /* Fail to get menu hdl */
menuID = 0; /* Reset menu ID # */
if (optHdl) { /*Check if got option hdl*/
/* Allocate buffer table */
bufTable = (long **)(NewHandle(
(long)((*optHdl)->bufTableSize) *
(long)(sizeof(long))));
bufData = NewHandle(/* Allocate buffer data */
(long)((*optHdl)->bufDataSize) *
(long)(sizeof(char)));
}
/* Check if memory low */
if (!hScrollBar || !vScrollBar || !peHdl ||
! menu || !optHdl || !dbgHdl ||
!bufTable || !bufData)
DoError(errLowMemory);
if (dbgHdl) { /* Check if got resource */
SetHandleSize(dbgHdl,/* Make sure right size */
(long)(sizeof(DBGINTERFACE)));
dbgPtr = *dbgHdl; /* Set debugger pointer */
dbgPtr->bufError = dbgNoOvrFlw;/* Init buffer */
dbgPtr->bufTableIdx = 0;
dbgPtr->bufNextIdx = 0;
dbgPtr->bufDataIdx = 0;
dbgPtr->bufTableSize = 0L;
dbgPtr->bufTable = NIL;
dbgPtr->bufData = NIL;
dbgPtr->bufDataSize = 0L;
dbgPtr->daRefNbr = 0;
/* Check if tables valid */
if (optHdl && bufTable && bufData) {
dbgPtr->bufTableSize = (*optHdl)->bufTableSize;
dbgPtr->bufTable = bufTable;
dbgPtr->bufData = bufData;
dbgPtr->bufDataSize = (*optHdl)->bufDataSize;
dbgPtr->daRefNbr = dce->dCtlRefNum;
}
ChangedResource(dbgHdl);/* Update it */
WriteResource(dbgHdl);
}
}
}
else /* Require newer system */
errCode = errOldSystem;
}
else /* Require newer system */
errCode = errOldSystem;
}
if (!wp) { /* Check if fail to open */
DoError(errCode); /* Fail to open DA */
DoQuit(); /* Lets get out now! */
}
}
}
DoClose()
{
register Handle hdl; /* Working handle */
Rect curRect; /* Working cur rect area */
register Rect **wRect; /* Working window rect */
if (dbgHdl) { /* Check if have handle */
(*dbgHdl)->daRefNbr = 0; /* OK, lets clear these */
(*dbgHdl)->bufTable = NIL;
(*dbgHdl)->bufData = NIL;
ChangedResource(dbgHdl); /* Update resource, too */
WriteResource(dbgHdl);
dbgHdl = NIL; /* Clear handle, but dont*/
/* release it since other*/
/* DAs and etc will be */
/* using it, too. */
}
if (bufTable) /* Check if its valid */
DisposHandle(bufTable); /* Release it to mem mgr */
bufTable = NIL; /* Invalidate it */
if (bufData) /* Check if its valid */
DisposHandle(bufData); /* Release it to mem mgr */
bufData = NIL; /* Invalidate it */
if (optHdl) /* Check if have option */
ReleaseResource(optHdl); /* Release it */
optHdl = NIL; /* Invalidate it too */
if (menu) { /* Check if have menu hdl*/
DeleteMenu(menuID); /* Delete from menu bar */
DrawMenuBar();
DisposeMenu(menu); /* Release menu handle */
menu = NIL; /* Invalidate menu handle*/
dce->dCtlMenu = 0; /* Clear-out menu ID # */
}
if (peHdl) { /* Check if its valid */
PEDispose(peHdl); /* Release it now */
peHdl = NIL; /* Invalidate edit hdl */
}
if (wp) { /* Check if window valid*/
curRect = wp->portRect; /* Translate to global */
LocalToGlobal(&curRect.top);
LocalToGlobal(&curRect.bottom);
DisposeWindow(wp); /* Delete the window now*/
wp = NIL; /* Reset it now */
if (!EqualRect(&curRect,&originalRect)) {/*Changed?*/
/* Check if got wnd hdl */
if (wRect = ((Rect **)GetResource(WIND,
GetResourceID(windID)))) {
**wRect = curRect; /* Save new location */
ChangedResource(wRect); /* Mark it changed */
WriteResource(wRect); /* Write resource now */
}
}
}
/* Get STR# resource */
if (hdl = GetResource(STR#,GetResourceID(strID)))
ReleaseResource(hdl); /* OK, release it now */
if (hdl = GetResource(STR#,GetResourceID(errID)))
ReleaseResource(hdl); /* OK, release it now */
InitCursor(); /* Restore arrow cursor */
alreadyOpen = FALSE; /* Reset it */
}
DoControl(code,parm)
short code; /* Control command code */
short *parm; /* csParam list pointer*/
{
switch(code) { /* Handle request: */
case accEvent: /* Event */
DoEvent(*((EventRecord **)parm)); break;
case accMenu: /* Menu */
DoMenu(*(parm + 1)); break;
case accRun: /* Run */
DoIdle(); break;
case accCopy: /* Copy */
DoCopy(); break;
case accClear: /* Clear */
DoClear(); break;
case goodBye: /* GoodBye */
DoClose(); break;
case accDbgPrint: /* DbgPrint */
DoDbgPrint(((long *)(parm))); break;
case accDbgDump: /* DbgDump */
DoPrintDump(*((long *)(parm)),
*(((long *)(parm))+1)); break;
}
}
DoEvent(e)
register EventRecord *e; /* Event Record pointer */
{
switch(e->what) { /* Handle request: */
case updateEvt: /* Update */
DoUpdate(); break;
case mouseDown: /* Mouse Down */
DoMouse(e->where,e->modifiers); break;
case activateEvt: /* Activate */
DoActivate((Boolean)(e->modifiers & activeFlag));
break;
case keyDown: /* Key Down */
case autoKey: /* Auto-Key Down */
/* Handle the input key */
DoKey((char)(e->message & charCodeMask),
(char)((e->message & keyCodeMask) >> 8L),
e->modifiers);
}
}
DoUpdate()
{
BeginUpdate(wp); /* Start update processng*/
ClipRect(&wp->portRect); /* Reset clipping */
EraseRect(&wp->portRect); /* Erase part of screen */
DrawGrowIcon(wp); /* Draw the grow icon */
DrawControls(wp); /* Draw the controls */
if (peHdl) { /* Check if has edit hdl */
DoRestoreClippings(); /* Restore clippgings */
PEUpdate(peHdl); /* OK, lets update it */
}
EndUpdate(wp); /* Wrapup update */
}
DoMouse(p,modifiers)
Point p; /* Mouse point position */
short modifiers; /* Mouses modifiers */
{
register long i; /* Working index */
Rect wRect; /* Working window rect */
register long wGrow; /* Working grow size */
ProcPtr wDef; /* Working window proc */
/* Get window proc def */
wDef = (ProcPtr)*((WindowPeek)wp)->windowDefProc;
/* Check if in Content */
if (CallPascalL(8,wp,(int)wHit,p,wDef) == wInContent)
DoContent(p,modifiers);
/* Check if in Grow */
else if (CallPascalL(8,wp,(int)wHit,p,wDef) ==
wInGrow) {
SetRect(&wRect,100,100,32767,32767);/*Define limits*/
wGrow = GrowWindow(wp,p,&wRect);/* OK, grow it now */
if (wGrow) { /* Check if got new size */
/* Reset new size */
SizeWindow(wp,LoWord(wGrow),HiWord(wGrow),TRUE);
DoResizeScrollBar(); /* Resize the scroll bar */
InvalRect(&wp->portRect);/* Invalidate everything */
DoAdjustScrollBar(); /* Adjust scroll bar */
}
}
/* Check if in Zoom In */
else if (CallPascalL(8,wp,(int)wHit,p,wDef) ==
wInZoomIn) {
ZoomWindow(wp,inZoomIn,TRUE);/* Zoom it in */
DoResizeScrollBar(); /* Resize the scroll bar */
DoAdjustScrollBar(); /* Adjust scroll bar */
}
/* Check if in Zoom Out*/
else if (CallPascalL(8,wp,(int)wHit,p,wDef) ==
wInZoomOut) {
ZoomWindow(wp,inZoomOut,TRUE);/* Zoom it out */
DoResizeScrollBar(); /* Resize the scroll bar */
DoAdjustScrollBar(); /* Adjust scroll bar */
}
}
DoActivate(activate)
short activate; /* Activate flag */
{
Rect wRect; /* Working window rect */
/* Set vertical ctrl area*/
wRect.left = wp->portRect.right - 14;
wRect.top = wp->portRect.top - 1;
wRect.right = wp->portRect.right + 1;
wRect.bottom = wp->portRect.bottom - 16;
ClipRect(&wRect); /* Reset clippings */
if (activate) { /* Check if activating */
dce->dCtlFlags |= dNeedTime;/* Allow periodic runs */
dce->dCtlDelay = 15; /* Reset delay timer */
if (peHdl) { /* Check if got the text */
active = TRUE; /* Activate text editing */
PEActivate(peHdl); /* Activate the text */
}
DoActivateScrollBars(); /* Activate scroll bars */
if (menu) { /* Check if menu is valid*/
InsertMenu(menu,0); /* Insert into menu bar */
DrawMenuBar();
dce->dCtlMenu = menuID; /* Reset menu ID # */
}
}
else { /* Nope, deactivating */
if (dbgHdl) { /* Check if its valid */
/* Check if there outputs*/
if ((*dbgHdl)->bufTableIdx !=
(*dbgHdl)->bufNextIdx) {
dce->dCtlFlags |= dNeedTime;/* Allow periodic run*/
dce->dCtlDelay = 15; /* Reset delay timer */
}
else /* No, buffer outputs */
dce->dCtlFlags &= ~dNeedTime;/* Turn off runs */
}
else /* Nope, use defaults */
dce->dCtlFlags &= ~dNeedTime;/* Turn off runs */
active = FALSE; /* Deactivate text edit */
if (peHdl) /* Check if got the text */
PEDeactivate(peHdl); /* Deactivate the text */
DoDeActivateScrollBars(); /* Deactivate scroll bars*/
InitCursor(); /* Restore arrow cursor */
cursorMode = FALSE; /* Reset cursor mode */
if (menu) { /* Check if menu is valid*/
DeleteMenu(menuID); /* Delete from menu bar */
DrawMenuBar();
dce->dCtlMenu = 0; /* Clear-out menu ID # */
}
}
}
DoActivateScrollBars()
{
Rect wRect; /* Working rect area */
ClipRect(&wp->portRect); /* Set clippings */
if (hScrollBar) /* Check if have horz bar*/
ShowControl(hScrollBar); /* Show the scroll bar */
if (vScrollBar) /* Check if have vert bar*/
ShowControl(vScrollBar); /* Show the scroll bar */
/* Invalidate drag icon */
wRect.top = wp->portRect.bottom - 14;
wRect.bottom = wp->portRect.bottom;
wRect.left = wp->portRect.right - 14;
wRect.right = wp->portRect.right;
InvalRect(&wRect);
DoRestoreClippings(); /* Restore clippings */
}
DoDeActivateScrollBars()
{
Rect wRect; /* Working rect area */
ClipRect(&wp->portRect); /* Set clippings */
if (hScrollBar) /* Check if have horz bar*/
HideControl(hScrollBar); /* Hide the scroll bar */
if (vScrollBar) /* Check if have vert bar*/
HideControl(vScrollBar); /* Hide the scroll bar */
/* Clear drag icon */
wRect.top = wp->portRect.bottom - 14;
wRect.bottom = wp->portRect.bottom;
wRect.left = wp->portRect.right - 14;
wRect.right = wp->portRect.right;
EraseRect(&wRect);
DoUpdate(); /* Update the DA window */
DoRestoreClippings(); /* Restore clippings */
}
DoIdle()
{
register short id; /* Working string ID # */
register DBGPTR dbgPtr; /* Working debugger ptr */
register char *s,*f; /* Working string ptrs */
Str255 wStr; /* Working string */
Point p; /* Working mouse location*/
if (active) { /* Check if it activated */
GetMouse(&p); /* Get mouse location */
if (peHdl) { /* Check if got the text */
PEIdle(peHdl); /* Do cursor blinking */
if (PtInRect(p,&(*peHdl)->viewRect)){/*Within view*/
if (!cursorMode) { /* Check if not I-Beam */
SetCursor(*GetCursor(iBeamCursor));/* Reset curs*/
cursorMode = TRUE; /* Reset cursor mode */
}
}
else { /* Reset to arrow cursor */
if (cursorMode) { /* Check if using I-Beam */
InitCursor(); /* Restore arrow cursor */
cursorMode = FALSE; /* Reset cursor mode */
}
}
}
}
if (dbgHdl) { /* Check if handle valid */
if ((*dbgHdl)->bufError) {/* Check for buf overflow*/
switch((*dbgHdl)->bufError) {/* Get buf err ID # */
case bufTableOvrFlw:
id = dbgTableOvrFlw; break;
case bufDataOvrFlw:
id = dbgDataOvrFlw; break;
case bufBufOvrFlw:
id = dbgBufOvrFlw;
}
/* Let user know about it*/
GetIndString(wStr,GetResourceID(strID),id);
DoPrintLine(%p\n,wStr);
(*dbgHdl)->bufError = dbgNoOvrFlw;/* Reset flag */
}
dbgPtr = *dbgHdl; /* Set debugger pointer */
/* Check if has changed */
if (dbgPtr->bufTableIdx != dbgPtr->bufNextIdx) {
/* Bump to next index */
dbgPtr->bufTableIdx = (dbgPtr->bufTableIdx + 1L) %
dbgPtr->bufTableSize;
HLock(dbgPtr->bufData); /*Lock it down for output*/
/* Set switch code ptr */
s = &(*dbgPtr->bufData)[(*dbgPtr->bufTable)
[dbgPtr->bufTableIdx]];
f = s + 2L; /*Set format string addr */
switch((unsigned char)(*s)){/* Process input cmd */
case accDbgPrint: /* Do LSC debugging line */
DoDbgPrintSetUp(f); break;
case accDbgDump: /* Do debugging dump */
DoPrintDump(((long *)(f + sizeof(long))),
*((long *)(f)));
}
dbgPtr = *dbgHdl; /* Reset debugger pointer*/
/* Check if its finished*/
if (dbgPtr->bufTableIdx == dbgPtr->bufNextIdx) {
if (!active) /* Check if not active */
dce->dCtlFlags &= ~dNeedTime;/* Turn it off */
else /* Restore delay timer */
dce->dCtlDelay = 15;
}
HUnlock(dbgPtr->bufData);/* OK, lets unlock it */
}
}
}
DoKey(c,code,modifiers)
char c; /* Input character */
char code; /* Input code */
short modifiers; /* Input modifiers */
{
register short i,j; /* Working indexes */
register short adjustIt = TRUE;/* adjust view */
register short item = 0; /* Working item # */
char cmdChar[2];/* Working command char */
register ControlHandle ctrlHdl;/* Working ctrl hdl */
static short cnt = 0; /* Debugging counter */
if (active) { /* Check if activated */
if (modifiers & cmdKey) { /* Check if key command */
switch(c) { /* Process key command */
case c: /* Copy command */
case C:
DoCopy(); c = 0; break;
case k: /* Clear command */
case K:
DoClear(); c = 0;
}
if (c) { /* Check if should cont */
if (menu) { /* Check if got menu hdl*/
/* Search for item cmd */
for(i = 1, j = CountMItems(menu); i <= j; i++) {
GetItemCmd(menu,i,cmdChar);/* Get items cmd */
if (cmdChar[1] == ?) /* Check if ? char */
cmdChar[1] = /; /* Translate lower case */
/* Check if this is it */
if (!IUMagIDString(&c,&cmdChar[1],1,1)) {
item = i; /* Yup, save item # */
i += j; /* Break-out of loop */
}
}
if (item) { /* Check if got our guy */
HiliteMenu(menuID); /* OK, lets highlite it*/
DoMenu(item); /* Lets do it */
HiliteMenu(0); /* Unhighlite the menu */
}
else /* Opps, wrong menu */
SysBeep(1); /* Let um know about it */
}
else /* Opps, no menu handle */
SysBeep(1); /* Let um know about it */
}
}
else if (peHdl) { /* Check if got the text*/
/* Check if has ext key */
if (sysEnv.keyBoardType == envAExtendKbd ||
sysEnv.keyBoardType == envStandADBKbd) {
if (modifiers & optionKey)/* Check if want horz */
ctrlHdl = hScrollBar; /* Set horz scroll bar */
else /* Nope, use vert bar */
ctrlHdl = vScrollBar;
switch(code) { /* Check if F1-F4 keys */
case 0x63: /* F3 Copy key */
DoCopy(); break;
case 0x73: /* Home key */
if (ctrlHdl) { /* Check if has ctrl hdl*/
if (i = GetCtlValue(ctrlHdl)) {/* Can scroll ?*/
ClipRect(&wp->portRect);/* Reset clippings */
SetCtlValue(ctrlHdl,0);/* Set new value */
DoRestoreClippings();/* Restore clippings */
if (ctrlHdl == vScrollBar)/* Check if vert */
PEScroll(0,(long)(i),peHdl);/* Scroll vert */
else /* Nope, horz scroll */
PEScroll(i,0L,peHdl);/* Scroll horz dir. */
}
}
adjustIt = FALSE; /* Dont adjust view */
break;
case 0x77: /* End key */
if (ctrlHdl) { /* Check if has ctrl hdl*/
/* Check if can scroll */
if ((i = GetCtlValue(ctrlHdl)) !=
(j = GetCtlMax(ctrlHdl))) {
ClipRect(&wp->portRect);/* Reset clippings */
SetCtlValue(ctrlHdl,j);/* Reset new value */
DoRestoreClippings();/* Restore clippings */
if (ctrlHdl == vScrollBar)/* Check if vert */
PEScroll(0,(long)(i - j),peHdl);
else /* Scroll horz dir. */
PEScroll(i - j,0L,peHdl);
}
}
adjustIt = FALSE; /* Dont adjust view */
break;
case 0x74: /* Page up key */
if (ctrlHdl) { /* Check if has ctrl hdl*/
DoTextScroll(ctrlHdl,inPageUp);/* Scroll up */
}
adjustIt = FALSE; /* Dont adjust view */
break;
case 0x79: /* Page down key */
if (ctrlHdl) { /* Check if has ctrl hdl*/
DoTextScroll(ctrlHdl,inPageDown);/*Scroll down*/
}
adjustIt = FALSE; /* Dont adjust view */
break;
}
}
if (adjustIt) /* Should adjust it ? */
DoAdjustScrollBar(); /* Adjust the scroll bar*/
}
}
}
DoMenu(item)
short item; /* Item code */
{
switch(item) { /* Process menu command */
case Info: /* On-line information */
DoInfo(); break;
case StartOutput: /* Start/Stop output */
DoStartStopOutput(); break;
case Quit: /* Quit from the DA */
DoQuit(); break;
}
}
DoContent(p,modifiers)
Point p; /* Mouse down point */
short modifiers; /* Mouses modifiers */
{
long i; /* Working index */
register short selectIt = FALSE;/* Selection flag */
Point pt; /* Working point */
pt = p; /* Convert to local coord*/
GlobalToLocal(&pt);
if (!DoScrollBar(pt)) /* Check if in scroll bar*/
DoTextClick(pt,modifiers);/* Do text clicking */
}
DoQuit()
{
SysBeep(1); /* Beep the user now! */
CloseDriver(dce->dCtlRefNum);/* OK, lets close DA */
}
DoCopy()
{
register long len; /* Working text length */
if (active) { /* Check if it activated */
if (peHdl) { /* Check if have edit hdl*/
/* Check if any selection*/
if (len = (*peHdl)->selEnd - (*peHdl)->selStart) {
ZeroScrap(); /* Reset the scrap file */
HLock((*peHdl)->hText); /* Lock the text down */
/* Transfer to clipboard */
PutScrap(len,TEXT,*(*peHdl)->hText +
(*peHdl)->selStart);
HUnlock((*peHdl)->hText);/* OK, safe to unlock it*/
}
}
}
}
DoClear()
{
register Handle txtHdl; /* Working text handle */
Rect wRect; /* Working rect area */
if (peHdl) { /* Check if have edit hdl*/
if (txtHdl = NewHandle(0L)) {/* Check if got hdl */
ClipRect(&wp->portRect); /* Reset clipping */
if (hScrollBar) { /* Check if have scroll */
(*hScrollBar)->contrlMax = 0;/* Reset values */
SetCtlValue(hScrollBar,0);
}
if (vScrollBar) { /* Check if have scroll */
(*vScrollBar)->contrlMax = 0;/* Reset values */
SetCtlValue(vScrollBar,0);
}
DoRestoreClippings(); /* Restore clippings */
DisposHandle((*peHdl)->hText);/* Release old text */
(*peHdl)->hText = NIL; /* Reset it to zip! */
PESetHText(txtHdl,peHdl);/* Set new text handle */
wRect = wp->portRect; /* Clear the display */
wRect.right -= 15; wRect.bottom -= 15;
InvalRect(&wp->portRect);
}
}
}
DoInfo()
{
register DialogPtr dPtr; /* Working dialog pointer*/
short dItem; /* Working dialogue item */
register short next = TRUE;/* Working next flag*/
if (dbgHdl) { /* Check if got ref hdl */
(*dbgHdl)->daRefNbr = 0; /* Clear debugger ref hdl*/
ChangedResource(dbgHdl);
WriteResource(dbgHdl);
}
DoDeActivateScrollBars(); /* Deactivate scroll bars*/
DoDlgCenter(DLOG,infoID);/* Center the dialog now */
/* Open dialog */
dPtr = GetNewDialog(GetResourceID(infoID),NIL,-1L);
if (dPtr) { /* Check if open dialog */
InitCursor(); /* Restore arrow cursor */
cursorMode = FALSE; /* Reset cursor mode */
SetPort(dPtr); /* Set to my window port */
while(next) { /* Process next event */
ModalDialog(NIL,&dItem); /* Get modal event */
if (dItem == OK) /* Check if time to quit */
next = FALSE; /* Lets break-out ! */
}
SetPort(wp); /* Restore DA window port*/
DisposDialog(dPtr); /* Kill dialogue window */
}
DoActivateScrollBars(); /* Activate scroll bars */
if (dbgHdl) { /* Check if got ref hdl */
if (outputEnable) { /* Check if enabled */
/* Restore ref handle */
(*dbgHdl)->daRefNbr = dce->dCtlRefNum;
ChangedResource(dbgHdl);
WriteResource(dbgHdl);
}
}
}
DoStartStopOutput()
{
Str255 wStr; /* Working item string */
if (dbgHdl) { /* Check if has ref hdl */
if (outputEnable) { /* Check if to turn off */
outputEnable = FALSE; /* Disable output display*/
(*dbgHdl)->daRefNbr = 0;
GetIndString(wStr,GetResourceID(strID),
itmStartOutput);
}
else { /* Nope, start-up output */
outputEnable = TRUE; /* Enable output display */
(*dbgHdl)->daRefNbr = dce->dCtlRefNum;
GetIndString(wStr,GetResourceID(strID),itmStopOutput);
}
SetItem(menu,StartOutput,wStr);/* Reset item string*/
}
}
DoError(errMsg)
ERROR errMsg; /* Error message */
{
Str255 wStr; /* Working string */
if (dbgHdl) { /* Check if got ref hdl */
(*dbgHdl)->daRefNbr = 0; /* Clear debugger ref hdl*/
ChangedResource(dbgHdl);
WriteResource(dbgHdl);
}
/* Get error message */
GetIndString(wStr,GetResourceID(errID),errMsg);
ParamText(wStr,,,); /* Setup text messages */
DoDlgCenter(ALRT,errorID);/* Center alert dialog */
DoDeActivateScrollBars(); /* Deactivate scroll bars*/
CautionAlert(GetResourceID(errorID),NIL);/* Show it */
DoActivateScrollBars(); /* Activate scroll bars */
if (dbgHdl) { /* Check if got ref hdl */
if (outputEnable) { /* Check if enabled */
/* Restore ref handle */
(*dbgHdl)->daRefNbr = dce->dCtlRefNum;
ChangedResource(dbgHdl);
WriteResource(dbgHdl);
}
}
}
DoTextClick(pt,modifiers)
Point pt; /* Mouse down point */
short modifiers; /* Modifiers selection */
{
register short extendIt = FALSE;/* Extend selection*/
if (peHdl) { /* Check if got the text */
if ((*peHdl)->peLength > 0) {/* Check if any text */
if (modifiers & shiftKey)/*Check if want extend it*/
extendIt = TRUE; /* Extend selection then */
PEClick(pt,extendIt,peHdl);/* Do clicking stuff */
}
}
}
DoScrollBar(pt)
Point pt; /* Mouse down point */
{
register short partCtrl; /* Working control part */
ControlHandle ctrlHdl; /* Working control handle*/
/* Check if got ctrl part*/
if (partCtrl = FindControl(pt,wp,&ctrlHdl)) {
ClipRect(&wp->portRect); /* Setup clippings */
if (partCtrl == inThumb) {/* Check if using thumb */
/* Save cur ctrls value */
SetCRefCon(ctrlHdl,GetCtlValue(ctrlHdl));
ClipRect(&wp->portRect); /* Reset for a moment */
TrackControl(ctrlHdl,pt,NIL);/* Let track by thumb*/
DoTextScroll(ctrlHdl,inThumb);/* OK, lets scroll */
DoRestoreClippings(); /* Restore view clippings*/
}
else { /* Nope, other types */
ClipRect(&wp->portRect); /* Reset for a moment */
TrackControl(ctrlHdl,pt,DoTextScroll);/* Scroll it*/
DoRestoreClippings(); /* Restore text clippings*/
}
}
return(partCtrl); /* Return part control */
}
pascal void DoTextScroll(ctrlHdl,partCtrl)
ControlHandle ctrlHdl; /* Control scroll handle */
short partCtrl; /* Controls part */
{
register short delta; /* Working delta scroll */
register short value; /* Working current value */
register short maxValue; /* Working maximum value */
register short viewLines; /* Working view lines */
short dh = 0; /* Working delta horz */
long dv = 0; /* Working delta vertical*/
PEPtr pePtr; /* Working edit pointer */
SetUpA4(); /* Setup register A4 */
delta = GetCtlValue(ctrlHdl);/* Get current value */
maxValue = GetCtlMax(ctrlHdl);/* Get maximum value */
switch(partCtrl) { /* Handle request: */
case 0: /* Nothing */
return;
case inUpButton:
value = max(0,delta - 1);/* Set new value position*/
break;
case inDownButton:
value = min(maxValue,delta + 1);/* Set new value */
break;
case inPageUp: /* Page Up */
case inPageDown: /* Page Down */
if (ctrlHdl == vScrollBar) {/* Check if vertical */
pePtr = *peHdl; /* Set edit text pointer */
/* Set vis lines by half */
viewLines = (pePtr->viewRect.bottom -
pePtr->viewRect.top) / pePtr->lineHeight;
if (partCtrl == inPageUp)/* Check if page up reg */
value = max(0,delta - viewLines);
else /* Nope, page down region*/
value = min(maxValue,delta + viewLines);
}
else { /* Check if horizontal */
if (partCtrl == inPageUp)/* Check if page up reg */
value = max(0,delta - 10);/* Set new position */
else /* Nope, page down region*/
value = min(maxValue,delta + 10);
}
break;
case inThumb: /* Thumb */
delta = GetCRefCon(ctrlHdl);/* Get starting value */
value = GetCtlValue(ctrlHdl);/* Get new value */
}
SetCtlValue(ctrlHdl,value);/* Reset the value */
if (hScrollBar == ctrlHdl) /* Check if horzontal */
dh = delta - value; /* Set horizontal offset */
else
dv = delta - value; /* Set vertical offset */
DoRestoreClippings(); /* Restore view clippings*/
if (dh || dv) /* Check if should scroll*/
PEScroll(dh * CharWidth( ),dv,peHdl);/* Scroll it*/
ClipRect(&wp->portRect); /* Reset clippings */
RestoreA4(); /* Restore register A4 */
}
pascal void DoClickScroll(peHdl)
register PEHandle peHdl; /* Edit data handle */
{
register Rect viewRect;/* Working view rect area*/
Point pt; /* Working mouse point */
viewRect = (*peHdl)->viewRect;/* Set view rect area */
GetMouse(&pt); /* Get current mouse */
if (pt.v < viewRect.top) /* Check if going upward */
DoTextScroll(vScrollBar,inUpButton);
else if (pt.v > viewRect.bottom)/* Check if downward*/
DoTextScroll(vScrollBar,inDownButton);
else if (pt.h < viewRect.left)/* Check if leftward */
DoTextScroll(hScrollBar,inUpButton);
else if (pt.h > viewRect.right)/* Check if rightward*/
DoTextScroll(hScrollBar,inDownButton);
}
pascal void DoHighLite(hilite,pePtr)
Rect *hilite; /* Highlite rect area */
register PEPtr pePtr; /* Edit text pointer */
{
HiliteMode &= 0x7f; /* Set highliting bit */
InvertRect(hilite); /* Invert rect area */
}
DoNewLineToReturn(s)
char *s; /* Input string pointer */
{
while(*s) { /* Cvt NEW-LINE to RETURN*/
if (*s == \n) /* Check if NEW-LINE char*/
*s = \r; /* Convert to RETURN char*/
s += 1; /* Bump to next character*/
}
}
DoPrintLine(format,args)
char *format; /* Format string pointer */
va_list args; /* Arguments list */
{
vsprintf(PrintOutputBuf,format,&args);/* Format buf */
DoNewLineToReturn(PrintOutputBuf);/*Convert NEW-LINE*/
/* Output string */
PEInsert(PrintOutputBuf,DbgStrLen(PrintOutputBuf), peHdl);
DoAdjustScrollBar(); /* Adjust the scroll bar */
}
DoDbgPrintSetUp(fmt)
char *fmt; /* Input format pointer */
{
register short fLen; /* Working format str len*/
register char *stack; /* Working fake stack ptr*/
fLen = DbgStrLen(fmt) + 1; /* Set string length */
if (fLen & 0x1) /* Check if even # chars */
fLen += 1; /* Align it to even addr */
stack = fmt + fLen; /* Set format string addr*/
*((long *)(stack)) = ((long)(fmt));
DoDbgPrint(stack); /* OK, lets really do it*/
}
DoDbgPrint(args)
long *args; /* Input arguments list */
{
DoSetupView(); /* Setup the view display*/
DoAdjustView(); /* Adjust the view */
vsprintf(PrintOutputBuf,*args,args + 1L);/*Format it*/
DoNewLineToReturn(PrintOutputBuf);/*Convert NEW-LINE*/
/* Output string */
PEInsert(PrintOutputBuf,DbgStrLen(PrintOutputBuf), peHdl);
DoAdjustScrollBar(); /* Adjust the scroll bar */
}
DoPrintDump(ptr,size)
char *ptr; /* Print buffer pointer */
long size; /* Print buffer length */
{
register long i,j,k,m,n;/* Working indexes */
register char *tptr; /* Working temporary ptr */
Str255 buffer; /* Working string buffer */
Str255 tbuffer; /* Working temp buffer */
DoSetupView(); /* Setup the view display*/
DoAdjustView(); /* Adjust the view */
/* Output # of bytes */
DoPrintLine(\nNumber of bytes - %ld\n,size);
DoPrintLine(Cnt Address %s %s\n,
Hex Values--------------------------------------------------,
ASCII Values--------);
for(i = 0L; i < size; i += 16L) {/*Transfer all data*/
n = 14L; /* Set init buffer index */
for(j = 0L; j < sizeof(buffer); j++)/* Clr buf str */
buffer[j] = ; /* Pad it with spaces */
sprintf(buffer,%04ld %08lx ,i,tptr = ptr);
j = i; k = m = 0L; /* Init indexes */
while(j < size && m < 16L) {/* Output hex parts */
m += 1L; /* Bump # of characters */
if (k++ == 3L) { /* Check if time to pad */
sprintf(tbuffer,%04x ,*tptr++);/* Get char hex */
/* Add it to output buf */
BlockMove(&tbuffer[2],&buffer[n],
DbgStrLen((char *)(&tbuffer[2])) + 1);
k = 0L; /* Reset index */
n += 1L; /* Bump one extra */
}
else {
sprintf(tbuffer,%04x,*tptr++);/* Get char hex */
/* Add it to output buf */
BlockMove(&tbuffer[2],&buffer[n],
DbgStrLen((char *)(&tbuffer[2])) + 1);
}
j += 1L; /* Bump to next character*/
n += 2L; /* Bump for two hex chars*/
}
buffer[n] = ; /* Remove end-of-string */
n = 50L; /* Reset character index */
j = i; m = 0L; /* Init indexes */
while(j < size && m < 16L) {/* Output hex parts */
j += 1L; /* Bump to next character*/
m += 1L; /* Bump # of characters */
if (isprint(*ptr)) /* Check if printable */
sprintf(&buffer[n],%c,*ptr++);/* Output char */
else { /* Its not printable */
BlockMove(.,&buffer[n],2L);/* Show period only */
ptr += 1L; /* Bump to next character*/
}
n += 1L; /* Bump for one character*/
}
/* Add RETURN character */
BlockMove(\r,&buffer[DbgStrLen((char *)(buffer))], 2L);
DoPrintLine(%s,buffer); /* Output the string */
}
}
DoRestoreClippings()
{
Rect wRect; /* Working rect area */
if (peHdl) { /* Check if its valid */
wRect = (*peHdl)->viewRect;/* Restore clipping */
ClipRect(&wRect);
}
}
DoAdjustScrollBar()
{
register short viewHeight;/* Working view height */
register short hiddenLines;/* Working # hidden line*/
register PEPtr pePtr; /* Working edit pointer */
if (peHdl) { /* Check if have edit hdl*/
pePtr = *peHdl; /* Set edit pointer */
if (pePtr->peLength) { /*Check if there any text*/
ClipRect(&wp->portRect); /* Reset clippings */
if (hScrollBar) { /* Check if there a horz */
if (!GetCtlMax(hScrollBar))/* Check if not init */
SetCtlMax(hScrollBar,maxColumns);/* Reset to max*/
}
if (vScrollBar) { /* Check if there a vert */
/* Set view height */
viewHeight = abs(pePtr->viewRect.bottom -
pePtr->viewRect.top);
/*Check if need to enable*/
if (pePtr->nLines*pePtr->lineHeight > viewHeight) {
/* Set # of hidden lines */
hiddenLines = max(0,pePtr->nLines - viewHeight /
pePtr->lineHeight);
/*Check if hidden changed*/
if (GetCtlMax(vScrollBar) != hiddenLines) {
/* Update maximum # lines*/
(*vScrollBar)->contrlMax = hiddenLines - 1;
/* Adjust thumb position */
SetCtlValue(vScrollBar,
min((short)pePtr->viewOrgV, hiddenLines - 1));
DoAdjustView(); /* Adjust the view */
}
}
else { /* Nope, disable scroll */
/* Check if its enabled */
if (GetCtlMax(vScrollBar)) {
(*vScrollBar)->contrlMax = 0;/* Reset it */
SetCtlValue(vScrollBar,0);
}
}
}
}
else { /* Reset the scroll bars */
if (hScrollBar) { /* Check if there a horz */
if (GetCtlMax(hScrollBar)) {/* Check if enabled */
(*hScrollBar)->contrlMax = 0;/* Reset it */
SetCtlValue(hScrollBar,0);
}
}
if (vScrollBar) { /* Check if there a vert */
if (GetCtlMax(vScrollBar)) {/* Check if enabled */
(*vScrollBar)->contrlMax = 0;/* Reset it */
SetCtlValue(vScrollBar,0);
}
}
}
DoRestoreClippings(); /* Restore view clippings */
}
}
DoSetupView()
{
register PEPtr pePtr; /* Working edit data ptr */
if (peHdl) { /* Check if have edit hdl*/
pePtr = *peHdl; /* Set edit pointer */
/* Check if selected text*/
if (pePtr->selStart != pePtr->selEnd)
PESetSelect(pePtr->peLength,pePtr->peLength,peHdl);
/* Check not end-of-text */
else if (pePtr->selStart != pePtr->peLength)
PESetSelect(pePtr->peLength,pePtr->peLength,peHdl);
}
}
DoAdjustView()
{
register PEPtr pePtr; /* Working edit data ptr */
long delta; /* Working delta offset */
long currentLine;/* Cur line selection*/
register long selectLine;/* Working line sel */
register long viewLines;/* Working view lines */
long hViewLines;/* Half view lines */
register long viewOrgV;/* Origin view offset */
long saveSelStr;/* Save selStart value*/
long saveSelEnd;/* Save selEnd value */
register long status = TRUE;/* Adjust view flag*/
short adjust = FALSE;/* Vert adjustment*/
if (peHdl) { /* Check if have edit hdl*/
DoRestoreClippings(); /* Restore view clippings*/
pePtr = *peHdl; /* Set edit text pointer */
if (optHdl) { /* Check if hdl valid */
if ((*optHdl)->maxTextSize) {/* Check if maxing */
/* Set cur line to chop */
currentLine = pePtr->peLength - (*optHdl)->maxTextSize;
if (currentLine > 0) { /* Check if time to chop */
PECloseGap(peHdl); /* Close the gap first */
saveSelStr = pePtr->selStart;/* Save start sel */
saveSelEnd = pePtr->selEnd;/* Save end selection*/
/* Reset selection */
PESetSelect(0L,currentLine = PEEol(currentLine,
peHdl) + 1L,peHdl);
PEDelete(peHdl); /* OK, lets delete it */
/* Restore it */
PESetSelect(saveSelStr - currentLine,
saveSelEnd - currentLine,peHdl);
}
}
}
pePtr = *peHdl; /* Set edit text pointer */
viewOrgV = pePtr->viewOrgV;/*Set view origin offset*/
/* Set # of visible lines*/
viewLines = abs(pePtr->viewRect.bottom -
pePtr->viewRect.top) /
pePtr->lineHeight;
hViewLines = viewLines / 2;/*Half of the view lines*/
/* Set selected line # */
selectLine=currentLine=PELineNum(pePtr->selEnd,peHdl);
pePtr = *peHdl; /* Reset edit text ptr */
/* Check if within view */
if (selectLine >= viewOrgV &&
selectLine < viewOrgV + viewLines)
status = FALSE;
if (status) { /* Check if should adjust*/
adjust = TRUE; /* Set adjust vert offset*/
selectLine -= viewOrgV; /* Adjust select line # */
if (selectLine == viewLines)/* Check if just off */
selectLine -= viewLines - 1;/* Adjust by one line*/
/* Check if close bottom */
else if (delta = (pePtr->nLines - currentLine -
1 - hViewLines) < 0)
selectLine += delta - viewLines;/*Adjust to bottom*/
else if (selectLine != -1)/*Check if completely off*/
selectLine -= hViewLines;/* Center the page */
selectLine += viewOrgV; /*Adjust physical offset */
/* Scroll to cursor */
PEScrollTo(pePtr->viewOrgH,selectLine,peHdl);
}
}
}
DoResizeScrollBar()
{
Rect wRect; /* Window rect area */
if (peHdl) { /*Check if have edit hdl*/
wRect.left = wp->portRect.left;
wRect.top = wp->portRect.top + 5;
wRect.right = wp->portRect.right - 15;
wRect.bottom = wp->portRect.bottom - 15;
(*peHdl)->viewRect = wRect;
}
if (hScrollBar) { /* Check if have scroll */
/* Compute rect area */
wRect.left = wp->portRect.left - 1;
wRect.top = wp->portRect.bottom - 15;
wRect.right = wp->portRect.right - 14;
wRect.bottom = wp->portRect.bottom + 1;
(*hScrollBar)->contrlRect = wRect;/* Set new rect */
}
if (vScrollBar) { /* Check if have scroll */
/* Compute rect area */
wRect.left = wp->portRect.right - 15;
wRect.top = wp->portRect.top - 1;
wRect.right = wp->portRect.right + 1;
wRect.bottom = wp->portRect.bottom - 14;
(*vScrollBar)->contrlRect = wRect;/* Set new ret */
}
}
DialogTHndl DoDlgCenter(type,id)
long type; /* Resource type id */
short id; /* Id # */
{
register DialogTHndl dhdl; /* Working dialog handle */
register DialogTPtr dptr; /* Working dialog ptr */
WindowPtr wPtr; /* Working window ptr */
register short swidth;/*Working 1/2 horz width*/
register short width;/*Working 1/2 horz width */
/* Check if got dlg hdl */
if (dhdl = ((DialogTHndl)GetResource(type,
GetResourceID(id)))) {
GetWMgrPort(&wPtr); /* Get window mgr ptr */
dptr = *dhdl; /* Set dialog ptr */
/* Set 1/2 screen width */
swidth = abs(wPtr->portRect.right -
wPtr->portRect.left) / 2;
/* Set 1/2 dialog width */
width = abs(dptr->boundsRect.right -
dptr->boundsRect.left) / 2;
/* Center the dialog */
dptr->boundsRect.left = swidth - width;
dptr->boundsRect.right = swidth + width;
}
return(dhdl); /* Return dialog handle */
}
DoItemIdx(item,menu)
register unsigned char *item;/* Item string look up */
register MenuHandle menu;/* Menu handle */
{
register short i,j; /* Working index */
register unsigned short len = *item++;/* Item length*/
Str255 wStr; /* Working string */
/* Look for matching item*/
for(i = 1, j = CountMItems(menu); i <= j; i++) {
GetItem(menu,i,&wStr); /* Working string */
if (!IUMagString(item,&wStr[1],len,len))/* Matches?*/
return(i); /* Found matching string */
}
return(1); /* Opps, didnt find it */
}
GetResourceID(n)
{ return(0xC000 + ((~(dce->dCtlRefNum))<<5) + n); }
/*
* Source - Debugger.c
* Author - Alexander S. Colwell,
* Copyright (C) 1988, 1989
* Purpose - This is the Debugger Window DA
* interface routines.
*/
#include Debugger.h /* Debugger defs */
/* Device ctrl entry func*/
#define DbgDCtlEntry(refNbr) (UTableBase[-1*(refNbr+1)])
short DbgArgCnt(); /* Define forward refs */
DBGHDL DbgGetRefHdl()
{
register DBGHDL dbgHdl; /* DAs reference # hdl */
asm { /* Debuggers res name */
CLR.L -(sp) ;Allocate return handle
PEA debuggerType ;Load resource type
PEA @dbgRef ;Load resource name
_GetNamedResource ;Get resource handle
MOVE.L (sp)+,dbgHdl ;Save resource handle
BRA.S @dbgExit ;Skip around resource name
dbgRef: DC.B 18,D,e,b,u,g,g,e,r, ,R,e,f,e,r,e,n,c,e
dbgExit:
}
return(dbgHdl); /* Return resource handle*/
}
void DbgPrint(dbgHdl,args)
register DBGHDL dbgHdl; /* Working DAs ref # hdl*/
char *args; /* Input arguments */
{
register short refNbr; /* Working DAs ref # */
register short daEnable; /* Working save DA state */
register DCtlHandle dceHdl;/* Device control entry */
if (dbgHdl) { /* Check if got handle */
if (refNbr = (*dbgHdl)->daRefNbr) {/*Check if valid*/
/* Check if got dev hdl */
if (dceHdl = GetDCtlEntry(refNbr)) {
/* Save enabled stated */
daEnable = (*dceHdl)->dCtlFlags & dCtlEnable;
/* Enable DAs entry */
(*dceHdl)->dCtlFlags |= dCtlEnable;
Control(refNbr,accDbgPrint,&args);/* Write it */
if (!daEnable) /* Check if not enabled */
(*dceHdl)->dCtlFlags &= ~dCtlEnable;
}
}
}
}
void DbgBufPrint(args)
long *args; /* Input arguments */
{
register DBGHDL dbgHdl; /* Working DAs ref # hdl*/
register DBGPTR dbgPtr; /* Working DAs ref hdl */
DCtlHandle dceHdl; /* Working device ctrl */
register char *fmt; /* Working format string */
register char *buf; /* Working buffer address*/
long *addr; /* Working stack address */
register long fLen; /* Working format str len*/
register long dLen; /* Working data buf len */
register long argc; /* Working # of arg bytes*/
register long nextIdx; /* Working next table idx*/
register long dataIdx; /* Working data index */
dbgHdl = (DBGHDL)(&args[0]);/* Set debugger handle */
if (dbgHdl) { /* Check if got handle */
dbgPtr = *dbgHdl; /* Setup debugger pointer*/
if (dbgPtr->daRefNbr) { /* Check if its valid */
/* Check if got device */
if (dceHdl = DbgDCtlEntry(dbgPtr->daRefNbr)) {
/* Check if have buffers */
if (dbgPtr->bufTable && dbgPtr->bufData) {
/* Set next tbl idx entry*/
nextIdx = (dbgPtr->bufNextIdx + 1L) %
dbgPtr->bufTableSize;
if (nextIdx == dbgPtr->bufTableIdx)/* Overflow? */
dbgPtr->bufError = dbgTableOvrFlw;
else { /* Nope, continue */
argc = DbgArgCnt(&args) - 4L;/* Get # of args */
if (argc >= 4L) { /* Check if has fmt str */
addr = (long *)(&args);/* Set stack address */
fmt = (char *)(addr[1]);/* Get variable arg */
fLen = DbgStrLen(fmt) + 1L;/* Get fmt str len */
if (fLen & 0x1L) /* Check if even align */
fLen += 1L; /* Align it */
dLen = argc + fLen + 2L;/* Total buf length */
/* Check if time buf wrap*/
if ((dataIdx = dbgPtr->bufDataIdx) + dLen >=
dbgPtr->bufDataSize)
dataIdx = 0L; /* Reset begin-of-buffer */
if (dLen > dbgPtr->bufDataSize)/* Buf to big?*/
dbgPtr->bufError = dbgBufOvrFlw;
/* Check if any in buffer*/
else if (dbgPtr->bufTableIdx != dbgPtr->bufNextIdx) {
/* Check if buf overflow */
if (dataIdx < (*dbgPtr->bufTable)[dbgPtr->bufTableIdx+1L])
if (dLen + dataIdx > (*dbgPtr->bufTable)[dbgPtr->bufTableIdx+1L])
dbgPtr->bufError = dbgDataOvrFlw;
}
if (!dbgPtr->bufError) {/* Check no overflow */
dbgPtr->bufNextIdx = nextIdx;/* Set next lin*/
/* Save data buffer index*/
(*dbgPtr->bufTable)[nextIdx] = dataIdx;
/* Set buffer address */
buf = &(*dbgPtr->bufData)[dataIdx];
*buf = accDbgPrint;/* Set code */
BlockMove(fmt,buf + 2L,fLen);/* Copy fmt str*/
/* Copy the stack */
BlockMove(&addr[1],buf + fLen + 2L,argc);
/* Bump to next position */
dbgPtr->bufDataIdx = dataIdx + dLen;
(*dceHdl)->dCtlFlags |= dNeedTime;/* Enable */
(*dceHdl)->dCtlDelay = 1;/* Reset delay time*/
}
}
}
}
}
}
}
}
void DbgDump(dbgHdl,buffer,size)
register DBGHDL dbgHdl; /* Working DAs ref # hdl*/
char *buffer; /* Input buffer */
long size; /* Input buffer size */
{
register short refNbr; /* Working DAs ref # */
register short daEnable; /* Working save DA state */
register DCtlHandle dceHdl;/* Working dev ctrl entry*/
long csParam[2];/* Working ctrl parm list*/
if (dbgHdl) { /* Check if got handle */
if (refNbr = (*dbgHdl)->daRefNbr) {/*Check if valid*/
/*Check if got device hdl*/
if (dceHdl = GetDCtlEntry(refNbr)) {
/* Save enabled stated */
daEnable = (*dceHdl)->dCtlFlags & dCtlEnable;
/* Enable DAs entry */
(*dceHdl)->dCtlFlags |= dCtlEnable;
csParam[0] = (long)(buffer);/* Init param list */
csParam[1] = size;
/* OK, lets dump it now */
Control(refNbr,accDbgDump,csParam);
if (!daEnable) /* Check if not enabled */
(*dceHdl)->dCtlFlags &= ~dCtlEnable;
}
}
}
}
void DbgBufDump(dbgHdl,buffer,size)
register DBGHDL dbgHdl; /* Working DAs ref # hdl*/
char *buffer; /* Input buffer */
long size; /* Input buffer size */
{
register DBGPTR dbgPtr; /* Working DAs ref hdl */
DCtlHandle dceHdl; /* Working dev ctrl entry*/
register char *buf; /* Working buffer address*/
register long dLen; /* Working data buf len */
register long argc; /* Working # of arg bytes*/
register long nextIdx; /* Working next table idx*/
register long dataIdx; /* Working data index */
if (dbgHdl) { /* Check if got handle */
dbgPtr = *dbgHdl; /* Setup debugger pointer*/
if (dbgPtr->daRefNbr) { /* Check if its valid */
/* Check if got dev hdl */
if (dceHdl = DbgDCtlEntry(dbgPtr->daRefNbr)) {
/* Check if have buffers */
if (dbgPtr->bufTable && dbgPtr->bufData) {
/* Set next tbl idx entry*/
nextIdx = (dbgPtr->bufNextIdx + 1L) %
dbgPtr->bufTableSize;
if (nextIdx == dbgPtr->bufTableIdx)/* Overflow? */
dbgPtr->bufError = dbgTableOvrFlw;
else { /* Nope, continue */
dLen = size + sizeof(size) + 2L;/*Total buf len*/
if (dLen & 0x1L) /* Check if odd size */
dLen += 1L; /* Lets make it even */
/* Check if time buf wrap*/
if ((dataIdx = dbgPtr->bufDataIdx) + dLen >=
dbgPtr->bufDataSize)
dataIdx = 0L; /* Reset begin-of-buffer */
if (dLen > dbgPtr->bufDataSize)/*Buffer to big?*/
dbgPtr->bufError = dbgBufOvrFlw;
/* Check if any in buffer*/
else if (dbgPtr->bufTableIdx != dbgPtr->bufNextIdx) {
/* Check if buf overflow */
if (dataIdx <
(*dbgPtr->bufTable)[dbgPtr->bufTableIdx+1L])
if (dLen + dataIdx >
(*dbgPtr->bufTable)[dbgPtr->bufTableIdx+1L])
dbgPtr->bufError = dbgDataOvrFlw;
}
if (!dbgPtr->bufError) {/* Check if no overflow*/
dbgPtr->bufNextIdx = nextIdx;/* Set next line */
/* Save data buffer index*/
(*dbgPtr->bufTable)[nextIdx] = dataIdx;
/* Set buffer address */
buf = &(*dbgPtr->bufData)[dataIdx];
*buf = accDbgDump; /* Set code */
/* Copy size of buffer */
BlockMove(&size,buf + 2L,(long)(sizeof(size)));
/* Copy the buffer */
BlockMove(buffer,buf + sizeof(size) + 2L,size);
/* Bump to next position */
dbgPtr->bufDataIdx = dataIdx + dLen;
(*dceHdl)->dCtlFlags |= dNeedTime;/* Enable it*/
(*dceHdl)->dCtlDelay = 1;/* Reset delay timer */
}
}
}
}
}
}
}
short DbgArgCnt(vararg)
long vararg; /* Variable argument list */
{
register union { /* Union of 3 var types */
long addr; /* Address of the types */
long **args;
} varg; /* Working var arg list */
register unsigned long instr;/* Working instruction */
register long arg; /* Working argument */
register long count = 0L;/* # of arguments */
varg.addr = vararg; /* Init variable arg list */
varg.addr -= 4; /* Position to instruction*/
instr = **varg.args & 0xffff0000;/* Set instr word */
if (instr == 0x4fef0000) /* Check if ADD instr */
count = (**varg.args & 0x0000ffff );/* Set # of bytes*/
/* Check if ADDI instr */
else if ((instr & 0xf1ff0000) == 0x508f0000) {
/* Check if 0, then 8 byte*/
if (!(count = ((instr & 0x0e000000) >> 25)))
count = 8; /* Reset 8 bytes on stack */
}
return(count); /* Return count */
}
long DbgStrLen(s)
register char *s; /* String pointer */
{
register long sLen = 0; /* String length */
while(*s++) /* Continue to end-of-str*/
sLen++; /* Bump string length */
return(sLen); /* Return string length */
}
*
* Resource - DebuggerDA.R
* Author - Alexander S. Colwell,
* Copyright (C) 1988, 1989
* Purpose - This is the resource file for the
* Debugger Window DA.
*
DebuggerDA.Π.rsrc
rsrcRSED
Type MENU
Debugger Menu,-16000
Debugger
About This Debugger Window.../?
(-
Stop Output/S
Quit/Q
Type STR#
Debugger Misc,-16000 (32)
5
Start Output
Stop Output
ERROR: Table index overflow
ERROR: Data buffer overflow
ERROR: Buffer size overflow
Debugger Errors,-15999 (32)
6
Sorry, fail to open DA. Perhaps running low on memory.
DAs global memory allocation fail. Running low on memory.
Warning, running low on memory!
Sorry, require 4.1 or higher System file version.
Sorry, cannot run under Lisa clone Macintosh.
Sorry, cannot run on Mac 128K or 512K computer.
Type WIND
Debugger,-16000 (32)
Debugger Window
227 10 337 502
NoVisible GoAway
8
0
Type DLOG
Debugger Info,-16000 (32)
Info
64 92 105 323
Visible NoGoAway
1
0
-16000
Type ALRT
Debugger Alert,-15999 (32)
100 100 199 401
-15999
4444
Type DITL
Debugger Info,-16000 (32)
1
StatText Enabled
5 5 110 278
Debugger Window, Version 1.0 Written by Alexander S. Colwell
Debugger Alert,-15999 (32)
2
BtnItem Enabled
71 215 91 294
OK
StatText Enabled
8 60 63 297
^0
Type Opts = GNRL
Debugger Options,-16000
.I
0
4
9
4
.L
100
2048
Type Dbgr = GNRL
Debugger Reference,-16000 (32)
.I
0
0
.L
0
0
0
0
0
0
0
/*
* Source - Round Window.c
* Author - Alexander S. Colwell,
* Copyright (C) 1988, 1989
* Purpose - This will display a round window using
* Debugger Window DA demostration.
*/
#include <Color.h> /* Color Manager defs */
#include <math.h> /* Math defs */
#include <SetUpA4.h> /* Desk Accessory defs */
#include <VRetraceMgr.h> /* Vertical Retrace defs */
#include Debugger.h /* Debugger defs */
/* Misc definitions */
#define NIL (0L) /* NIL pointer */
#define abs(a) (a<0?-a:a) /* Absolute macro func */
#define min(a,b) (a<b?a:b) /* Minumim macro function*/
#define max(a,b) (a<b?b:a) /* Maximum macro function*/
/* Resource ID #s */
#define windID 0 /* Window ID # */
#define helloWorld \pHello, World/* String message */
typedef struct { /* VBL data structure */
VBLTask vblTask; /* VBL */
DBGHDL dbgHdl; /* Debugger handler */
short counter; /* Tick counter */
} VBL;
typedef VBL *VBLPTR;
DCtlPtr dce; /* Device control entry */
WindowPtr wp = NIL; /* My window pointer */
short alreadyOpen = FALSE;/* DA is opened */
VBLPTR vblPtr = NIL;/* VBL data block */
Handle vblHdl = NIL;/* VBL code handle */
DBGHDL dbgHdl = NIL;/* Debugger reference hdl*/
main(p,d,n)
cntrlParam *p; /* Parameter block */
DCtlPtr d; /* Device control entry */
short n; /* Entry point selector */
{
WindowPtr savePort; /* Save cur window port */
if (d->dCtlStorage == 0) { /* Check if got globals */
if (n == 0) { /*Check if request Open*/
SysBeep(1); /* Beep da user! */
CloseDriver(d->dCtlRefNum);/* Close the DA */
}
}
else { /* Got globals then cont */
GetPort(&savePort); /* Get cur window port */
if (wp) /* Check if win ptr valid*/
SetPort(wp); /* Set port to my window */
dce = d; /* Save DCE in our global*/
dce->dCtlFlags &= ~dCtlEnable;/* Set not re-entrant*/
switch(n) { /* Handle request: */
case 0: /* Open */
DoOpen(); break;
case 2: /* Control */
DoControl(p->csCode,p->csParam); break;
case 4: /* Close */
DoClose(); break;
}
dce->dCtlFlags |= dCtlEnable;/* Enable calls again */
SetPort(savePort); /* OK, lets restore it */
}
return(0); /* Return default success*/
}
DoOpen()
{
Handle wDEFHdl; /* Working window def hdl*/
/* Add driver flags */
dce->dCtlFlags |= dNeedLock|dNeedGoodBye;
if (wp) /* Check if there a wind */
SelectWindow(wp); /* Bring our window front*/
if (!alreadyOpen) { /* Check if require inits*/
wp = GetNewWindow(GetResourceID(windID),NIL,-1L);
if (wp) { /* Check if got window */
/* Check if got our WDEF */
if (wDEFHdl = GetResource(WDEF,GetResourceID(0)))
((WindowPeek)(wp))->windowDefProc = wDEFHdl;
ShowWindow(wp); /* Show the window now */
SetPort(wp); /* Set port to our window*/
alreadyOpen = TRUE; /* Set open DA indicator */
/*Save window association*/
((WindowPeek)wp)->windowKind = dce->dCtlRefNum;
dce->dCtlWindow = wp; /* Tell device where I am*/
dbgHdl = DbgGetRefHdl(); /* Get reference handle */
/* Check if got VBL ptr */
if (vblPtr = (VBLPTR)(NewPtr((long)sizeof(VBL)))) {
/* Check if got VBL code */
if (vblHdl = GetResource(VBLC,GetResourceID(0))){
HLock(vblHdl); /* Lock it for VBL task */
/* Init VBL task */
vblPtr->vblTask.vblAddr = (ProcPtr)(*vblHdl);
vblPtr->vblTask.vblCount = 120;
vblPtr->vblTask.vblPhase = 0;
vblPtr->vblTask.qType = vType;
vblPtr->dbgHdl = dbgHdl;
vblPtr->counter = 120;
VInstall(vblPtr); /* Install the VBL task */
}
}
}
else { /* Fail to open */
SysBeep(1); /* Beep da user! */
CloseDriver(dce->dCtlRefNum);/* OK, lets close DA*/
}
}
}
DoClose()
{
if (wp) /* Check if win ptr valid*/
DisposeWindow(wp); /* Delete the window now */
wp = NIL; /* Invalidate it now */
if (vblPtr && vblHdl) /* Check if VBL installed*/
VRemove(vblPtr);
if (vblPtr) /* Check if has VBL ptr */
DisposPtr(vblPtr); /* Release it now */
vblPtr = NIL; /* Invalidate it now */
if (vblHdl) { /* Check if has VBL hdl */
HUnlock(vblHdl); /* OK, it safe unlock it */
ReleaseResource(vblHdl); /* Release it now */
}
vblHdl = NIL; /* Invalidate it now */
alreadyOpen = FALSE; /* Reset it */
}
DoControl(code,parm)
short code; /* Control command code */
short *parm; /* csParam list pointer*/
{
switch(code) { /* Handle request: */
case accEvent: /* Event */
DoEvent(*((EventRecord **)parm)); break;
case goodBye: /* GoodBye */
DoClose(); break;
}
}
DoEvent(e)
register EventRecord *e; /* Event Record pointer */
{
/* Output DAs event type*/
DbgPrint(dbgHdl,DA Event: what - %d\n,e->what);
switch(e->what) { /* Handle request: */
case updateEvt: /* Update */
DoUpdate(); break;
case mouseDown: /* Mouse Down */
DoMouse(e->where,e->modifiers); break;
case keyDown: /* Key Down */
case autoKey: /* Auto-Key Down */
/* Handle the input key */
DoKey((char)(e->message & charCodeMask),
(char)((e->message & keyCodeMask) >> 8L),
e->modifiers);
}
}
DoUpdate()
{
BeginUpdate(wp); /* Start update process */
EraseRect(&wp->portRect); /* Clear the window */
MoveTo(abs(wp->portRect.right - wp->portRect.left)/2 -
StringWidth(helloWorld) / 2,
abs(wp->portRect.bottom - wp->portRect.top)/2);
DrawString(helloWorld); /* Draw string message */
EndUpdate(wp); /* Wrapup update process */
}
DoMouse(p,modifiers)
Point p; /* Mouse point position */
short modifiers; /* Mouses modifiers */
{
register long i; /* Working index */
Rect wRect; /* Working window rect */
register long wGrow; /* Working grow size */
ProcPtr wDef; /* Working wind proc hdl */
/* Load it into memory */
LoadResource(((WindowPeek)wp)->windowDefProc);
HLock(((WindowPeek)wp)->windowDefProc);/* Lock it */
/* Get window proc def */
wDef = (ProcPtr)*((WindowPeek)wp)->windowDefProc;
/* Check if in Content */
if (CallPascalL(8,wp,(int)wHit,p,wDef) == wInContent)
DoContent(p,modifiers);
HUnlock(((WindowPeek)wp)->windowDefProc);
}
DoKey(c,code,modifiers)
char c; /* Input character */
char code; /* Input code */
short modifiers; /* Input modifiers */
{
if (modifiers & cmdKey) { /* Check if key command */
if (c == q) /* Check if time to quit */
CloseDriver(dce->dCtlRefNum);/* OK, lets close DA*/
else /* Opps, invalid command */
SysBeep(1); /* Let the user know it */
}
}
DoContent(p,modifiers)
Point p; /* Mouse down point */
short modifiers; /* Mouses modifiers */
{
Rect wRect; /* Working window rect */
register long wGrow; /* Working grow point */
WindowPtr wPtr; /* Working window pointer*/
/* Check if want to resiz*/
if (modifiers & (shiftKey | optionKey | cmdKey)) {
SetRect(&wRect,50,50,32767,32767);/* Define limits */
wGrow = GrowWindow(wp,p,&wRect);/* OK, let grow it */
if (wGrow) { /* Check if got new size */
/* Reset new size */
SizeWindow(wp,LoWord(wGrow),HiWord(wGrow),TRUE);
InvalRect(&wp->portRect);/* Invalidate everything */
}
}
else { /* Nope, just move it */
GetWMgrPort(&wPtr); /* Get window manager ptr*/
DragWindow(wp,p,&wPtr->portRect);/* Drag the window*/
}
}
GetResourceID(n)
{ return(0xC000 + ((~(dce->dCtlRefNum))<<5) + n); }
*
* Resource - Round Window.R
* Author - Alexander S. Colwell,
* Copyright (C) 1988
* Purpose - This is resource file for Round Window.
*
Round Window.Π.rsrc
rsrcRSED
Type WIND
Clock,-16000 (32)
Clock
64 64 187 187
NoVisible GoAway
2
0
include RoundWDEF.Π.rsrc
include RoundVBL.Π.rsrc
/*
* Source - RoundVBL.c
* Author - Alexander S. Colwell,
* Copyright (C) 1988
* Purpose - This is VBL def for Debugger DAs demo.
*/
#include <VRetraceMgr.h> /* Vertical Retrace defs */
#include <SetupA4.h> /* Setup Register A4 defs*/
#include Debugger.h /* Debugger defs */
typedef struct { /* VBL data structure */
VBLTask vblTask; /* VBL */
DBGHDL dbgHdl; /* Debugger handler */
short counter; /* Tick counter */
} VBL;
typedef VBL *VBLPTR;
main()
{
register VBLPTR vblPtr; /* Working VBL data block*/
asm { MOVE.L d0,vblPtr }; /* Move to vblPtr */
RememberA0(); /* Remember global ptr */
SetUpA4(); /* Setup register A4 */
/* Output entry message */
DbgBufPrint(vblPtr->dbgHdl,VBL: entry\n);
/* Reset timer */
vblPtr->vblTask.vblCount = vblPtr->counter;
RestoreA4(); /* Restore register A4 */
}
/*
* Source - RoundWDEF.c
* Author - Alexander S. Colwell,
* Copyright (C) 1988
* Purpose - This is WDEF def for Debugger DAs demo.
*/
#include <WindowMgr.h> /* Window Manager defs */
#include <SetUpA4.h> /* Setup Register A4 */
#include Debugger.h /* Debugger defs */
/* Compilation directives*/
#define DEBUG /* Enable debugging stuff*/
/* WDEF entry point */
pascal long main(varCode,theWindow,message,param)
short varCode; /* Variation code */
WindowPtr theWindow; /* Window pointer */
short message; /* Message command */
long param; /* Parameter control */
{
long status = 0L; /* Working status flag */
RememberA0(); /* Remember A0 global ptr*/
SetUpA4(); /* Setup register A4 */
#ifdef DEBUG /* Check if want debug */
/* Output debugging info */
DbgPrint(DbgGetRefHdl(),WDEF: message - %d\n,message);
#endif
switch(message) { /* Process message */
case wNew: /* Opening window */
break;
case wDispose: /* Closing window */
break;
case wDraw: /* Draw window frame */
DoDrawMsg(theWindow,param); break;
case wHit: /* Check mouse down hits */
status = DoHitMsg(theWindow,param); break;
case wCalcRgns: /* Calc window regions */
DoCalcMsg(theWindow); break;
case wGrow: /* Grow window */
DoGrowMsg(theWindow,param); break;
case wDrawGIcon: /* Draw window Grow Icon */
break;
}
RestoreA4(); /* Restore register A4 */
return(status); /* Return status flag */
}
DoDrawMsg(theWindow,param)
WindowPtr theWindow; /* Window pointer */
long param; /* Message parameter */
{
Rect wRect; /* Working window rect */
long wPat[2]; /* Working white pattern */
long bPat[2]; /* Working black pattern */
if (!param) { /* Check if want to frame*/
wPat[0] = wPat[1] = 0L; /* Init patterns */
bPat[0] = bPat[1] = 0xFFFFFFFFL;
/* Set window rect area */
wRect=(*((WindowPeek)(theWindow))->strucRgn)->rgnBBox;
PenNormal(); /* Reset pen states */
FrameOval(&wRect); /* Frame outer-most part */
InsetRect(&wRect,1,1); /* Frame between part */
PenPat(wPat);
FrameOval(&wRect);
InsetRect(&wRect,1,1); /* Frame middle part */
PenSize(3,3);
PenPat(bPat);
FrameOval(&wRect);
InsetRect(&wRect,3,3); /* Frame between part */
PenSize(1,1);
PenPat(wPat);
FrameOval(&wRect);
InsetRect(&wRect,1,1); /* Frame inter-most part */
PenSize(1,1);
PenPat(bPat);
FrameOval(&wRect);
InsetRect(&wRect,1,1); /* Frame between parts */
PenPat(wPat);
FrameOval(&wRect);
PenPat(bPat);
}
}
DoHitMsg(theWindow,pt)
WindowPtr theWindow; /* Window pointer */
Point pt; /* Mouse-down point */
{
register short status; /* Working status flag */
/* Check if point inside */
if (PtInRgn(pt,((WindowPeek)(theWindow))->contRgn))
status = wInContent; /* Yup, inside contents */
else /* Nope, outside contents*/
status = wNoHit; /* Set no hit indicator */
return(status); /* Return hit status flag*/
}
DoCalcMsg(theWindow)
WindowPtr theWindow; /* Window pointer */
{
Rect wRect; /* Working window rect */
wRect = theWindow->portRect;/* Set window rect area */
/* Normalize window rect */
OffsetRect(&wRect,-theWindow->portBits.bounds.left,
-theWindow->portBits.bounds.top);
/* Setup contents region*/
SetEmptyRgn(((WindowPeek)(theWindow))->contRgn);
OpenRgn();
FrameOval(&wRect);
CloseRgn(((WindowPeek)(theWindow))->contRgn);
/* Setup contents region*/
SetEmptyRgn(((WindowPeek)(theWindow))->strucRgn);
OpenRgn();
InsetRect(&wRect,-8,-8);
FrameOval(&wRect);
CloseRgn(((WindowPeek)(theWindow))->strucRgn);
}
DoGrowMsg(theWindow,theRect)
WindowPtr theWindow; /* Window pointer */
Rect *theRect; /* Rect area to grow */
{
FrameOval(theRect); /* Draw the frame area */
}