dubois@uwmacc.UUCP (Paul DuBois) (11/25/86)
#!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # TransDisplay/TransDisplay.c # TransDisplay/TransDisplay.h # # MODERATOR'S NOTE: Tab-width is 4 # sed 's/^X//' << 'SHAR_EOF' > TransDisplay/TransDisplay.c X/* X TransDisplay version 1.0 - TransSkel plug-in module supporting X an arbitrary number of generic display windows with memory. X X TransSkel and TransDisplay are public domain, and are written by: X X Paul DuBois X Wisconsin Regional Primate Research Center X 1220 Capital Court X Madison WI 53706 USA X X UUCP: {allegra,ihnp4,seismo}!uwvax!uwmacc!dubois X ARPA: dubois@unix.macc.wisc.edu X dubois@rhesus.primate.wisc.edu X X This version of TransDisplay written for LightspeedC. LightspeedC X is a trademark of: X THINK Technologies, Inc X 420 Bedford Street Suite 350 X Lexington, MA 02173 USA X X History X 08/25/86 Genesis. Beta version. X 09/15/86 Changed to allow arbitrary number of windows. Changed X version number to 1.0. X*/ X X X/* X The following symbol controls the compile mode. If it is #define'd, X TransDisplay allows only a single display window, and generates X less code. If it is #undef'ed, TransDisplay allows an arbitrary X number of display windows, but generates more code. X*/ X X# undef singleDisplay X X# include <ControlMgr.h> /* includes WindowMgr.h, QuickDraw.h, MacTypes.h */ X# include <TextEdit.h> X# include "TransDisplay.h" X X X/* X Display window types, constants, variables. X*/ X X X# define monaco 4 X X X/* X Default values for display window characteristics X*/ X Xstatic int d_font = monaco; /* default font */ Xstatic int d_size = 9; /* default pointsize */ Xstatic int d_wrap = 0; /* default word wrap (on) */ Xstatic int d_just = teJustLeft; /* default justification */ Xstatic long d_maxText = 30000L; /* default max text allowed */ Xstatic long d_flushAmt = 25000L; /* default autoflush amount */ Xstatic ProcPtr d_activate = nil; /* default notification proc */ X X X/* X Lowest allowable values for autoflush characteristics X*/ X X# define d_loMaxText (100L) X# define d_loFlushAmt (100L) X X X# ifndef singleDisplay X X/* X New(TypeName) returns handle to new object, for any TypeName. X If there is insufficient memory, the result is nil. X*/ X X# define New(x) (x **) NewHandle ((Size) sizeof (x)) X X X/* X dwList points to a list of structures describing the known display X windows. X X curDispWind is the current output window. X If curDispWind = nil, output is currently turned off. X*/ X X Xtypedef struct DisplayInfo X{ X WindowPtr dWind; /* display window */ X TEHandle dTE; /* window text */ X ControlHandle dScroll; /* window scroll bar */ X ProcPtr dActivate; /* notification procedure */ X long dMaxText; /* max text length */ X long dFlushAmt; /* amount to autoflush */ X struct DisplayInfo **dNext; /* next window structure */ X} DisplayInfo, *DIPtr, **DIHandle; X X Xstatic DIHandle dwList = nil; X X# endif X X/* X Variables pertaining to the display window being operated on X (updated, resized, etc.). This window is not necessarily the X same as curDispWind! These variables are synced to the window X with SyncGlobals. X*/ X X# ifndef singleDisplay Xstatic DIHandle dispInfo; /* info structure */ X# endif X Xstatic WindowPtr dispWind = nil; /* the window */ Xstatic TEHandle dispTE; /* window text */ Xstatic ControlHandle dispScroll; /* the scroll bar */ Xstatic ProcPtr dActivate; /* notification procedure */ Xstatic long dMaxText; /* max text allowed */ Xstatic long dFlushAmt; /* amount to flush */ X X X/* X curDispWind is the current output window. X If curDispWind = nil, output is turned off. X*/ X Xstatic WindowPtr curDispWind = nil; X X X/* -------------------------------------------------------------------- */ X/* Miscellaneous Internal (private) Routines */ X/* -------------------------------------------------------------------- */ X X X/* X Draw grow box of dispWind in lower right hand corner X*/ X X Xstatic DrawGrowBox () X{ Xregister RgnHandle oldClip; XRect r; X X r = dispWind->portRect; X r.left = r.right - 15; /* draw only in corner */ X r.top = r.bottom - 15; X oldClip = NewRgn (); X GetClip (oldClip); X ClipRect (&r); X DrawGrowIcon (dispWind); X SetClip (oldClip); X DisposeRgn (oldClip); X} X X X X/* -------------------------------------------------------------------- */ X/* Lowest-level Internal (Private) Display Window Routines */ X/* -------------------------------------------------------------------- */ X X X# ifndef singleDisplay X X/* X Get display window info associated with window. X Return nil if window isn't a known display window. X*/ X Xstatic DIHandle GetDInfo (theWind) XWindowPtr theWind; X{ Xregister DIHandle h; X X for (h = dwList; h != nil; h = (**h).dNext) X { X if ((**h).dWind == theWind) X return (h); X } X return (nil); X} X X# endif X X# ifdef singleDisplay X# define SyncGlobals(x) ; /* make it a nop */ X# else X X/* X Synchronize globals to a display window. theWind must be a legal X display window, with one exception: if theWind is nil, the X variables are synced to the current port. That is safe (and X correct) because: X (i) nil is only passed by display window handler procedures, X which are only called by TransSkel for display window X events. X (ii) TransSkel always sets the port to the window before X calling the handler proc. X Hence, use of the current port under these circumstances X always produces a legal display window. X X SyncGlobals is not used in single display mode, because the X globals are all set by SetupDWindow and do not change thereafter. X*/ X Xstatic SyncGlobals (theWind) XWindowPtr theWind; X{ Xregister DIPtr dp; X X if (theWind == nil) /* use current window */ X GetPort (&theWind); X X dispWind = theWind; X dispInfo = GetDInfo (dispWind); X dp = *dispInfo; X dispScroll = (*dp).dScroll; X dispTE = (*dp).dTE; X dActivate = (*dp).dActivate; X dMaxText = (*dp).dMaxText; X dFlushAmt = (*dp).dFlushAmt; X} X X# endif X X X/* X Calculate the dimensions of the editing rectangle for X dispWind (which must be set properly and is assumed to be X the current port). (The viewRect and destRect are the X same size.) Assumes the port, text font and text size are all X set properly. The viewRect is sized so that an integral X number of lines can be displayed in it, i.e., so that a X partial line never shows at the bottom. X*/ X Xstatic CalcEditRect (r) XRect *r; X{ XFontInfo f; Xregister int lineHeight; X X GetFontInfo (&f); X lineHeight = f.ascent + f.descent + f.leading; X *r = dispWind->portRect; X r->left += 4; X r->right -= 17; /* leave room for scroll bar + 2 */ X r->top += 2; X r->bottom = r->top + ((r->bottom - r->top - 2) / lineHeight) * lineHeight; X} X X X/* X Calculate the dimensions of the scroll bar rectangle for the X window. Make sure that the edges overlap the window frame and X the grow box. X*/ X Xstatic CalcScrollRect (r) XRect *r; X{ X *r = dispWind->portRect; X ++r->right; X --r->top; X r->left = r->right - 16; X r->bottom -= 14; X} X X X/* X Calculate the number of lines currently scrolled off X the top. X*/ X Xstatic LinesOffTop () X{ Xregister TEPtr ePtr; X X ePtr = *dispTE; X return (((*ePtr).viewRect.top - (*ePtr).destRect.top) X / (*ePtr).lineHeight); X} X X X/* X Highlight the scroll bar properly. This means that it's not X made active if the window itself isn't active, even if X there's enough text to fill the window. X*/ X Xstatic HiliteScroll () X{ X HiliteControl (dispScroll, dispWind == FrontWindow () && X GetCtlMax (dispScroll) > 0 ? 0 : 255); X} X X X/* X Scroll to the correct position. lDelta is the X amount to CHANGE the current scroll setting by. X Positive scrolls the text up, negative down. X*/ X Xstatic ScrollText (lDelta) Xint lDelta; X{ Xregister int lHeight; Xregister int newLine; Xregister int topLine; X X lHeight = (**dispTE).lineHeight; X topLine = LinesOffTop (); X newLine = topLine + lDelta; X if (newLine < 0) X newLine = 0; X if (newLine > GetCtlMax (dispScroll)) X newLine = GetCtlMax (dispScroll); X SetCtlValue (dispScroll, newLine); X TEScroll (0, (topLine - newLine ) * lHeight, dispTE); X} X X X/* X Filter proc for tracking mousedown in scroll bar. The code for X the part originally hit is stored in the control's reference X value by Mouse () before calling this. X X Scroll by one line if the mouse is in an arrow. Scroll by a half X window's worth of lines if the mouse is in a page region. X*/ X Xstatic pascal void TrackScroll (theScroll, partCode) XControlHandle theScroll; Xint partCode; X{ Xregister int lDelta; Xregister int halfPage; X X if (partCode == GetCRefCon (theScroll)) /* still in same part? */ X { X halfPage = (((**dispTE).viewRect.bottom - (**dispTE).viewRect.top) X / (**dispTE).lineHeight) / 2; X if (halfPage == 0) X ++halfPage; X switch (partCode) X { X case inUpButton: lDelta = -1; break; X case inDownButton: lDelta = 1; break; X case inPageUp: lDelta = -halfPage; break; X case inPageDown: lDelta = halfPage; break; X } X ScrollText (lDelta); X } X} X X X/* X Adjust the text in the text record and the scroll bar. This is X called for major catastrophes, such as resizing the window, or X changing the word wrap style. It makes sure the view and X destination rectangles are sized properly, and that the bottom X line of text never scrolls up past the bottom line of the X window, if there's enough to fill the window, and that the X scroll bar max and current values are set properly. X X Resizing the dest rect just means resetting the right edge X (the top is NOT reset), since text might be scrolled off the X top (i.e., destRect.top != 0). X*/ X Xstatic OverhaulDisplay () X{ XRect r; Xregister int nLines; /* number of lines in TERec */ Xregister int visLines; /* number of lines displayable in window */ Xregister int topLines; /* number of lines currently scrolled off top */ Xregister int scrollLines; /* number of lines to scroll down */ Xregister int lHeight; X X CalcEditRect (&r); X (**dispTE).destRect.right = r.right; X (**dispTE).viewRect = r; X TECalText (dispTE); /* recalc line starts */ X /*r = (**dispTE).viewRect;*/ /* ?? */ X lHeight = (**dispTE).lineHeight; X nLines = (**dispTE).nLines; X visLines = (r.bottom - r.top) / lHeight; X topLines = LinesOffTop (); X X/* X If the text doesn't fill the window (visLines > nLines - topLines), X pull the text down if possible (if topLines > 0). Make sure not X to try to scroll down by more lines than are hidden off the top. X*/ X scrollLines = visLines - (nLines - topLines); X if (scrollLines > 0 && topLines > 0) X { X if (scrollLines > topLines) X scrollLines = topLines; X TEScroll (0, scrollLines * lHeight, dispTE); X topLines -= scrollLines; X } X TEUpdate (&r, dispTE); X X SetCtlMax (dispScroll, nLines - visLines < 0 ? 0 : nLines - visLines); X SetCtlValue (dispScroll, topLines); X HiliteScroll (); X} X X X/* ---------------------------------------------------------------- */ X/* Window Handler Routines */ X/* ---------------------------------------------------------------- */ X X X/* X When the window comes active, highlight the scroll bar appropriately. X When the window is deactivated, un-highlight the scroll bar. X Redraw the grow box. X X Notify the host as appropriate. X X Note that clicking close box hides the window, which generates a X deactivate event, so there is no need for a close notifier. X*/ X Xstatic Activate (isActive) XBoolean isActive; X{ X SyncGlobals (nil); /* sync to current port */ X DrawGrowBox (); X HiliteScroll (); X X if (dActivate != nil) X (*dActivate) (isActive); X} X X X/* X Update window. The update event might be in response to a X window resizing. If so, move and resize the scroll bar, X and recalculate the text display. X X The ValidRect call is done because the HideControl adds the X control bounds box to the update region - which would generate X another update event! Since everything is redrawn below anyway, X the ValidRect is used to cancel the update. X*/ X Xstatic Update (resized) XBoolean resized; X{ XRect r; X X SyncGlobals (nil); /* sync to current port */ X r = dispWind->portRect; X EraseRect (&r); X if (resized) X { X HideControl (dispScroll); X r = (**dispScroll).contrlRect; X ValidRect (&r); X CalcScrollRect (&r); X SizeControl (dispScroll, 16, r.bottom - r.top); X MoveControl (dispScroll, r.left, r.top); X OverhaulDisplay (); X ShowControl (dispScroll); X } X else X { X r = (**dispTE).viewRect; X TEUpdate (&r, dispTE); /* redraw text display */ X } X X DrawGrowBox (); X DrawControls (dispWind); /* redraw scroll bar */ X} X X X/* X Handle mouse clicks in window X*/ X Xstatic Mouse (thePt, t, mods) XPoint thePt; Xlong t; Xint mods; X{ Xregister int thePart; Xregister int oldCtlValue; X X SyncGlobals (nil); /* sync to current port */ X X if ((thePart = TestControl (dispScroll, thePt)) == inThumb) X { X oldCtlValue = GetCtlValue (dispScroll); X if (TrackControl (dispScroll, thePt, nil) == inThumb) X ScrollText (GetCtlValue (dispScroll) - oldCtlValue); X } X else if (thePart != 0) X { X SetCRefCon (dispScroll, (long) thePart); X (void) TrackControl (dispScroll, thePt, &TrackScroll); X } X} X X X X/* X Remove the display window from the list, and dispose of it. X Since the clobber procedure is never called except for real display X windows, and since the list must therefore be non-empty, it is X not necessary to check the legality of the window or that the X window's in the list. X X Must do SetDWindow (nil) to turn output off, if the window being X clobbered is the current output window. X*/ X Xstatic Clobber () X{ X# ifndef singleDisplay Xregister DIHandle h, h2; X# endif X X SyncGlobals (nil); /* sync to current port */ X X if (dispWind == curDispWind) X SetDWindow (nil); X X# ifndef singleDisplay X X if ((**dwList).dWind == dispWind) /* is it the first window in list? */ X { X h2 = dwList; X dwList = (**dwList).dNext; X } X else X { X for (h = dwList; h != nil; h = h2) X { X h2 = (**h).dNext; X if ((**h2).dWind == dispWind) /* found it */ X { X (**h).dNext = (**h2).dNext; X break; X } X } X } X DisposHandle (h2); /* get rid of information structure */ X X# endif X X TEDispose (dispTE); /* toss text record */ X DisposeWindow (dispWind); /* toss window and scroll bar */ X dispWind = nil; X} X X X/* ---------------------------------------------------------------- */ X/* Control Routines */ X/* ---------------------------------------------------------------- */ X X X/* X Test whether a window is a legal display window or not X*/ X XBoolean IsDWindow (theWind) XWindowPtr theWind; X{ X X# ifdef singleDisplay X return (theWind == dispWind && dispWind != nil); X# else X return (GetDInfo (theWind) != nil); X# endif X} X X X/* X Return handle to display window's text record X*/ X XTEHandle GetDWindowTE (theWind) XWindowPtr theWind; X{ X X# ifndef singleDisplay Xregister DIHandle dInfo; X return (GetDInfo (theWind) == nil ? nil : (**dInfo).dTE); X# else X return (IsDWindow (theWind) ? dispTE : nil); X# endif X} X X X/* X Change the text display characteristics of a display window X and redisplay it. As a side effect, this always scrolls to the X home position. X*/ X XSetDWindowStyle (theWind, font, size, wrap, just) XWindowPtr theWind; Xint font; Xint size; Xint wrap; Xint just; X{ XGrafPtr savePort; XFontInfo f; Xregister TEHandle te; XRect r; X X if (theWind == nil) /* reset window creation defaults */ X { X d_font = font; X d_size = size; X d_wrap = wrap; X d_just = just; X return; X } X X if (IsDWindow (theWind)) X { X GetPort (&savePort); X SyncGlobals (theWind); X SetPort (dispWind); X te = dispTE; X r = (**te).viewRect; X EraseRect (&r); X r = (**te).destRect; /* scroll home without redrawing */ X OffsetRect (&r, 0, 2 - r.top); X (**te).destRect = r; X X (**te).crOnly = wrap; /* set word wrap */ X TESetJust (just, te); /* set justification */ X X TextFont (font); /* set the font and point size */ X TextSize (size); /* of text record (this is the */ X GetFontInfo (&f); /* hard part) */ X (**te).lineHeight = f.ascent + f.descent + f.leading; X (**te).fontAscent = f.ascent; X (**te).txFont = font; X (**te).txSize = size; X X OverhaulDisplay (); X SetPort (savePort); X } X} X X X/* X Scroll the text in the window so that line lineNum is at the top. X First line is line zero. X*/ X XSetDWindowPos (theWind, lineNum) XWindowPtr theWind; Xint lineNum; X{ XGrafPtr savePort; X X if (IsDWindow (theWind)) X { X GetPort (&savePort); X SyncGlobals (theWind); X SetPort (dispWind); X ScrollText (lineNum - GetCtlValue (dispScroll)); X SetPort (savePort); X } X} X X X/* X Set display window activate notification procedure. X Pass nil to disable it. X*/ X XSetDWindowNotify (theWind, p) XWindowPtr theWind; XProcPtr p; X{ X# ifndef singleDisplay Xregister DIHandle dInfo; X# endif X X if (theWind == nil) /* reset window creation default */ X { X d_activate = p; X return; X } X X# ifdef singleDisplay X X if (IsDWindow (theWind)) X dActivate = p; X X# else X X if ((dInfo = GetDInfo (theWind)) != nil) X { X (**dInfo).dActivate = p; X } X X# endif X} X X X/* X Set display window autoflush characteristics X*/ X XSetDWindowFlush (theWind, maxText, flushAmt) XWindowPtr theWind; Xlong maxText; Xlong flushAmt; X{ X# ifndef singleDisplay Xregister DIHandle dInfo; X# endif X X if (maxText > 32767L) X maxText = 32767L; X if (maxText < d_loMaxText) X maxText = d_loMaxText; X if (flushAmt < d_loFlushAmt) X flushAmt = d_loFlushAmt; X X if (theWind == nil) /* reset window creation defaults */ X { X d_maxText = maxText; X d_flushAmt = flushAmt; X return; X } X X# ifdef singleDisplay X X if (IsDWindow (theWind)) X { X X dMaxText = maxText; X dFlushAmt = flushAmt; X } X X# else X X if ((dInfo = GetDInfo (theWind)) != nil) X { X (**dInfo).dMaxText = maxText; X (**dInfo).dFlushAmt = flushAmt; X } X X# endif X} X X X/* X Set which display window is to be used for output. If theWind X is nil, output is turned off. If theWind is not a legal display X window, nothing is done. X*/ X XSetDWindow (theWind) XWindowPtr theWind; X{ X if (theWind == nil || IsDWindow (theWind)) X { X curDispWind = theWind; X } X} X X X/* X Get the WindowPtr of the current output display window. If X output is turned off, this will be nil. X*/ X XGetDWindow (theWind) XWindowPtr *theWind; X{ X *theWind = curDispWind; X} X X X/* X Flush text from the window and readjust the display. X*/ X XFlushDWindow (theWind, byteCount) XWindowPtr theWind; Xlong byteCount; X{ X if (IsDWindow (theWind)) X { X SyncGlobals (theWind); X TESetSelect (0L, byteCount, dispTE); /* select text */ X TEDelete (dispTE); /* clobber it */ X OverhaulDisplay (); X } X} X X X/* X Create and initialize a display window and the associated data X structures, and return the window pointer. Install window in X list of display windows. X*/ X Xstatic SetupDWindow () X{ XRect r; XGrafPtr savePort; X X# ifndef singleDisplay Xregister DIHandle dInfo; X# endif X X X GetPort (&savePort); X SkelWindow (dispWind, /* the window */ X Mouse, /* mouse click handler */ X nil, /* key clicks are ignored */ X Update, /* window updating procedure */ X Activate, /* window activate/deactivate procedure */ X nil, /* TransSkel hides window if no close proc */ X /* (generates deactivate event) */ X Clobber, /* window disposal procedure */ X nil, /* no idle proc */ X false); /* irrelevant since no idle proc */ X X/* X Build the scroll bar. Make sure the borders overlap the X window frame and the frame of the grow box. X*/ X X CalcScrollRect (&r); X dispScroll = NewControl (dispWind, &r, "\p", true, 0, 0, 0, X scrollBarProc, 0L); X X/* X Create the TE record used for text display. Use defaults for X display characteristics. Setting window style overhauls X display, so can cancel and update event pending for the window. X*/ X X CalcEditRect (&r); X dispTE = TENew (&r, &r); X X# ifndef singleDisplay X X/* X Get new information structure, attach to list of known display X windows. X*/ X dInfo = New (DisplayInfo); X (**dInfo).dNext = dwList; X dwList = dInfo; X (**dInfo).dWind = dispWind; X (**dInfo).dScroll = dispScroll; X (**dInfo).dTE = dispTE; X X# endif X X SetDWindowNotify (dispWind, d_activate); X SetDWindowFlush (dispWind, d_maxText, d_flushAmt); X SetDWindowStyle (dispWind, d_font, d_size, d_wrap, d_just); X X/* X Make window current display output window X*/ X X SetDWindow (dispWind); X SetPort (savePort); X} X X X/* X Create and initialize a display window and the associated data X structures, and return the window pointer. Install window in X list of display windows. In single-window mode, disallow X creation of a new window if one already exists. X X The parameters are similar to those for NewWindow. See Inside X Macintosh. X*/ X XWindowPtr NewDWindow (bounds, title, visible, behind, goAway, refCon) XRect *bounds; XStringPtr title; XBoolean visible; XWindowPtr behind; XBoolean goAway; Xlong refCon; X{ X X# ifdef singleDisplay X X if (dispWind != nil) X return (nil); X X# endif X X dispWind = NewWindow (nil, bounds, title, visible, X documentProc, behind, goAway, refCon); X SetupDWindow (); X return (dispWind); X} X X X/* X Create and initialize a display window (using a resource) and X the associated data structures, and return the window pointer. X Install window in list of display windows. In single-window X mode, disallow creation of a new window if one already exists. X X The parameters are similar to those for GetNewWindow. See Inside X Macintosh. X*/ X XWindowPtr GetNewDWindow (resourceNum, behind) Xint resourceNum; XWindowPtr behind; X{ X X# ifdef singleDisplay X X if (dispWind != nil) X return (nil); X X# endif X X dispWind = GetNewWindow (resourceNum, nil, behind); X SetupDWindow (); X return (dispWind); X} X X X X X/* ------------------------------------------------------------ */ X/* Output Routines */ X/* ------------------------------------------------------------ */ X X X/* X Write text to display area if output is on (curDispWind != nil). X DisplayText is the fundamental output routine. All other X output calls map (eventually) to it. X X First check whether the insertion will cause overflow and flush X out some stuff if so. Insert new text at the end, then test X whether lines must be scrolled to get the new stuff to show up. X If yes, then do the scroll. Set values of scroll bar properly X and highlight as appropriate. X X The current port is preserved. Since all output calls end up X here, it's the only output routine that has to save the port X and check whether output is on. X*/ X XDisplayText (theText, len) XPtr theText; Xlong len; X{ Xregister int nLines; /* number of lines in TERec */ Xregister int dispLines; /* number of lines displayable in window */ Xregister int topLines; /* number of lines currently scrolled off top */ Xregister int scrollLines; /* number of lines to scroll up */ Xregister int lHeight; XRect r; XGrafPtr savePort; Xregister TEHandle dTE; X X if (curDispWind == nil) X return; X X GetPort (&savePort); X SetPort (curDispWind); X SyncGlobals (curDispWind); X dTE = dispTE; X X if ((**dTE).teLength + len > dMaxText) /* check overflow */ X { X FlushDWindow (dispWind, dFlushAmt); X DisplayString ("\p\r(autoflush occurred)\r"); X } X X lHeight = (**dTE).lineHeight; X TESetSelect (32767L, 32767L, dTE); /* set to insert at end */ X TEInsert (theText, len, dTE); X r = (**dTE).viewRect; X nLines = (**dTE).nLines; X dispLines = (r.bottom - r.top) / lHeight; X topLines = LinesOffTop (); X scrollLines = nLines - (topLines + dispLines); X if (scrollLines > 0) /* must scroll up */ X TEScroll (0, -lHeight * scrollLines, dTE); /* scroll up */ X topLines = nLines - dispLines; X if (topLines >= 0 && GetCtlMax (dispScroll) != topLines) X { X SetCtlMax (dispScroll, topLines); X SetCtlValue (dispScroll, topLines); X } X HiliteScroll (); X SetPort (savePort); X} X X X/* X Derived output routines: X X DisplayString Write (Pascal) string X X DisplayLong Write value of long integer X DisplayInt Write value of integer X DisplayChar Write character X X DisplayHexLong Write value of long integer in hex (8 digits) X DisplayHexInt Write value of integer in hex (4 digits) X DisplayHexChar Write value of character in hex (2 digit) X X DisplayBoolean Write boolean value X DisplayLn Write carriage return X*/ X XDisplayString (theStr) XStringPtr theStr; X{ X DisplayText (theStr+1, (long) theStr[0]); X} X X XDisplayLong (l) Xlong l; X{ XStr255 s; X X NumToString (l, s); X DisplayString (s); X} X X XDisplayInt (i) Xint i; X{ X DisplayLong ((long) i); X} X X XDisplayChar (c) Xchar c; X{ X DisplayText (&c, 1L); X} X X XDisplayLn () X{ X DisplayChar ('\r'); X} X X XDisplayBoolean (b) XBoolean b; X{ X DisplayString (b ? "\ptrue" : "\pfalse"); X} X X Xstatic HexByte (value) /* should be 0..15 */ Xint value; X{ X DisplayChar ((char) (value + (value < 10 ? '0' : 'a' - 10))); X} X X XDisplayHexChar (c) Xchar c; X{ X HexByte ((int) (c >> 4) & 0x0f); X HexByte ((int) c & 0x0f); X} X X XDisplayHexInt (i) Xint i; X{ X DisplayHexChar ((char) ((i >> 8) & 0xff)); X DisplayHexChar ((char) (i & 0xff)); X} X X XDisplayHexLong (l) Xlong l; X{ X DisplayHexInt ((int) (l >> 16) & 0xffff); X DisplayHexInt ((int) l & 0xffff); X} SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > TransDisplay/TransDisplay.h X/* X TransDisplay.h - TransDisplay header file X*/ X X# ifndef _WindowMgr_ X# include "WindowMgr.h" X# endif X X# ifndef _TextEdit_ X# include "TextEdit.h" X# endif X X X# ifndef nil X# define nil (0L) X# endif X X X/* X Functions returning non-int values X*/ X XWindowPtr NewDWindow (); XWindowPtr GetNewDWindow (); XBoolean IsDWindow (); XTEHandle GetDWindowTE (); SHAR_EOF exit