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