Thread View: mod.mac.sources
1 messages
1 total messages
Started by Paul DuBois
Wed, 26 Nov 1986 20:39
TransEdit.pit.Hqx [Human Readable Version]
Author: Paul DuBois
Date: Wed, 26 Nov 1986 20:39
Date: Wed, 26 Nov 1986 20:39
1936 lines
47842 bytes
47842 bytes
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# TransEdit/TransEdit.h
# TransEdit/TransEdit.c
# TransEdit/FakeAlert.c
#
# MODERATOR'S NOTE: Tab-width is 4
#
sed 's/^X//' << 'SHAR_EOF' > TransEdit/TransEdit.h
X/*
X TransEdit.h - TransEdit 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
XWindowPtr NewEWindow ();
XWindowPtr GetNewEWindow ();
XTEHandle GetEWindowTE ();
XBoolean GetEWindowFile ();
XBoolean IsEWindow ();
XBoolean IsEWindowDirty ();
XBoolean EWindowSave ();
XBoolean EWindowSaveAs ();
XBoolean EWindowSaveCopy ();
XBoolean EWindowClose ();
XBoolean EWindowRevert ();
XBoolean ClobberEWindows ();
Xint EWindowEditOp ();SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > TransEdit/TransEdit.c
X/*
X TransEdit.c version 1.0 - TransSkel plug-in module supporting an
X arbitrary number of generic edit windows. Each window may be
X bound to a file.
X
X *** Requires FakeAlert.c for proper linking! ***
X
X Shortcomings:
X Doesn't check for the obvious out of memory conditions.
X
X TransSkel and TransEdit 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 TransEdit 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.
X 11/04/86 Added conditional stuff to allow compilation in
X single- or multiple-window mode. Changed version to 1.0.
X*/
X
X
X/*
X The following symbol controls the compile mode. If it is #define'd,
X TransEdit allows only a single edit window, and generates less code.
X If it is #undef'ed, TransEdit allows an arbitrary number of edit
X windows, but generates more code.
X*/
X
X# undef singleEdit
X
X
X# include <ControlMgr.h> /* includes WindowMgr.h, QuickDraw.h, MacTypes.h */
X# include <StdFilePkg.h>
X# include <FileMgr.h>
X# include <ToolBoxUtil.h>
X# include "TransEdit.h"
X
X
X/*
X Edit window types, constants, variables.
X*/
X
X
X# define enter 3
X# define cr 13
X# define monaco 4
X# define shiftKey 0x0200
X
X
Xtypedef enum /* Edit menu item numbers */
X{
X undo = 1,
X /* --- */
X cut = 3,
X copy,
X paste,
X clear /* (it's ok if the host doesn't have this item) */
X};
X
X
X/*
X Default values for edit window text display characteristics
X and event notification procedures
X*/
X
Xstatic int e_font = monaco; /* default font */
Xstatic int e_size = 9; /* default pointsize */
Xstatic int e_wrap = 0; /* default word wrap (on) */
Xstatic int e_just = teJustLeft;/* default justification */
Xstatic ProcPtr e_key = nil; /* default key procedure */
Xstatic ProcPtr e_activate = nil; /* default activation procedure */
Xstatic ProcPtr e_close = nil; /* default close procedure */
X
X
X# ifndef singleEdit
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 ewList points to a list of structures describing the known edit
X windows.
X*/
X
X
Xtypedef struct EditInfo
X{
X WindowPtr editWind; /* the edit window */
X Boolean bound; /* whether window is bound to file */
X SFReply editFile; /* file it's bound to, if bound true */
X TEHandle editTE; /* window text */
X Boolean dirty; /* whether text modified since save */
X ControlHandle scroll; /* scroll bar */
X int visLines; /* # lines visible in window, max */
X ProcPtr eKey; /* key click notifier */
X ProcPtr eActivate; /* activate event notifier */
X ProcPtr eClose; /* close notifier */
X struct EditInfo **eNext; /* next information structure */
X} EditInfo, *EIPtr, **EIHandle;
X
X
Xstatic EIHandle ewList = nil;
X
X# endif
X
X
X/*
X Global variables - most of these are always synced to
X the current window. Note that not all these are set by
X SyncGlobals, since some are not often needed. When they
X are all needed, use SyncAllGlobals.
X*/
X
X# ifndef singleEdit
Xstatic EIHandle editInfo; /* window's info structure */
X# endif
X
Xstatic WindowPtr editWind = nil; /* the window */
Xstatic TEHandle editTE; /* window text */
Xstatic ControlHandle editScroll; /* the scroll bar */
Xstatic SFReply editFile; /* file information */
Xstatic int visLines; /* number of lines in window */
Xstatic Boolean bound; /* true if window bound to file */
Xstatic Boolean dirty; /* whether window is dirty */
Xstatic ProcPtr eKey; /* key click notifier */
Xstatic ProcPtr eActivate; /* activate event notifier */
Xstatic ProcPtr eClose; /* close notifier */
X
X
Xstatic int windID = 0;
Xstatic Point dlogWhere = { 70, 100 }; /* GetFile/PutFile location */
Xstatic OSType creator = 'TEDT'; /* default file creator */
X
Xstatic RgnHandle clipRgn;
X
X
X/* -------------------------------------------------------------------- */
X/* Miscellaneous Internal (private) Routines */
X/* -------------------------------------------------------------------- */
X
X
X/*
X Save and restore the current window's clip region
X*/
X
Xstatic SaveClipRgn ()
X{
X clipRgn = NewRgn ();
X GetClip (clipRgn);
X}
X
X
Xstatic RestoreClipRgn ()
X{
X SetClip (clipRgn);
X DisposeRgn (clipRgn);
X}
X
X
X/*
X Draw grow box in lower right hand corner of window.
X*/
X
X
Xstatic DrawGrowBox ()
X{
XRect r;
X
X SaveClipRgn ();
X r = editWind->portRect;
X r.left = r.right - 15; /* draw only in corner */
X r.top = r.bottom - 15;
X ClipRect (&r);
X DrawGrowIcon (editWind);
X RestoreClipRgn ();
X}
X
X
X/* -------------------------------------------------------------------- */
X/* Lowest-level Internal (Private) Edit Window Routines */
X/* -------------------------------------------------------------------- */
X
X
X# ifndef singleEdit
X
X/*
X Get edit window info associated with window.
X Return nil if window isn't a known edit window.
X*/
X
Xstatic EIHandle GetEInfo (theWind)
XWindowPtr theWind;
X{
Xregister EIHandle h;
X
X for (h = ewList; h != nil; h = (**h).eNext)
X {
X if ((**h).editWind == theWind)
X return (h);
X }
X return (nil);
X}
X
X# endif
X
X
X# ifdef singleEdit
X# define SyncAllGlobals SyncGlobals
X# endif
X
X
X/*
X Synchronize globals to an edit window and make it the
X current port. theWind must be a legal edit window, with one
X exception: if theWind is nil, the variables are synced to the
X port that's already current. That is safe (and correct) because:
X (i) nil is only passed by edit window handler procedures,
X which are only attached to edit windows
X (ii) TransSkel always sets the port to the window before
X calling the handler proc.
X Hence, using the current port under these circumstances always
X produces a legal edit window.
X*/
X
Xstatic SyncGlobals (theWind)
XWindowPtr theWind;
X{
X
X if (theWind == nil) /* use current window */
X GetPort (&theWind);
X
X SetPort (theWind);
X
X# ifndef singleEdit
X
X editWind = theWind;
X editInfo = GetEInfo (editWind);
X editTE = (**editInfo).editTE;
X editScroll = (**editInfo).scroll;
X visLines = (**editInfo).visLines;
X
X# endif
X
X}
X
X
X# ifndef singleEdit
X
Xstatic SyncAllGlobals (theWind)
XWindowPtr theWind;
X{
X
X SyncGlobals (theWind); /* sync display globals */
X editFile = (**editInfo).editFile; /* sync file, state, and */
X bound = (**editInfo).bound; /* procedure globals */
X dirty = (**editInfo).dirty;
X eKey = (**editInfo).eKey;
X eActivate = (**editInfo).eActivate;
X eClose = (**editInfo).eClose;
X}
X
X# endif
X
X
X/*
X Set dirty flag for current window
X*/
X
Xstatic SetDirty (boolVal)
XBoolean boolVal;
X{
X
X# ifdef singleEdit
X dirty = boolVal;
X# else
X (**editInfo).dirty = boolVal;
X# endif
X}
X
X
X/* -------------------------------------------------------------------- */
X/* Internal (private) Display Routines */
X/* -------------------------------------------------------------------- */
X
X
X/*
X Calculate the dimensions of the editing rectangle for
X editWind (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. If that's not
X done, funny things can happen to the caret.
X*/
X
Xstatic GetEditRect (r)
XRect *r;
X{
XFontInfo f;
Xregister int lineHeight;
X
X GetFontInfo (&f);
X lineHeight = f.ascent + f.descent + f.leading;
X *r = editWind->portRect;
X r->left += 4;
X r->right -= 17; /* leave room for scroll bar */
X r->top += 2;
X r->bottom = r->top + ((r->bottom - r->top - 2) / lineHeight) * lineHeight;
X}
X
X
X/*
X Set the edit rect properly.
X*/
X
Xstatic SetEditRect ()
X{
XRect r;
X
X GetEditRect (&r);
X (**editTE).destRect.right = r.right;
X (**editTE).viewRect = r;
X}
X
X
X
X/*
X Calculate the dimensions of the scroll bar rectangle for
X editWind (which must be set properly). Make sure that
X the edges overlap the window frame and the grow box.
X*/
X
Xstatic CalcScrollRect (r)
XRect *r;
X{
X *r = editWind->portRect;
X ++r->right;
X --r->top;
X r->left = r->right - 16;
X r->bottom -= 14;
X}
X
X
X/*
X Return true if the mouse is in the non-scrollbar part of the
X edit window.
X*/
X
Xstatic Boolean PtInText (pt)
XPoint pt;
X{
XRect r;
X
X r = editWind->portRect;
X r.right -= 15;
X return (PtInRect (pt, &r));
X}
X
X
X/*
X Set the cursor appropriately. If theCursor == iBeamCursor, check
X that it's really in the text area of an edit window (and if not
X set the cursor to an arrow instead). Otherwise, set the cursor
X to the given type (usually a watch).
X
X If the cursor is supposed to be set to an i-beam, it is assumed
X that the globals are synced, because DoCursor changes them and
X syncs them back.
X
X Pass -1 for theCursor to set the cursor to the arrow.
X*/
X
Xstatic DoCursor (theCursor)
Xint theCursor;
X{
XPoint pt;
XGrafPtr savePort;
X
X if (theCursor == iBeamCursor) /* check whether there's an edit */
X { /* window in front and if so, */
X theCursor = -1; /* whether the cursor's in its */
X if (IsEWindow (FrontWindow ())) /* text area */
X {
X GetPort (&savePort);
X SyncGlobals (FrontWindow ());
X GetMouse (&pt);
X if (PtInText (pt))
X theCursor = iBeamCursor;
X SyncGlobals (savePort);
X }
X }
X SetCursor (theCursor == -1 ? &arrow : *GetCursor (theCursor));
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 = *editTE;
X return (((*ePtr).viewRect.top - (*ePtr).destRect.top)
X / (*ePtr).lineHeight);
X}
X
X
X/*
X Return the line number that the caret (or the beginning of
X the currently selected text) is in. Value returned is in
X the range 0..(**editTE).nLines. If = (**editTE).nLines, the
X caret is past the last line. The only special case to watch out
X for is when the caret is at the very end of the text. If the
X last character is not a carriage return, then the caret is on
X the (nLines-1)th line, not the (nLines)th line.
X
X (This really should do a binary search for speed.)
X*/
X
Xstatic LineWithCaret ()
X{
Xregister int i;
Xregister int nLines;
Xregister int teLength;
Xregister int selStart;
Xregister int lineStart;
X
X selStart = (**editTE).selStart;
X nLines = (**editTE).nLines;
X teLength = (**editTE).teLength;
X
X if (selStart == teLength)
X {
X if (teLength != 0 && (*((**editTE).hText))[teLength-1] != cr)
X return (nLines - 1);
X return (nLines);
X }
X
X for (i = 0; /* empty */; ++i)
X {
X if ((lineStart = (**editTE).lineStarts[i]) >= selStart)
X {
X if (lineStart != selStart)
X --i;
X return (i);
X }
X }
X}
X
X
X/*
X Return the number of the last displayable line. That's one
X more than nLines if the text is empty or the last character
X is a carriage return.
X*/
X
Xstatic LastLine ()
X{
Xregister int nLines;
Xregister int teLength;
X
X nLines = (**editTE).nLines;
X teLength = (**editTE).teLength;
X
X if (teLength == 0 || (*((**editTE).hText))[teLength-1] == cr)
X nLines++;
X return (nLines);
X}
X
X
X/*
X Set the maximum value of the scroll bar. It's set so that if
X there's more text than fits in the window, the bottom line can
X be scrolled up at least a little below the bottom of the window.
X
X The shenanigans with topLines and scrollableLines have to do with
X the case where there may be less text than fills the window, but
X most of it's scrolled off the top. This can happen when you
X scroll a bunch of stuff up, then delete everything visible in
X the window.
X*/
X
Xstatic SetScrollMax ()
X{
Xregister int topLines;
Xregister int scrollableLines;
Xregister int max;
X
X topLines = LinesOffTop ();
X scrollableLines = LastLine () - visLines;
X max = (topLines > scrollableLines ? topLines : scrollableLines);
X
X if (max < 0)
X max = 0;
X
X if (max != GetCtlMax (editScroll))
X {
X SetCtlMax (editScroll, max);
X HiliteControl (editScroll, max > 0 ? 0 : 255);
X }
X}
X
X
X/*
X Set scroll bar current value (but only if it's different than
X the current value, to avoid needless flashing).
X*/
X
Xstatic SetScrollValue (value)
Xint value;
X{
X if (GetCtlValue (editScroll) != value)
X SetCtlValue (editScroll, value);
X}
X
X
X/*
X Scroll to the correct position. lDelta is the
X amount to CHANGE the current scroll setting by.
X*/
X
Xstatic ScrollText (lDelta)
Xint lDelta;
X{
Xregister int topVisLine;
Xregister int newTopVisLine;
X
X topVisLine = LinesOffTop ();
X newTopVisLine = topVisLine + lDelta;
X if (newTopVisLine < 0) /* clip to range */
X newTopVisLine = 0;
X if (newTopVisLine > GetCtlMax (editScroll))
X newTopVisLine = GetCtlMax (editScroll);
X SetScrollValue (newTopVisLine);
X TEScroll (0, (topVisLine-newTopVisLine )*(**editTE).lineHeight, editTE);
X}
X
X
X/*
X Scroll to home position without redrawing.
X*/
X
Xstatic ScrollToHome ()
X{
XRect r;
X
X r = (**editTE).destRect;
X OffsetRect (&r, 0, 2 - r.top);
X (**editTE).destRect = r;
X}
X
X/*
X ClikLoop proc for autoscrolling text when the mouse is dragged out
X of the text view rectangle.
X
X The clipping region has to be set to include the scroll bar,
X because whenever this proc is called, TE has the region set down
X to the view rectangle - if it's not reset, changes to the scroll
X bar will not show up!
X*/
X
Xstatic pascal Boolean AutoScroll ()
X{
XPoint p;
XRect r;
X
X SaveClipRgn ();
X ClipRect (&editWind->portRect);
X GetMouse (&p);
X r = (**editTE).viewRect;
X if (p.v < r.top)
X ScrollText (-1);
X else if (p.v > r.bottom)
X ScrollText (1);
X RestoreClipRgn ();
X return (true); /* true = 'keep tracking mouse' */
X}
X
X
X/*
X Filter proc for tracking mousedown in scroll bar. The code for
X the part originally hit is shoved into the control's reference
X value by Mouse() before this is called.
X
X I suspect odd scrolling may occur for hits in paging regions if
X the window is allowed to size such that less than two lines show.
X*/
X
Xstatic pascal void TrackScroll (theScroll, partCode)
XControlHandle theScroll;
Xint partCode;
X{
Xregister int lDelta;
X
X if (partCode == GetCRefCon (theScroll)) /* still in same part? */
X {
X switch (partCode)
X {
X case inUpButton: lDelta = -1; break;
X case inDownButton: lDelta = 1; break;
X case inPageUp: lDelta = -(visLines - 1); break;
X case inPageDown: lDelta = visLines - 1; break;
X }
X ScrollText (lDelta);
X }
X}
X
X
X/*
X Set the scroll bar properly and adjust the text in the
X window so that the line containing the caret is visible.
X If the line with the caret if more than a line outside of
X the viewRect, try to place it in the middle of the window.
X
X Yes, it is necessary to SetScrollMax at the end.
X*/
X
Xstatic AdjustDisplay ()
X{
Xregister int caretLine;
Xregister int topVisLine;
Xregister int d;
X
X SetScrollMax ();
X caretLine = LineWithCaret ();
X topVisLine = LinesOffTop ();
X if ((d = caretLine - topVisLine) < 0)
X ScrollText (d == -1 ? -1 : d - visLines / 2);
X else if (( d = caretLine - (topVisLine + visLines - 1)) > 0)
X ScrollText (d == 1 ? 1 : d + visLines / 2);
X else
X SetScrollValue (topVisLine);
X SetScrollMax (); /* might have changed from scrolling */
X}
X
X
X/*
X Overhaul the entire display. This is called for major
X catastrophes, such as resizing the window, or changes to
X 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 Doesn't redraw the control, though!
X*/
X
Xstatic OverhaulDisplay (showCaret, recalc)
XBoolean showCaret;
XBoolean recalc;
X{
XRect r;
X
X r = (**editTE).viewRect; /* erase current viewRect */
X EraseRect (&r);
X SetEditRect (); /* recalculate editing rects */
X if (recalc)
X TECalText (editTE); /* recalculate line starts */
X visLines = ((**editTE).viewRect.bottom - (**editTE).viewRect.top)
X / (**editTE).lineHeight;
X
X# ifndef singleEdit
X (**editInfo).visLines = visLines;
X# endif
X
X/*
X If there is text, but none of it is visible in the window
X (it's all scrolled off the top), pull some down.
X*/
X
X if (showCaret)
X AdjustDisplay ();
X else
X SetScrollMax ();
X r = (**editTE).viewRect;
X TEUpdate (&r, editTE);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Window Handler Routines */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Handle mouse clicks in window. The viewRect is never tested
X directly, because if it were, clicks along the top, left and
X bottom edges of the window wouldn't register.
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 (editScroll, thePt)) == inThumb)
X {
X oldCtlValue = GetCtlValue (editScroll);
X if (TrackControl (editScroll, thePt, nil) == inThumb)
X ScrollText (GetCtlValue (editScroll) - oldCtlValue);
X }
X else if (thePart != 0)
X {
X SetCRefCon (editScroll, (long) thePart);
X (void) TrackControl (editScroll, thePt, &TrackScroll);
X }
X else if (PtInText (thePt))
X {
X TEClick (thePt, (mods & shiftKey) != 0, editTE);
X }
X
X SetScrollMax ();
X}
X
X
X/*
X Handle key clicks in window
X*/
X
Xstatic Key (c, mods)
Xchar c;
Xint mods;
X{
X SyncAllGlobals (nil); /* sync to current port */
X
X if (c != enter)
X TEKey (c, editTE);
X AdjustDisplay ();
X SetDirty (true);
X if (eKey != nil) /* report event to the host */
X (*eKey) ();
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 in any case. Set the cursor (DoCursor avoids
X changing it from an ibeam to an arrow back to an ibeam, in the case
X where one edit window is going inactive and another is coming
X active).
X
X Report the event to the host.
X*/
X
Xstatic Activate (active)
XBoolean active;
X{
X SyncAllGlobals (nil); /* sync to current port */
X
X DrawGrowBox ();
X if (active)
X {
X TEActivate (editTE);
X HiliteControl (editScroll, GetCtlMax (editScroll) > 0 ? 0 : 255);
X }
X else
X {
X TEDeactivate (editTE);
X HiliteControl (editScroll, 255);
X }
X DoCursor (iBeamCursor);
X if (eActivate != nil) /* report event to the host */
X (*eActivate) (active);
X}
X
X
X/*
X Close box was clicked. If user specified notify proc, call it.
X Otherwise do default close operation (ask about saving if dirty,
X etc.).
X*/
X
Xstatic Close ()
X{
X SyncAllGlobals (nil); /* sync to current port */
X
X if (eClose != nil)
X (*eClose) ();
X else
X (void) EWindowClose (editWind);
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 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 gets redrawn below,
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
X r = editWind->portRect;
X EraseRect (&r);
X if (resized)
X {
X HideControl (editScroll);
X r = (**editScroll).contrlRect;
X ValidRect (&r);
X CalcScrollRect (&r);
X SizeControl (editScroll, 16, r.bottom - r.top);
X MoveControl (editScroll, r.left, r.top);
X OverhaulDisplay (false, (**editTE).crOnly >= 0);
X ShowControl (editScroll);
X }
X else
X {
X OverhaulDisplay (false, false);
X DrawControls (editWind); /* redraw scroll bar */
X }
X
X DrawGrowBox ();
X}
X
X
X/*
X Remove the edit window from the list, and dispose of it.
X This is called by SkelRmveWind, not directly by user program.
X
X At this point it's too late to back out if any changes have been
X made to the text.
X
X Since the clobber procedure is never called except for real edit
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
Xstatic Clobber ()
X{
X# ifndef singleEdit
Xregister EIHandle h, h2;
X# endif
X
X SyncGlobals (nil); /* sync to current port */
X
X# ifndef singleEdit
X
X if ((**ewList).editWind == editWind) /* is it the first window in list? */
X {
X h2 = ewList;
X ewList = (**ewList).eNext;
X }
X else
X {
X for (h = ewList; h != nil; h = h2)
X {
X h2 = (**h).eNext;
X if ((**h2).editWind == editWind) /* found it */
X {
X (**h).eNext = (**h2).eNext;
X break;
X }
X }
X }
X DisposHandle (h2); /* get rid of information structure */
X
X# endif
X
X TEDispose (editTE); /* toss text record */
X DisposeWindow (editWind); /* disposes of scroll bar, too */
X editWind = nil;
X DoCursor (iBeamCursor);
X}
X
X
X/*
X Blink the caret and make sure the cursor's an i-beam when it's
X in the non-scrollbar part of the window.
X*/
X
Xstatic Idle ()
X{
X
X SyncGlobals (nil);
X TEIdle (editTE); /* blink that caret! */
X DoCursor (iBeamCursor);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Internal File Routines */
X/* ---------------------------------------------------------------- */
X
X
Xstatic ErrMesg (s)
XStringPtr s;
X{
X (void) FakeAlert (s, "\p", "\p", "\p", 1, 1, "\pOK", "\p", "\p");
X}
X
X
X/*
X Save the contents of the edit window. If there is no file bound
X to the window, ask for a file name. If askForFile is true, ask
X for a name even if the window is currently bound to a file. If
X bindToFile is true, bind the window to the file written to (if
X that's different than the currently bound file), and clear the
X window's dirty flag.
X
X Return true if the file was written without error. Return false
X if (a) user was asked for name and clicked Cancel (b) there was
X some error writing the file. In the latter case, the window is
X not bound to any new name given by user.
X
X Always returns false if the window isn't an edit window. This
X simplifies EWindowSave, EWindowSaveAs, EWindowSaveCopy. (They
X don't do the test.)
X*/
X
Xstatic Boolean SaveFile (theWind, askForFile, bindToFile)
XWindowPtr theWind;
XBoolean askForFile;
XBoolean bindToFile;
X{
Xint f;
XFInfo fndrInfo; /* finder info */
XSFReply tmpFile;
XHandle hText;
Xlong count;
XOSErr result;
XBoolean haveNewFile = false;
X
X if (!IsEWindow (theWind))
X return (false);
X
X SyncAllGlobals (theWind);
X if (bound == false || askForFile)
X {
X SFPutFile (dlogWhere, "\pSave file as:", editFile.fName,
X nil, &tmpFile);
X if (!tmpFile.good)
X return (false);
X else
X {
X haveNewFile = true;
X if (GetFInfo (tmpFile.fName, tmpFile.vRefNum, &fndrInfo)
X == noErr) /* exists */
X {
X if (fndrInfo.fdType != 'TEXT')
X {
X ErrMesg ("\pNot a TEXT File");
X return (false);
X }
X }
X else /* doesn't exist. create it. */
X {
X if (Create (tmpFile.fName, tmpFile.vRefNum,
X creator, 'TEXT') != noErr)
X {
X ErrMesg ("\pCan't Create");
X return (false);
X }
X }
X }
X }
X
X if (FSOpen (tmpFile.fName, tmpFile.vRefNum, &f) != noErr)
X ErrMesg ("\pCan't Open");
X else
X {
X DoCursor (watchCursor);
X (void) SetFPos (f, fsFromStart, 0L);
X hText = (**editTE).hText;
X HLock (hText);
X count = (**editTE).teLength;
X result = FSWrite (f, &count, *hText);
X (void) GetFPos (f, &count);
X (void) SetEOF (f, count);
X (void) FSClose (f);
X (void) FlushVol (nil, tmpFile.vRefNum);
X HUnlock (hText);
X DoCursor (iBeamCursor);
X if (result == noErr)
X {
X if (bindToFile)
X {
X SetDirty (false);
X if (haveNewFile) /* name different than current */
X {
X SetWTitle (editWind, tmpFile.fName);
X
X# ifdef singleEdit
X bound = true;
X editFile = tmpFile;
X# else
X (**editInfo).bound = true;
X (**editInfo).editFile = tmpFile;
X# endif
X
X }
X }
X return (true);
X }
X ErrMesg ("\pWrite error!");
X }
X return (false);
X}
X
X
X/*
X Revert to version of file saved on disk. Doesn't check whether
X the window's really bound to a file or not, doesn't ask whether
X to really revert if the window's dirty, does no redrawing, etc.
X Just reports whether the file was read in successfully.
X*/
X
Xstatic Boolean Revert ()
X{
XBoolean result = false;
Xint f;
Xlong len;
XHandle h;
X
X DoCursor (watchCursor);
X if (FSOpen (editFile.fName, editFile.vRefNum, &f) != noErr)
X ErrMesg ("\pCouldn't open file");
X else
X {
X (void) GetEOF (f, &len);
X if (len >= 32000)
X ErrMesg ("\pFile is too big");
X else
X {
X h = TEGetText (editTE);
X SetHandleSize (h, len);
X HLock (h);
X (void) FSRead (f, &len, *h);
X HUnlock (h);
X (**editTE).teLength = len;
X TESetSelect (0L, 0L, editTE); /* set caret at start */
X result = true;
X SetDirty (false);
X }
X (void) FSClose (f);
X }
X DoCursor (iBeamCursor);
X return (result);
X}
X
X
X/* ------------------------------------------------------------ */
X/* Lowest-level Interface (Public) Routines */
X/* ------------------------------------------------------------ */
X
X
X/*
X Return true/false to indicate whether the window is really an
X edit window.
X*/
X
XBoolean IsEWindow (theWind)
XWindowPtr theWind;
X{
X# ifdef singleEdit
X return (theWind == editWind && editWind != nil);
X# else
X return (GetEInfo (theWind) != nil);
X# endif
X}
X
X
X/*
X Return true/false to indicate whether the text associated with
X the window has been changed since the last save/revert (or since
X created, if not bound to file).
X*/
X
XBoolean IsEWindowDirty (theWind)
XWindowPtr theWind;
X{
X# ifndef singleEdit
Xregister EIHandle eInfo;
X if ((eInfo = GetEInfo (theWind)) != nil)
X return ((**eInfo).dirty);
X# else
X if (IsEWindow (theWind))
X return (dirty);
X# endif
X return (false);
X}
X
X
X/*
X Return a handle to the TextEdit record associated with the edit
X window, or nil if it's not an edit window
X*/
X
XTEHandle GetEWindowTE (theWind)
XWindowPtr theWind;
X{
X# ifndef singleEdit
Xregister EIHandle eInfo;
X if ((eInfo = GetEInfo (theWind)) != nil)
X return ((**eInfo).editTE);
X# else
X if (IsEWindow (theWind))
X return (editTE);
X# endif
X return (nil);
X}
X
X
X/*
X Return true/false depending on whether the editor is bound to
X a file or not, and a copy of the file info in the second
X argument. Pass nil for fileInfo if only want the return status.
X Returns false if it's not an edit window.
X*/
X
XBoolean GetEWindowFile (theWind, fileInfo)
XWindowPtr theWind;
XSFReply *fileInfo;
X{
X# ifndef singleEdit
Xregister EIHandle eInfo;
X if ((eInfo = GetEInfo (theWind)) != nil)
X {
X if (fileInfo != nil)
X *fileInfo = (**eInfo).editFile;
X return ((**eInfo).bound);
X }
X# else
X if (IsEWindow (theWind))
X {
X if (fileInfo != nil)
X *fileInfo = editFile;
X return (bound);
X }
X# endif
X return (false);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Interface Display Routines */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Install event notification procedures for an edit window.
X*/
X
XSetEWindowProcs (theWind, pKey, pActivate, pClose)
XWindowPtr theWind;
XProcPtr pKey;
XProcPtr pActivate;
XProcPtr pClose;
X{
X# ifndef singleEdit
Xregister EIHandle eInfo;
X# endif
X
X if (theWind == nil) /* reset window creation defaults */
X {
X e_key = pKey;
X e_activate = pActivate;
X e_close = pClose;
X return;
X }
X
X# ifndef singleEdit
X
X if ((eInfo = GetEInfo (theWind)) != nil)
X {
X (**eInfo).eKey = pKey;
X (**eInfo).eActivate = pActivate;
X (**eInfo).eClose = pClose;
X }
X
X# else
X
X if (IsEWindow (theWind))
X {
X eKey = pKey;
X eActivate = pActivate;
X eClose = pClose;
X }
X
X# endif
X
X}
X
X
X/*
X Change the text display characteristics of an edit window
X and redisplay it.
X
X Scroll to home position before overhauling, because although
X the overhaul sets the viewRect to display an integral number
X of lines, there's no guarantee that the destRect offset will
X also be integral except at home position. Clipping is set to
X an empty rect so the scroll doesn't show.
X*/
X
XSetEWindowStyle (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;
Xint oldWrap;
X
X if (theWind == nil) /* reset window creation defaults */
X {
X e_font = font;
X e_size = size;
X e_wrap = wrap;
X e_just = just;
X return;
X }
X
X if (IsEWindow (theWind))
X {
X GetPort (&savePort);
X SyncGlobals (theWind); /* sync and set port */
X te = editTE;
X ScrollToHome ();
X
X oldWrap = (**te).crOnly;
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 */
X GetFontInfo (&f);
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 (true, (oldWrap >= 0 || wrap >= 0));
X
X SetPort (savePort);
X }
X}
X
X
X/*
X Redo display. Does not save current port. This is used by hosts
X that mess with the text externally to TransEdit. The arguments
X determine whether the text is scrolled to show the line with the
X caret, whether the lineStarts are recalculated, and whether the
X text should be marked dirty or not.
X*/
X
XEWindowOverhaul (theWind, showCaret, recalc, dirty)
XWindowPtr theWind;
XBoolean showCaret;
XBoolean recalc;
XBoolean dirty;
X{
X if (IsEWindow (theWind))
X {
X SyncGlobals (theWind);
X OverhaulDisplay (showCaret, recalc);
X DrawControls (editWind);
X SetDirty (dirty);
X }
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Menu Interface Routine */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Do Edit menu selection. This is only valid if an edit
X window is frontmost.
X*/
X
XEWindowEditOp (item)
Xint item;
X{
X
X if (!IsEWindow (FrontWindow ()))
X return; /* host messed up */
X
X SyncGlobals (FrontWindow ());
X
X switch (item)
X {
X
X/*
X cut selection, put in TE Scrap, clear clipboard and put
X TE scrap in it
X*/
X case cut:
X {
X TECut (editTE);
X (void) ZeroScrap ();
X (void) TEToScrap ();
X break;
X }
X/*
X copy selection to TE Scrap, clear clipboard and put
X TE scrap in it
X*/
X case copy:
X {
X TECopy (editTE);
X (void) ZeroScrap ();
X (void) TEToScrap ();
X break;
X }
X/*
X get clipboard into TE scrap, put TE scrap into edit record
X*/
X case paste:
X {
X (void) TEFromScrap ();
X TEPaste (editTE);
X break;
X }
X/*
X delete selection without putting into TE scrap or clipboard
X*/
X case clear:
X {
X (void) TEDelete (editTE);
X break;
X }
X
X }
X AdjustDisplay ();
X SetDirty (true);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Interface File Routines */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Set file creator for any files created by TransEdit
X*/
X
XSetEWindowCreator (creat)
XOSType creat;
X{
X creator = creat;
X}
X
X
X
X/*
X Save the contents of the given window
X*/
X
XBoolean EWindowSave (theWind)
XWindowPtr theWind;
X{
X return (SaveFile (theWind, /* window to save */
X false, /* don't ask for file if have one */
X true)); /* bind to new file if one given */
X}
X
X
X/*
X Save the contents of the given window under a new name
X and bind to that name.
X*/
X
XBoolean EWindowSaveAs (theWind)
XWindowPtr theWind;
X{
X return (SaveFile (theWind, /* window to save */
X true, /* ask for file even if have one */
X true)); /* bind to new file if one given */
X}
X
X
X/*
X Save the contents of the given window under a new name, but
X don't bind to the name.
X*/
X
XBoolean EWindowSaveCopy (theWind)
XWindowPtr theWind;
X{
X return (SaveFile (theWind, /* window to save */
X true, /* ask for file even if have one */
X false)); /* don't bind to file */
X}
X
X
X/*
X Close the window. If it's dirty and is either bound to a file
X or (if not bound) has some text in it, ask about saving it first,
X giving user option of saving changes, tossing them, or
X cancelling altogether.
X
X Return true if the file was saved and the window closed, false if
X user cancelled or there was an error.
X*/
X
XBoolean EWindowClose (theWind)
XWindowPtr theWind;
X{
X if (IsEWindow (theWind) == false)
X return (false);
X
X SyncAllGlobals (theWind);
X if ( (bound || (**editTE).teLength > 0) && dirty)
X {
X switch (FakeAlert ("\pSave changes to \"", editFile.fName,
X "\p\"?", "\p", 3, 3,
X "\pCancel", "\pDiscard", "\pSave")) /* ask whether to save */
X {
X
X case 1: /* cancel Close */
X return (false);
X
X case 2: /* toss changes */
X break;
X
X case 3:
X if (SaveFile (editWind, /* window to save */
X false, /* don't ask for name */
X false) /* don't bind to name */
X == false)
X return (false); /* cancelled or error - cancel Close */
X break;
X }
X }
X SkelRmveWind (editWind);
X return (true);
X}
X
X
X/*
X Revert to saved version of file on disk. theWind must be an edit
X window, and must be bound to a file. Returns false if one of these
X conditions is not met, or if they are met but there was an error
X reading the file.
X
X The window need not be dirty, but if it is, the user is asked
X whether to really revert.
X*/
X
XBoolean EWindowRevert (theWind)
XWindowPtr theWind;
X{
X if (!IsEWindow (theWind))
X return (false);
X SyncAllGlobals (theWind);
X if (!bound)
X return (false); /* no file to revert to */
X if (dirty)
X {
X if (FakeAlert ("\p\"", editFile.fName,
X "\p\" has been changed. Really revert?",
X "\p", 2, 1, "\pCancel", "\pRevert", "\p") == 1)
X return (false);
X }
X if (Revert () == false)
X return (false);
X ScrollToHome ();
X OverhaulDisplay (true, true);
X DrawControls (editWind);
X ValidRect (&editWind->portRect);
X return (true);
X}
X
X
X/* ---------------------------------------------------------------- */
X/* Interface Initialization/Termination Routines */
X/* ---------------------------------------------------------------- */
X
X
X/*
X Initialize the window and associated data structures.
X Return window pointer or nil if some sort of error.
X
X Preserves the current port.
X*/
X
XWindowPtr NewEWindow (bounds, title, visible, behind,
X goAway, refNum, bindToFile)
XRect *bounds;
XStringPtr title;
XBoolean visible;
XWindowPtr behind;
XBoolean goAway;
Xlong refNum;
XBoolean bindToFile;
X{
XGrafPtr savePort;
XRect r;
XOSType type = 'TEXT';
XStr255 s, s2;
XStringPtr tPtr;
X
X# ifndef singleEdit
Xregister EIHandle eInfo;
X# endif
X
X# ifdef singleEdit
X
X if (editWind != nil) /* allow only one window at a time */
X return (nil);
X
X# endif
X
X/*
X If supposed to bind to file, ask for name. Return without doing
X anything if Cancel button clicked.
X*/
X
X if (bindToFile)
X {
X SFGetFile (dlogWhere, "\p", nil, 1, &type, nil, &editFile);
X if (!editFile.good)
X return (nil);
X }
X bound = bindToFile;
X
X/*
X Create window and install handler. Set window title: If window is
X to be bound to file, use name of file. Otherwise use any title that
X was passed in. If nil was passed, use a default name ("Untitled nnn").
X Also copy the name into the file info structure even if the window is
X unbound, because the Save operations expect to find it there as the
X most likely name to use if the window is untitled.
X
X Save and restore port, because it gets reset by the rest of the
X initialization code.
X*/
X
X if (bound)
X tPtr = editFile.fName;
X else
X {
X if (title != nil)
X tPtr = title;
X else
X {
X
X# ifndef singleEdit
X BlockMove ("\pUntitled ", s, 10L);
X NumToString ((long) ++windID, s2);
X BlockMove (&s2[1], &s[10], (long) s2[0]);
X s[0] += s2[0];
X tPtr = s;
X# else
X tPtr = (StringPtr) "\pUntitled";
X# endif
X
X }
X BlockMove (tPtr, editFile.fName, (long) (tPtr[0] + 1));
X }
X
X editWind = NewWindow (nil, bounds, tPtr, false, documentProc,
X behind, goAway, refNum);
X
X GetPort (&savePort);
X SkelWindow (editWind, /* the window */
X Mouse, /* mouse click handler */
X Key, /* key click handler */
X Update, /* window updating procedure */
X Activate, /* window activate/deactivate procedure */
X Close, /* window close procedure */
X Clobber, /* window disposal procedure */
X Idle, /* idle proc */
X true); /* idle only when frontmost */
X
X
X/*
X Build the scroll bar.
X*/
X
X CalcScrollRect (&r);
X editScroll = NewControl (editWind, &r, "\p", true, 0, 0, 0,
X scrollBarProc, 0L);
X
X
X
X/*
X Create the TE record used for text display. Use default
X characteristics.
X*/
X
X GetEditRect (&r);
X editTE = TENew (&r, &r);
X SetClikLoop (AutoScroll, editTE); /* set autoscroll proc */
X
X
X# ifndef singleEdit
X
X/*
X Get new information structure, attach to list of known edit
X windows.
X*/
X
X eInfo = New (EditInfo);
X editInfo = eInfo;
X (**eInfo).eNext = ewList;
X ewList = eInfo;
X (**eInfo).editWind = editWind;
X (**eInfo).scroll = editScroll;
X (**eInfo).editTE = editTE;
X (**eInfo).bound = bound;
X (**eInfo).editFile = editFile;
X
X# endif
X
X/*
X Install default event notification procedures, font characteristics.
X*/
X
X SetEWindowProcs (editWind, e_key, e_activate, e_close);
X SetEWindowStyle (editWind, e_font, e_size, e_wrap, e_just);
X SetDirty (false);
X
X/*
X If supposed to read file, do so. Check the return value of
X Revert and toss the window if there was an error.
X*/
X
X if (bindToFile && Revert () == false)
X {
X SkelRmveWind (editWind);
X SetPort (savePort);
X return (nil);
X }
X
X/*
X Show window if specified as visible, and return a pointer to it.
X*/
X
X SyncGlobals (editWind);
X OverhaulDisplay (true, true);
X if (visible)
X ShowWindow (editWind);
X SetPort (savePort);
X return (editWind);
X}
X
X
X/*
X Look through the list of windows, shutting down all the edit
X windows. If any window is dirty, ask user about saving it first.
X If the user cancels on any such request, ClobberEWindows returns
X false. If all edit windows are shut down, return true. It is
X then safe for the host to exit.
X
X When a window *is* shut down, have to start looking through the
X window list again, since theWind no longer points anywhere
X meaningful.
X*/
X
XBoolean ClobberEWindows ()
X{
XWindowPtr theWind;
X
X for (;;)
X {
X for (theWind = FrontWindow ();
X theWind != nil;
X theWind = (WindowPtr) ((WindowPeek) theWind)->nextWindow)
X {
X if (IsEWindow (theWind))
X break;
X }
X if (theWind == nil)
X return (true); /* all edit windows are shut down */
X
X if (theWind != FrontWindow ())
X {
X SelectWindow (theWind);
X ShowWindow (theWind);
X EWindowOverhaul (theWind, false, false, IsEWindowDirty (theWind));
X SetPort (theWind);
X ValidRect (&theWind->portRect);
X }
X
X if (EWindowClose (theWind) == false)
X return (false); /* cancel or error */
X }
X}
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > TransEdit/FakeAlert.c
X# include <DialogMgr.h>
X
X
X# define nil (0L)
X
X
X/*
X In-memory item list for dialog with four items:
X
X 1 "^0^1^2^3" (static text)
X 2 Button 1
X 3 Button 2
X 4 Button 3
X
X The caller of FakeAlert passes the four strings that are to be
X substituted into the first item, the number of buttons that
X should be used, and the titles to put into each button.
X A copy of the item list is hacked to use the right number of
X buttons.
X
X Thanks to Erik Kilk and Jason Haines. Some of the stuff to do
X this is modified from code they wrote.
X*/
X
X
Xstatic int itemList [] =
X{
X 3, /* max number of items - 1 */
X
X/*
X statText item
X*/
X 0, 0, /* reserve a long for item handle */
X 10, 27, 61, 225, /* display rectangle */
X ((8+128) << 8) | 8, /* 8 + 128 = statText (disabled), title 8 bytes long */
X '^0', '^1', /* ^0^1^2^3 */
X '^2', '^3',
X
X/*
X first button
X*/
X
X 0, 0, /* reserve a long for item handle */
X 104, 140, 124, 210, /* display rectangle */
X (4 << 8) | 0, /* 4 = pushButton, title is 0 bytes long*/
X
X/*
X second button
X*/
X
X 0, 0, /* reserve a long for item handle */
X 104, 30, 124, 100, /* display rectangle */
X (4 << 8) | 0, /* 4 = pushButton, title is 0 bytes long */
X
X/*
X third button
X*/
X
X 0, 0, /* reserve a long for item handle */
X 72, 30, 92, 100, /* display rectangle */
X (4 << 8) | 0 /* 4 = pushButton, title is 0 bytes long */
X};
X
X
X/*
X Set dialog button title and draw bold outline if makeBold true.
X This must be done after the window is shown or else the bold
X outline won't show up (which is probably the wrong way to do it).
X*/
X
Xstatic SetDControl (theDialog, itemNo, title, makeBold)
XDialogPtr theDialog;
Xint itemNo;
XStringPtr title;
XBoolean makeBold;
X{
XHandle itemHandle;
Xint itemType;
XRect itemRect;
XPenState pState;
X
X GetDItem (theDialog, itemNo, &itemType, &itemHandle, &itemRect);
X SetCTitle (itemHandle, title);
X if (makeBold)
X {
X GetPenState (&pState);
X PenNormal ();
X PenSize (3, 3);
X InsetRect (&itemRect, -4, -4);
X FrameRoundRect (&itemRect, 16, 16);
X SetPenState (&pState);
X }
X}
X
X
X/*
X Fake an alert, using an in-memory window and item list.
X The message to be presented is constructed from the first
X four arguments. nButtons is the number of buttons to use,
X defButton is the default button, the next three args are
X the titles to put into the buttons. The return value is
X the button number (1..nButtons). This must be interpreted
X by the caller, since the buttons may be given arbitrary
X titles.
X
X nButtons should be between 1 and 3, inclusive.
X defButton should be between 1 and nButtons, inclusive.
X*/
X
X
XFakeAlert (s1, s2, s3, s4, nButtons, defButton, t1, t2, t3)
XStringPtr s1, s2, s3, s4;
Xint nButtons;
Xint defButton;
XStringPtr t1, t2, t3;
X{
XGrafPtr savePort;
Xregister DialogPtr theDialog;
Xregister Handle iListHandle;
XRect bounds;
Xint itemHit;
X
X InitCursor ();
X GetPort (&savePort);
X iListHandle = NewHandle (512L);
X HLock (iListHandle);
X BlockMove (&itemList, *iListHandle, 512L);
X ((int *) *iListHandle)[0] = nButtons; /* = number items - 1 */
X SetRect (&bounds, 115, 80, 355, 220);
X theDialog = NewDialog (nil, &bounds, "\p", false, dBoxProc, -1L,
X false, 0L, iListHandle);
X
X ParamText (s1, s2, s3, s4); /* construct message */
X
X SetPort (theDialog);
X ShowWindow (theDialog);
X
X switch (nButtons) /* set button titles */
X {
X case 3:
X SetDControl (theDialog, 4, t3, defButton == 3);
X /* fall through... */
X case 2:
X SetDControl (theDialog, 3, t2, defButton == 2);
X /* fall through... */
X case 1:
X SetDControl (theDialog, 2, t1, defButton == 1);
X }
X
X/*
X ModalDialog returns 1 if return/enter hit, which, since
X the statText item is first, can be unambiguously
X interpreted as "choose default".
X*/
X ModalDialog (nil, &itemHit);
X itemHit = (itemHit == 1 ? defButton : itemHit - 1);
X HUnlock (iListHandle);
X /*HPurge (iListHandle);*/
X DisposDialog (theDialog);
X SetPort (savePort);
X return (itemHit);
X}
SHAR_EOF
exit
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads