dubois@uwmacc.UUCP (Paul DuBois) (12/01/86)
#!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # TSDemos/MiniSkel.c # TSDemos/Skel.c # TSDemos/MultiSkel.h # TSDemos/MultiSkel.c # TSDemos/MSkelEdit.c # TSDemos/MSkelHelp.c # TSDemos/MSkelRgn.c # TSDemos/MSkelZoom.c # TSDemos/ManyWind.c # TSDemos/DialogSkel.c # # MODERATOR'S NOTE: Tab-width is 4 # sed 's/^X//' << 'SHAR_EOF' > TSDemos/MiniSkel.c X/* X TransSkel demonstration: Minimal application X X This program does nothing but put up an Apple menu with desk X accessories, and a File menu with a Quit item. The user can X run DA's until Quit is selected or command-Q is typed. X X The project should include this file, TransSkel.c (or a project X built from TransSkel.c), and MacTraps. X X 27 June 1986 Paul DuBois X*/ X X# include <MenuMgr.h> X# define nil 0L X X XDoFileMenu (item) Xint item; /* ignored - there's only Quit */ X{ X SkelWhoa (); /* tell SkelMain to quit */ X} X X Xmain () X{ XMenuHandle m; X X SkelInit (); /* initialize */ X SkelApple (nil, nil); /* handle desk accessories */ X m = NewMenu (2, "\pFile"); /* create menu */ X AppendMenu (m, "\pQuit/Q"); X SkelMenu (m, DoFileMenu, nil); /* tell TransSkel to handle it */ X SkelMain (); /* loop 'til Quit selected */ X SkelClobber (); /* clean up */ X} SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > TSDemos/Skel.c X/* X TransSkel demonstration: Traditional Skel X X This program mimics the original Skel application: one sizable, X dragable, non-closable dark gray window, an "About" alert and two X dialogs. Desk accessories supported. X X The project should include this file, TransSkel.c (or a project X built from TransSkel.c), and MacTraps. X X 27 June 1986 Paul DuBois X*/ X X# include <DialogMgr.h> /* includes WindowMgr, QuickDraw, etc. */ X# include <MenuMgr.h> X# include <ToolboxUtil.h> X X# define nil 0L X X/* X Resource numbers X*/ X X# define fileMenuRes 2 /* File menu */ X# define aboutAlrt 1000 /* About box */ X# define theWindRes 260 /* window */ X# define reportDlog 257 /* message dialog box */ X# define aboutStr 1 /* message strings */ X# define rattleStr 2 X# define frightStr 3 X X X X/* file menu item numbers */ X Xtypedef enum { X rattle = 1, X frighten, X /* --- */ X quit = 4 X} fileItems; X X XWindowPtr theWind; X X/* X Menu handles. There isn't any apple menu here, since TransSkel will X be told to handle it itself. X*/ X XMenuHandle fileMenu; X X X/* -------------------------------------------------------------------- */ X/* Menu handling procedures */ X/* -------------------------------------------------------------------- */ X X X/* X Read a string resource and put into the Alert/Dialog paramtext X values X*/ X XSetParamText (strNum) Xint strNum; X{ XStringHandle h; X X h = GetString (strNum); X HLock (h); X ParamText (*h, "\p", "\p", "\p"); X HUnlock (h); X} X X X/* X Handle selection of "About SkelI" item from Apple menu X*/ X XDoAbout () X{ XStringHandle h; X X SetParamText (aboutStr); X (void) Alert (aboutAlrt, nil); X} X X X/* X Put up a dialog box with a message and an OK button. The message X is stored in the 'STR ' resource whose number is passed as strNum. X*/ X XReport (strNum) Xint strNum; X{ XDialogPtr theDialog; Xint itemHit; X X SetParamText (strNum); X theDialog = GetNewDialog (reportDlog, nil, -1L); X ModalDialog (nil, &itemHit); X DisposDialog (theDialog); X} X X X/* X Process selection from File menu. X X Rattle, Frighten A dialog box with message X Quit Request a halt by calling SkelHalt(). This makes SkelMain X return. X*/ X XDoFileMenu (item) Xint item; X{ X X switch (item) X { X case rattle: Report (rattleStr); break; X case frighten: Report (frightStr); break; X case quit: SkelWhoa (); break; /* request halt */ X } X} X X X/* X Initialize menus. Tell TransSkel to process the Apple menu X automatically, and associate the proper procedures with the X File and Edit menus. X*/ X XSetUpMenus () X{ X X SkelApple ("\pAbout SkelI", DoAbout); X fileMenu = GetMenu (fileMenuRes); X SkelMenu (fileMenu, DoFileMenu, nil); X} X X X/* -------------------------------------------------------------------- */ X/* Window handling procedures */ X/* -------------------------------------------------------------------- */ X X XWindActivate (active) XBoolean active; X{ X X DrawGrowIcon (theWind); /* make grow box reflect new window state */ X} X X X/* X On update event, can ignore the resizing information, since the whole X window is always redrawn in terms of the current size, anyway. X Content area is dark gray except scroll bar areas, which are white. X Draw grow box as well. X*/ X XWindUpdate (resized) XBoolean resized; X{ XRect r; X X r = theWind->portRect; /* paint window dark gray */ X r.bottom -= 15; /* don't bother painting the */ X r.right -= 15; /* scroll bar areas */ X FillRect (&r, dkGray); X r = theWind->portRect; /* paint scroll bar areas white */ X r.left = r.right - 15; X FillRect (&r, white); X r = theWind->portRect; X r.top = r.bottom - 15; X FillRect (&r, white); X DrawGrowIcon (theWind); X} X X XWindHalt () { CloseWindow (theWind); } X X X/* X Read window from resource file and install handler for it. Mouse X and key clicks are ignored. There is no close proc since the window X doesn't have a close box. There is no idle proc since nothing is X done while the window is in front (all the things that are done are X handled by TransSkel). X*/ X XWindInit () X{ X X theWind = GetNewWindow (theWindRes, nil, -1L); X SetPort (theWind); X SkelWindow (theWind, nil, nil, WindUpdate, WindActivate, nil, X WindHalt, nil, false); X} X X X/* -------------------------------------------------------------------- */ X/* Main */ X/* -------------------------------------------------------------------- */ X X Xmain () X{ X X SkelInit (); /* initialize */ X SetUpMenus (); /* install menu handlers */ X WindInit(); /* install window handler */ X SkelMain (); /* loop 'til Quit selected */ X SkelClobber (); /* clean up */ X} SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > TSDemos/MultiSkel.h X/* X TransSkel multiple-window demonstration: Header file. X X #includes standard header files used by all demo modules, #defines X demo resource numbers and some values used many places, such as nil. X X 14 June 1986 Paul DuBois X*/ X X X# include <WindowMgr.h> /* pulls in MacTypes, QuickDraw */ X# include <MenuMgr.h> X X/* from Event Manager */ X# define shiftKey 0x0200 X X# define nil 0L X X X/* X resource numbers X*/ X X# define aboutAlrt 1000 X# define getInfoDlog 1001 X X# define fileMenuRes 1001 X# define editMenuRes 1002 X X# define helpWindRes 1000 X# define editWindRes 1001 X# define zoomWindRes 1002 X# define rgnWindRes 1003 X X# define helpTextRes 1000 X X Xextern MenuHandle editMenu; X Xextern WindowPtr helpWind; Xextern WindowPtr editWind; Xextern WindowPtr zoomWind; Xextern WindowPtr rgnWind; SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > TSDemos/MultiSkel.c X/* X TransSkel multiple-window demonstration: main module X X This module performs setup and termination operations, installs X the window and menu handlers, and processes menu item selections. X X There are four window handlers in this demonstration. The code X for each handler is in its own module. X X Help Window Scrollable non-editable text window X Edit Window Non-scrollable editable text window X Zoom Window Non-manipulable graphics display window X Region Window Manipulable graphics display window X X The project should include MacTraps, TransSkel.c (or a project built X from TransSkel.c), MSkelHelp.c, MSkelEdit.c, MSkelZoom.c and X MSkelRgn.c. You'll also need the MultiSkel.h header file. X X 24 June 1986 Paul DuBois X*/ X X# include "MultiSkel.h" X X X/* file menu item numbers */ X Xtypedef enum { X open = 1, X close, X /* --- */ X quit = 4 X} fileItems; X X X/* X Menu handles. There isn't any apple menu here, since TransSkel will X be told to handle it itself. X*/ X XMenuHandle fileMenu; XMenuHandle editMenu; X XRgnHandle oldClip; X X Xmain () X X{ X SkelInit (); X SetUpMenus (); /* install menu handlers */ X RgnWindInit (); /* install window handlers */ X ZoomWindInit (); X EditWindInit (); X HelpWindInit (); X SkelMain (); X SkelClobber (); /* throw away windows and menus */ X} X X X/* X Initialize menus. Tell Skel to process the Apple menu automatically, X and associate the proper procedures with the File and Edit menus. X*/ X XSetUpMenus () X{ Xint DoAbout(), DoFile(), DoEdit(); X X SkelApple ("\pAbout MultiSkelI", &DoAbout); X fileMenu = GetMenu (fileMenuRes); X editMenu = GetMenu (editMenuRes); X SkelMenu (fileMenu, &DoFile, nil); X SkelMenu (editMenu, &DoEdit, nil); X} X X X/* X Handle selection of About MultiSkelI item from Apple menu X*/ X XDoAbout () X{ X (void) Alert (aboutAlrt, nil); X} X X X/* X Process selection from File menu. X X Open Make all four windows visible X Close Hide the frontmost window. If it belongs to a desk accessory, X close the accessory. X Quit Request a halt by calling SkelHalt(). This makes SkelMain X return. X*/ X XDoFile (item) Xint item; X{ XWindowPeek wPeek; X X switch (item) X { X case open: X { X MyShowWindow ((WindowPeek) rgnWind); X MyShowWindow ((WindowPeek) zoomWind); X MyShowWindow ((WindowPeek) editWind); X MyShowWindow ((WindowPeek) helpWind); X break; X } X/* X Close the front window. Take into account whether it belongs X to a desk accessory or not. X*/ X case close: X { X if ((wPeek = (WindowPeek) FrontWindow ()) != nil) X { X if (wPeek->windowKind < 0) X CloseDeskAcc (wPeek->windowKind); X else X HideWindow (FrontWindow ()); X } X break; X } X case quit: X { X SkelWhoa (); /* request halt */ X break; X } X } X} X X X/* X Show a window if it's not visible. Select the window FIRST, then X show it, so that it comes up in front. Otherwise it will be drawn X in back then brought to the front, which is ugly. X X The test for visibility must be done carefully: the window manager X stores 255 and 0 for true and false, not real boolean values. X*/ X XMyShowWindow (wind) XWindowPeek wind; X{ X X if (wind->visible == 0) X { X SelectWindow (wind); X ShowWindow (wind); X } X} X X X/* X Process item selected from Edit menu. First check whether it should X get routed to a desk accessory or not. If not, then for route the X selection to the text editing window, as that is the only one for X this application to which edit commands are valid. X (The test of FrontWindow is not strictly necessary, as the Edit X menu is disabled when any of the other windows is frontmost, and so X this Proc couldn't be called.) X*/ X XDoEdit (item) Xint item; X{ X if (!SystemEdit (item - 1)) /* check DA edit choice */ X { X if (FrontWindow () == editWind) X EditWindEditMenu (item); X } X} X X X/* X Miscellaneous routines X These take care of drawing the grow box and the line along X the right edge of the window, and of setting and resetting the clip X region to disallow drawing in that right edge by the other drawing X routines. X*/ X X XDrawGrowBox (wind) XWindowPtr wind; X X{ XRect r; XRgnHandle oldClip; X X r = wind->portRect; X r.left = r.right - 15; /* draw only along right edge */ X oldClip = NewRgn (); X GetClip (oldClip); X ClipRect (&r); X DrawGrowIcon (wind); X SetClip (oldClip); X DisposeRgn (oldClip); X} X X XSetWindClip (wind) XWindowPtr wind; X X{ XRect r; X X r = wind->portRect; X r.right -= 15; /* don't draw along right edge */ X oldClip = NewRgn (); X GetClip (oldClip); X ClipRect (&r); X} X X XResetWindClip () X{ X SetClip (oldClip); X DisposeRgn (oldClip); X} SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > TSDemos/MSkelEdit.c X/* X TransSkel multiple-window demonstration: TextEdit module X X This module handles a simple TextEdit window, in which text may be X typed and standard Cut/Copy/Paste/Clear operations may be performed. X Undo is not supported, nor is text scrolling. X X 14 June 1986 Paul DuBois X*/ X X# include "MultiSkel.h" X# include <TextEdit.h> X X X/* edit menu item numbers */ X Xtypedef enum { X undo = 1, X /* --- */ X cut = 3, X copy, X paste, X clear X} editItems; X X X X/* X Text Window - simple text editing window X*/ X XWindowPtr editWind; Xstatic TEHandle teEdit; /* handle to text window TextEdit record */ X X Xstatic Halt () X{ X TEDispose (teEdit); X CloseWindow (editWind); X} X X Xstatic Idle () X{ X TEIdle (teEdit); /* blink that cursor! */ X} X X Xstatic Key (ch, mods) Xchar ch; Xint mods; X{ X TEKey (ch, teEdit); X} X X Xstatic Mouse (thePt, t, mods) XPoint thePt; Xlong t; Xint mods; X{ X TEClick (thePt, (mods & shiftKey) != 0, teEdit); X} X X X/* X Update text window. The update event might be in response to a X window resizing. If so, resize the rects and recalc the linestarts X of the text. To resize the rects, only the right edge of the X destRect need be changed (the bottom is not used, and the left and X top should not be changed). The viewRect should be sized to the X screen. X*/ X Xstatic Update (resized) XBoolean resized; X{ XRect r; X X r = editWind->portRect; X EraseRect (&r); X r.left += 4; X r.bottom -= 2; X r.top += 2; X r.right -= 19; X if (resized) X { X (**teEdit).destRect.right = r.right; X (**teEdit).viewRect = r; X TECalText (teEdit); X } X DrawGrowBox (editWind); X TEUpdate (&r, teEdit); X} X X Xstatic Activate (active) XBoolean active; X{ X DrawGrowBox (editWind); X if (active) X { X TEActivate (teEdit); X DisableItem (editMenu, undo); X } X else X { X TEDeactivate (teEdit); X EnableItem (editMenu, undo); X } X} X X X/* X Handle Edit menu items for text window X*/ X XEditWindEditMenu (item) Xint item; X{ X switch (item) 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 (teEdit); 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 (teEdit); 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 (teEdit); X break; X } X/* X delete selection without putting into TE scrap or clipboard X*/ X case clear: X { X (void) TEDelete (teEdit); X break; X } X } X} X X XEditWindInit () X{ XRect r; XStringPtr str; X X editWind = GetNewWindow (editWindRes, nil, -1L); X SkelWindow (editWind, Mouse, Key, Update, X Activate, nil, Halt, Idle, true); X X TextFont (0); X TextSize (0); X X r = editWind->portRect; X r.left += 4; X r.bottom -= 2; X r.top += 2; X r.right -= 19; X teEdit = TENew (&r, &r); X str = (StringPtr) "\pThis is the text editing window.\r"; X TEInsert (&str[1], (long) str[0], teEdit); X} SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > TSDemos/MSkelHelp.c X/* X TransSkel multiple-window demonstration: Help module X X This module handles a help window, in which text may be scrolled but X not edited. A TextEdit record is used to hold the text, though. X X 14 June 1986 Paul DuBois X*/ X X# include "MultiSkel.h" X# include <ControlMgr.h> X# include <TextEdit.h> X X X X XWindowPtr helpWind; Xstatic TEHandle teHelp; /* handle to help window TextEdit record */ Xstatic ControlHandle helpScroll; /* help window scroll bar */ Xstatic int helpLine; /* line currently at top of window */ Xstatic int halfPage; /* number of lines in half a window */ X X Xstatic Halt () X{ X TEDispose (teHelp); X DisposeControl (helpScroll); X CloseWindow (helpWind); X} X X X/* X Scroll to the correct position. lDelta is the X amount to CHANGE the current scroll setting by. X*/ X XDoScroll (lDelta) Xint lDelta; X{ Xint newLine; X X newLine = helpLine + lDelta; X if (newLine < 0) X newLine = 0; X if (newLine > GetCtlMax (helpScroll)) X newLine = GetCtlMax (helpScroll); X SetCtlValue (helpScroll, newLine); X lDelta = (helpLine - newLine ) * (**teHelp).lineHeight; X TEScroll (0, lDelta, teHelp); X helpLine = newLine; X} X X X/* X Filter proc for tracking mousedown in scroll bar. The part code X of the part originally hit is stored as the control's reference X value. X X The "void" had better be there! Otherwise Lightspeed will treat X it as an integer function, not a procedure. X*/ X Xpascal void TrackScroll (theScroll, partCode) XControlHandle theScroll; Xint partCode; X{ Xint 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 = -halfPage; break; X case inPageDown: lDelta = halfPage; break; X } X DoScroll (lDelta); X } X} X X X/* X Handle hits in scroll bar X*/ X Xstatic Mouse (thePt, t, mods) XPoint thePt; Xlong t; Xint mods; X{ Xint thePart; X X if ((thePart = TestControl (helpScroll, thePt)) == inThumb) X { X (void) TrackControl (helpScroll, thePt, nil); X DoScroll (GetCtlValue (helpScroll) - helpLine); X } X else if (thePart != 0) X { X SetCRefCon (helpScroll, (long) thePart); X (void) TrackControl (helpScroll, thePt, &TrackScroll); X } X} X X X/* X Update help window. The update event might be in response to a X window resizing. If so, resize the rects and recalc the linestarts X of the text. To resize the rects, only the right edge of the X destRect need be changed (the bottom is not used, and the left and X top should not be changed). The viewRect should be sized to the X screen. Pull text down if necessary to fill window. X*/ X Xstatic Update (resized) XBoolean resized; X{ XRect r; Xint visLines; Xint lHeight; Xint topLines; Xint nLines; Xint scrollLines; X X r = helpWind->portRect; X EraseRect (&r); X if (resized) X { X r.left += 4; X r.bottom -= 2; X r.top += 2; X r.right -= 19; X (**teHelp).destRect.right = r.right; X (**teHelp).viewRect = r; X TECalText (teHelp); X lHeight = (**teHelp).lineHeight; X nLines = (**teHelp).nLines; X visLines = (r.bottom - r.top) / lHeight; X halfPage = visLines / 2; X topLines = (r.top - (**teHelp).destRect.top) / lHeight; X scrollLines = visLines - (nLines - topLines); X if (scrollLines > 0 && topLines > 0) X { X if (scrollLines > topLines) X scrollLines = topLines; X TEScroll (0, scrollLines * lHeight, teHelp); X } X scrollLines = nLines - visLines; X helpLine = (r.top - (**teHelp).destRect.top) / lHeight; X/* X move and resize the scroll bar as well. The ValidRect call is done X because the HideControl adds the control bounds box to the update X region - which would generate another update event! Since everything X gets redrawn below, the ValidRect is used to cancel the update. X*/ X X HideControl (helpScroll); X r = helpWind->portRect; X r.left = r.right - 15; X r.bottom -= 14; X --r.top; X ++r.right; X SizeControl (helpScroll, r.right - r.left, r.bottom - r.top); X MoveControl (helpScroll, r.left, r.top); X SetCtlMax (helpScroll, nLines - visLines < 0 ? 0 : nLines - visLines); X SetCtlValue (helpScroll, helpLine); X /*if (scrollLines <= 0) X HiliteControl (helpScroll, (scrollLines > 0 ? 0 : 255));*/ X ShowControl (helpScroll); X /*if (GetCtlValue (helpScroll) > scrollLines) X DoScroll (GetCtlValue (helpScroll) - scrollLines);*/ X } X DrawGrowBox (helpWind); X DrawControls (helpWind); /* redraw scroll bar */ X r = (**teHelp).viewRect; X TEUpdate (&r, teHelp); /* redraw text display */ X ValidRect (&helpWind->portRect); X} X X X/* X When the window comes active, disable the Edit menu and highlight X the scroll bar if there are any lines not visible in the content X region. When the window is deactivated, enable the Edit menu and X un-highlight the scroll bar. X*/ X Xstatic Activate (active) XBoolean active; X{ X DrawGrowBox (helpWind); X if (active) X { X DisableItem (editMenu, 0); X HiliteControl (helpScroll, (GetCtlMax (helpScroll) > 0 ? 0 : 255)); X } X else X { X EnableItem (editMenu, 0); X HiliteControl (helpScroll, 255); X } X DrawMenuBar (); X} X X XHelpWindInit () X{ XRect r; XHandle textHandle; Xint visLines; Xint scrollLines; X X helpWind = GetNewWindow (helpWindRes, nil, -1L); X SkelWindow (helpWind, Mouse, nil, Update, X Activate, nil, Halt, nil, true); X X TextFont (0); X TextSize (0); X X r = helpWind->portRect; X r.left += 4; X r.bottom -= 2; X r.top += 2; X r.right -= 19; X teHelp = TENew (&r, &r); X textHandle = GetResource ('TEXT', helpTextRes); /* read help text */ X HLock (textHandle); /* lock it and insert into TERec */ X TEInsert (*textHandle, GetHandleSize (textHandle), teHelp); X HUnlock (textHandle); X ReleaseResource (textHandle); /* done with it, so goodbye */ X/* X Now figure out how many lines will fit in the window and how many X will not. Determine the number of lines in half a window for use X in tracking clicks in the page up and page down regions of the X scroll bar. Then create the scroll bar . Make sure the borders X overlap the window frame and the frame of the grow box. X*/ X visLines = (r.bottom - r.top) / (**teHelp).lineHeight; X scrollLines = (**teHelp).nLines - visLines; X halfPage = visLines / 2; X helpLine = 0; X r = helpWind->portRect; X r.left = r.right - 15; X r.bottom -= 14; X --r.top; X ++r.right; X/* X Build the scroll bar. Don't need to bother testing whether to X highlight it or not, since that will be done in response to the X activate event. X*/ X helpScroll = NewControl (helpWind, &r, "\p", true, X helpLine, 0, scrollLines, scrollBarProc, 0L); X X/* X GetNewWindow generates an update event for entire portRect. X Cancel it, since the everything has been drawn already, X except for the grow box (which will be drawn in response X to the activate event). X*/ X ValidRect (&helpWind->portRect); X} SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > TSDemos/MSkelRgn.c X/* X TransSkel multiple-window demonstration: Region module X X This module handles a window in which the mouse may be clicked and X dragged to draw rectangles. The rects so drawn are combined into X a single region, the outline of which is drawn. Rects drawn while X the shift key is held down are subtracted from the region. X Double-clicking the mouse clears the display. If the window is X resized, the region that is drawn is resized as well. X X 14 June 1986 Paul DuBois X X Changes: X 07/08/86 Changed outline so that it's drawn as a marquee. X*/ X X# include "MultiSkel.h" X X XWindowPtr rgnWind; XRect rgnPortRect; /* portRect size - for detecting wind grows */ XRgnHandle selectRgn; /* current region to be drawn */ Xlong selectWhen; /* time of last click */ XPoint selectWhere; /* location of last click */ X XPattern marqueePat = { 0x0f, 0x87, 0xc3, 0xe1, 0xf0, 0x78, 0x3c, 0x1e }; X X Xstatic Clobber () X{ X DisposeRgn (selectRgn); X CloseWindow (rgnWind); X} X X X/* X On double-click, clear window. On single click, draw gray selection X rectangle as long as mouse is held down. If user draws non-empty rect, X then add it to the selection region and redraw the region's outline. X If the shift-key was down, then subtract the selection region instead X and redraw. X*/ X X Xstatic Mouse (thePt, t, mods) XPoint thePt; Xlong t; Xint mods; X X{ XRect r; XRgnHandle rgn; X X r = rgnWind->portRect; X if (thePt.h >= r.right - 15) /* must not click in right edge */ X return; X if (t - selectWhen <= GetDblTime ()) /* it's a double-click */ X { X selectWhen = 0L; /* don't take next click as dbl-click */ X SetWindClip (rgnWind); X EraseRgn (selectRgn); X ResetWindClip (); X SetEmptyRgn (selectRgn); /* clear region */ X } X else X { X selectWhen = t; /* update click variables */ X selectWhere = thePt; X DoSelectRect (thePt, &r); /* draw selection rectangle */ X if (!EmptyRect (&r)) X { X EraseRgn (selectRgn); X selectWhen = 0L; X rgn = NewRgn (); X RectRgn (rgn, &r); X if ((mods & shiftKey) != 0) /* test shift key */ X DiffRgn (selectRgn, rgn, selectRgn); X else X UnionRgn (selectRgn, rgn, selectRgn); X DisposeRgn (rgn); X } X } X} X X X/* X Redraw the current region. If the window was resized, resize X the region to fit. X*/ X Xstatic Update (resized) XBoolean resized; X{ XRect r; X X EraseRect (&rgnWind->portRect); X if (resized) X { X r = rgnWind->portRect; X rgnPortRect.right -= 15; /* don't use right edge of window */ X r.right -= 15; X MapRgn (selectRgn, &rgnPortRect, &r); X rgnPortRect = rgnWind->portRect; X } X DrawGrowBox (rgnWind); X Idle (); X} X X Xstatic Activate (active) XBoolean active; X{ X DrawGrowBox (rgnWind); X if (active) X DisableItem (editMenu, 0); X else X EnableItem (editMenu, 0); X DrawMenuBar (); X} X X XMarqueeRgn (r) XRgnHandle r; X{ XPenState p; XByte b; Xint i; X X GetPenState (&p); X PenPat (marqueePat); X PenMode (patCopy); X FrameRgn (r); X SetPenState (&p); X b = marqueePat[0]; /* shift pattern for next call */ X for (i = 0; i < 7; ++i) X marqueePat[i] = marqueePat[i+1]; X marqueePat[7] = b; X} X X Xstatic Idle () X{ Xint i; X X SetWindClip (rgnWind); X MarqueeRgn (selectRgn); /* draw selection region outline */ X ResetWindClip (); /* restore previous clipping */ X} X X/* X While mouse is down, draw gray selection rectangle in the current X port. Return the resultant rect in dstRect. The rect is always X clipped to the current portRect. X*/ X XDoSelectRect (startPoint, dstRect) XPoint startPoint; XRect *dstRect; X{ XPoint pt, dragPt; XRect rClip; XGrafPtr thePort; XBoolean result; XPenState ps; Xint i; X X GetPort (&thePort); X rClip = thePort->portRect; X rClip.right -= 15; X GetPenState (&ps); X PenPat (gray); X PenMode (patXor); X dragPt = startPoint; X Pt2Rect (dragPt, dragPt, dstRect); X FrameRect (dstRect); X for (;;) X { X GetMouse (&pt); X if (!EqualPt (pt, dragPt)) /* mouse has moved, change region */ X { X FrameRect (dstRect); X dragPt = pt; X Pt2Rect (dragPt, startPoint, dstRect); X result = SectRect (dstRect, &rClip, dstRect); X FrameRect (dstRect); X for (i = 0; i < 1000; ++i) { /* empty */ } X } X if (!StillDown ()) break; X } X FrameRect (dstRect); /* erase last rect */ X SetPenState (&ps); X} X X X XRgnWindInit () X{ X rgnWind = GetNewWindow (rgnWindRes, nil, -1L); X SkelWindow (rgnWind, X Mouse, /* draw rectangles */ X nil, /* ignore keyclicks */ X Update, X Activate, X nil, /* no close proc */ X Clobber, /* disposal proc */ X Idle, /* idle proc */ X true); X X rgnPortRect = rgnWind->portRect; X selectRgn = NewRgn (); /* selected region empty initially */ X selectWhen = 0L; /* first click can't be taken as dbl-click */ X} SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > TSDemos/MSkelZoom.c X/* X TransSkel multiple-window demonstration: ZoomRect module X X This module handles a window in which successive randomly generated X rectangles are smoothly interpolated into one another. The display X is white on black, which results in some interesting problems (see X ZDrawGrowBox, for instance). The display adjusts itself to the size X of the window, so that the zoom series always lie entirely within X the window. Clicking the mouse in the window pauses the display until X the button is released. X X 14 June 1986 Paul DuBois X*/ X X# include "MultiSkel.h" X X X# define zoomSteps 15 /* # rects in interpolative series */ X XWindowPtr zoomWind; Xstatic Rect zRect[zoomSteps]; /* set of interpolated rectangles */ Xstatic Rect zSrcRect; Xstatic int sizeX; /* size of window in pixels */ Xstatic int sizeY; X X XSetZoomSize () X{ XRect r; X X r = zoomWind->portRect; X r.right -= 15; /* don't use right edge */ X sizeX = r.right; X sizeY = r.bottom; X} X X X/* X return integer between zero and max (inclusive). assumes max is X non-negative. X*/ X XRand (max) Xint max; X{ Xregister int t; X X t = Random (); X if (t < 0) t = -t; X return (t % (max + 1)); X}; X X X/* X Interpolate one rectangle smoothly into another. Erase the previous X series as the new one is drawn. X*/ X XZoomRect (r1, r2) XRect r1, r2; X X{ Xregister int r1left, r1top; Xregister int l, t; Xregister int j; Xint hDiff, vDiff, widDiff, htDiff; Xint r, b; Xint rWid, rHt; X X X r1left = r1.left; X r1top = r1.top; X hDiff = r2.left - r1left; /* positive if moving to right */ X vDiff = r2.top - r1top; /* positive if moving down */ X rWid = r1.right - r1left; X rHt = r1.bottom - r1top; X widDiff = (r2.right - r2.left) - rWid; X htDiff = (r2.bottom - r2.top) - rHt; X/* X order of evaluation is important in the rect coordinate calculations. X since all arithmetic is integer, you can't save time by calculating X j/zoomSteps and using that - it'll usually be zero. X*/ X for (j = 1; j <= zoomSteps; j++) X { X FrameRect (&zRect[j-1]); /* erase a rectangle */ X l = r1left + (hDiff * j) / zoomSteps; X t = r1top + (vDiff * j) / zoomSteps; X r = l + rWid + (widDiff * j) / zoomSteps; X b = t + rHt + (htDiff * j) / zoomSteps; X SetRect (&zRect[j-1], l, t, r, b); X FrameRect (&zRect[j-1]); X } X} X X XIdle () X{ Xint i; XPoint pt1, pt2; XRect dstRect; X X SetPt (&pt1, Rand (sizeX), Rand (sizeY)); /* generate new rect */ X SetPt (&pt2, Rand (sizeX), Rand (sizeY)); /* and zoom to it */ X Pt2Rect (pt1, pt2, &dstRect); X SetWindClip (zoomWind); /* don't draw in right edge */ X ZoomRect (zSrcRect, dstRect); X ResetWindClip (); X zSrcRect = dstRect; X} X X X/* X just pause zoom display while mouse down X*/ X Xstatic Mouse (thePt, t, mods) XPoint thePt; Xlong t; Xint mods; X X{ X while (StillDown ()) { /* wait until mouse button released */ } X} X X X/* X Draw the grow box in white on black. This is tricky: if the window X is inactive, the grow box will be drawn black, as it should be. But X if the window is active, the box will STILL be drawn black on white! X So have to check whether the window is active or not. The test for X active has to be done carefully: the window manager stores 255 and 0 X for true and false, not real boolean values. X*/ X XZDrawGrowBox () X{ XRect r; X X PenMode (notPatCopy); X DrawGrowBox (zoomWind); X PenMode (patXor); X if ( ((WindowPeek) zoomWind)->hilited) /* grow box draw in white */ X { /* no matter what if active */ X r = zoomWind->portRect; /* - invert to fix */ X r.left = r.right - 14; X r.top = r.bottom - 14; X InvertRect (&r); X } X} X X Xstatic Update (resized) XBoolean resized; X{ Xint i; X X EraseRect (&zoomWind->portRect); X ZDrawGrowBox (zoomWind); X SetWindClip (zoomWind); X for (i = 0; i < zoomSteps; ++i) X FrameRect (&zRect[i]); X ResetWindClip (zoomWind); X if (resized) X SetZoomSize (); /* adjust to new window size */ X} X X Xstatic Activate (active) XBoolean active; X{ X X ZDrawGrowBox (zoomWind); X if (active) X DisableItem (editMenu, 0); X else X EnableItem (editMenu, 0); X DrawMenuBar (); X} X X Xstatic Halt () X{ X CloseWindow (zoomWind); X} X X XZoomWindInit () X{ Xint i; X X zoomWind = GetNewWindow (zoomWindRes, nil, -1L); X SkelWindow (zoomWind, X Mouse, /* pause while button down */ X nil, /* ignore key clicks */ X Update, X Activate, X nil, /* no close proc */ X Halt, /* when done with window */ X Idle, /* draw a new series */ X true); /* run only when frontmost */ X X SetZoomSize (); X BackPat (&black); X PenMode (patXor); X SetRect (&zSrcRect, 0, 0, 0, 0); X for (i = 0; i < zoomSteps; ++i) /* initialize rect array */ X zRect[i] = zSrcRect; X} SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > TSDemos/ManyWind.c X/* X ManyWind TransSkel demonstration X X This application allows up to twenty windows to be created at once, X with the New item under the File menu. The name of each window X appears under the Windows menu (which is not created until at least X one window exists). Selecting the window name from the Windows menu X brings the window to the front. For every window created, Skel is X told to create a new handler. If the window's close box is clicked, X the handler removes the window name from the Windows menu, disposes X of the window, and removes itself from the window handler list. If X the window was the last window, the Windows menu handler removes X itself from the menu handler list. X X When the first window is created, a Color menu also appears. This X allows the color of the content region of the frontmost window to X be changed. It goes away when the last window is closed. X X To quit, select Quit from the File menu or type command-Q. X X ManyWind demonstrates dynamic window and menu creation and disposal. X It also shows how handler procedures may be shared among handlers X for different windows. X X The project should include this file, TransSkel.c (or a project X built from TransSkel.c), and MacTraps. X X 28 June 1986 Paul DuBois X*/ X X# include <WindowMgr.h> X# include <MenuMgr.h> X X# define nil 0L X# define maxWind 20 /* maximum number of windows existing at once */ X X Xenum /* menu numbers */ X{ X aMenuNum = 1, /* Apple menu */ X fMenuNum, /* File menu */ X wMenuNum, /* Windows menu */ X cMenuNum /* Color menu */ X}; X X Xenum /* File menu item numbers */ X{ X new = 1, X /* --- */ X quit = 3 X}; X Xenum /* Color menu items numbers */ X{ X cWhite = 1, X cLtGray, X cGray, X cDkGray, X cBlack X}; X X XMenuHandle fileMenu; XMenuHandle windowMenu; XMenuHandle colorMenu; X Xint windCount = 0; /* number of currently existing windows */ Xlong windNum = 0; /* id of last window created */ X Xint DoWindowMenu(), DoColorMenu(), DoMClobber(); X X XDoWUpdate () X{ XGrafPtr thePort; X X X GetPort (&thePort); X EraseRect (&thePort->portRect); /* repaint w/background pattern */ X} X X X/* X Mouse was clicked in close box. Remove the window handler (which X causes the window to be disposed of), and delete the window title X from the Windows menu. If the window was the last one, delete the X Windows and Color menus entirely. X X Skel makes sure the port is pointing to the appropriate window, so X this procedure can determine which window had its close box clicked, X without being told explicitly. X*/ X XDoWClose () X{ XGrafPtr thePort; XMenuHandle m; Xint i, mItems; XStr255 iTitle, wTitle; X X GetPort (&thePort); /* grafport of window to be closed */ X GetWTitle ((WindowPtr) thePort, wTitle); X SkelRmveWind ((WindowPtr) thePort); X if (--windCount == 0) X { X SkelRmveMenu (windowMenu); /* last window - clobber menus */ X SkelRmveMenu (colorMenu); X } X else X { X /* just take out of menu */ X m = NewMenu (wMenuNum, "\pWindows"); X for (i = 1, mItems = CountMItems (windowMenu); i <= mItems; ++i) X { X GetItem (windowMenu, i, iTitle); X if (!EqualString (iTitle, wTitle, false, true)) X AppendMenu (m, iTitle); X }; X SkelRmveMenu (windowMenu); /* remove old Windows menu */ X windowMenu = m; /* and install new one */ X SkelMenu (windowMenu, DoWindowMenu, DoMClobber); X } X EnableItem (fileMenu, new); /* can always create at least one more now */ X} X X X/* X Dispose of window. Skel makes sure the port is pointing to the X appropriate window, so this procedure can determine which window X is to be disposed, of without being told explicitly. X*/ X XDoWClobber () X{ XGrafPtr thePort; X X GetPort (&thePort); /* grafport of window to dispose of */ X DisposeWindow ((WindowPtr) thePort); X} X X XDoMClobber (theMenu) XMenuHandle theMenu; X{ X DisposeMenu (theMenu); X} X X X/* X Make new window. Locate at (100, 100) if no other windows, else X offset slightly from front window. The window title is the next X window number (1, 2, 3, ...). If this is the first window, create X the Windows and Color menus. Add the window title as the last item X of the Windows menu. X X If the maximum window count has been reached, disable New in the X File menu. X*/ X X XMakeWindow () X{ XWindowPtr w; XRect r, r2; XStr255 s; X X SetRect (&r, 0, 0, 200, 150); X if ((w = FrontWindow ()) == nil) X OffsetRect (&r, 100, 100); X else X { X r2 = w->portBits.bounds; X OffsetRect (&r, 20 - r2.left, 20 - r2.top); X if (r.left > 480 || r.top > 300) /* keep on screen */ X OffsetRect (&r, 40 - r.left, 40 - r.top); X } X NumToString (++windNum, s); X w = NewWindow (nil, &r, s, true, documentProc, -1L, true, 0L); X SkelWindow (w, X nil, /* mouseclicks */ X nil, /* key clicks */ X DoWUpdate, /* updates */ X nil, /* activate/deactivate events */ X DoWClose, /* close window, remove from menu */ X DoWClobber, /* dispose of window */ X nil, /* idle proc */ X false); /* irrelevant, since no idle proc */ X X if (windCount++ == 0) /* if first window, create new menus */ X { X colorMenu = NewMenu (cMenuNum, "\pColor"); X AppendMenu (colorMenu, "\pWhite;Light Gray;Gray;Dark Gray;Black"); X SkelMenu (colorMenu, DoColorMenu, DoMClobber); X windowMenu = NewMenu (wMenuNum, "\pWindows"); X SkelMenu (windowMenu, DoWindowMenu, DoMClobber); X } X AppendMenu (windowMenu, s); X if (windCount == maxWind) X DisableItem (fileMenu, new); X X} X X XDoFileMenu (item) Xint item; X{ X X switch (item) X { X case quit: SkelWhoa (); break; /* tell SkelMain to quit */ X case new: MakeWindow (); break; /* make a new window */ X } X} X X XDoWindowMenu (item) Xint item; X{ XStr255 iTitle, wTitle; XWindowPeek w; X X GetItem (windowMenu, item, iTitle); /* get window name */ X for (w = (WindowPeek) FrontWindow (); w != nil; w = w->nextWindow) X { X GetWTitle (w, wTitle); X if (EqualString (iTitle, wTitle, false, true)) X { X SelectWindow (w); X break; X } X } X} X X X/* X Change the background pattern of the frontmost window. Ignore X if the front window is a DA window. X*/ X XDoColorMenu (item) Xint item; X{ XWindowPtr w; X X w = FrontWindow (); X if (((WindowPeek) w)->windowKind < 0) return; /* front is DA window */ X switch (item) X { X case cWhite: BackPat (white); break; X case cLtGray: BackPat (ltGray); break; X case cGray: BackPat (gray); break; X case cDkGray: BackPat (dkGray); break; X case cBlack: BackPat (black); break; X } X EraseRect (&w->portRect); X} X X Xmain () X{ X SkelInit (); /* initialize */ X SkelApple (nil, nil); /* handle desk accessories */ X fileMenu = NewMenu (fMenuNum, "\pFile"); /* make File menu handler */ X AppendMenu (fileMenu, "\pNew/N;(-;Quit/Q"); X SkelGrowBounds (nil, 50, 10, 500, 300); X SkelMenu (fileMenu, DoFileMenu, DoMClobber); X SkelMain (); /* loop 'til Quit selected */ X SkelClobber (); /* clean up */ X} SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > TSDemos/DialogSkel.c X X# include <DialogMgr.h> X# include <EventMgr.h> X# include <MenuMgr.h> X# include <ToolBoxUtil.h> X# include <Pascal.h> X X X# define nil (0L) X Xtypedef enum X{ X mDlogRes = 1000, X aboutAlrtRes /* About... alert resource number */ X}; X X Xtypedef enum /* File menu item numbers */ X{ X showDlog1 = 1, X showDlog2, X /* --- */ X quit = 4 X}; X X Xtypedef enum /* Edit menu item numbers */ X{ X undo = 1, X /* --- */ X cut = 3, X copy, X paste, X clear X}; X X Xtypedef enum /* dialog item numbers */ X{ X button1 = 1, X edit1, X static1, X radio1, X radio2, X radio3, X check1, X check2, X user1 X}; X X XDialogPtr mDlog1; XDialogPtr mDlog2; Xint iconNum1 = 0; Xint iconNum2 = 0; X Xpascal void DrawIcon (dlog, item) XDialogPtr dlog; Xint item; X{ XHandle h; XHandle itemHandle; Xint itemType; XRect itemRect; X X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect); X h = GetIcon (dlog == mDlog1 ? iconNum1 : iconNum2); X PlotIcon (&itemRect, h); X} X X XBoolean GetDCtl (dlog, item) XDialogPtr dlog; Xint item; X{ XHandle itemHandle; Xint itemType; XRect itemRect; X X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect); X return (GetCtlValue (itemHandle)); X} X X XSetDCtl (dlog, item, value) XDialogPtr dlog; Xint item; XBoolean value; X{ XHandle itemHandle; Xint itemType; XRect itemRect; X X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect); X SetCtlValue (itemHandle, (int) value); X} X X XGetDText (dlog, item, str) XDialogPtr dlog; Xint item; XStringPtr str; X{ XHandle itemHandle; Xint itemType; XRect itemRect; X X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect); X GetIText (itemHandle, str); X} X X XSetDText (dlog, item, str) XDialogPtr dlog; Xint item; XStr255 str; X{ XHandle itemHandle; Xint itemType; XRect itemRect; X X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect); X SetIText (itemHandle, str); X} X X XSetDProc (dlog, item, p) XDialogPtr dlog; Xint item; XProcPtr p; X{ XHandle itemHandle; Xint itemType; XRect itemRect; X X GetDItem (dlog, item, &itemType, &itemHandle, &itemRect); X SetDItem (dlog, item, itemType, p, &itemRect); X} X X XSetDRadio (dlog, item) XDialogPtr dlog; Xint item; X{ XDialogPtr partner; XHandle itemHandle; Xint itemType; XRect itemRect; X X partner = (DialogPtr) GetWRefCon (dlog); X SetDCtl (dlog, radio1, item == radio1); X SetDCtl (dlog, radio2, item == radio2); X SetDCtl (dlog, radio3, item == radio3); X X if (partner == mDlog1) X iconNum1 = item - radio1; X else X iconNum2 = item - radio1; X X GetDItem (partner, user1, &itemType, &itemHandle, &itemRect); X SetPort (partner); X InvalRect (&itemRect); X} X X XEvent (item, event) Xint item; XEventRecord *event; X{ XDialogPtr actor, partner; XStr255 title; XBoolean value; X X GetPort (&actor); X partner = (DialogPtr) GetWRefCon (actor); X switch (item) X { X case button1: X GetDText (actor, edit1, title); X SetWTitle (partner, title); X break; X X /* set radio buttons */ X X case radio1: X SetDRadio (actor, radio1); X break; X X case radio2: X SetDRadio (actor, radio2); X break; X X case radio3: X SetDRadio (actor, radio3); X break; X X /* flip check boxes */ X X case check1: X value = !GetDCtl (actor, item); X SetDCtl (actor, item, value); X if (value == false) X HideWindow (partner); X else X ShowWindow (partner); X break; X X case check2: X value = !GetDCtl (actor, check2); X SetDCtl (actor, check2, value); X ((WindowPeek) partner)->goAwayFlag = (char) (value ? 255 : 0); X break; X } X} X X XClose () X{ XDialogPtr actor, partner; X X GetPort (&actor); X partner = (DialogPtr) GetWRefCon (actor); X HideWindow (actor); X SetDCtl (partner, check1, false); X} X X XClobber () X{ XDialogPtr theDialog; X X GetPort (&theDialog); X DisposDialog (theDialog); X} X X X/* X File menu handler X*/ X XDoFileMenu (item) Xint item; X{ X X switch (item) X { X case showDlog1: X SelectWindow (mDlog1); X ShowWindow (mDlog1); X SetDCtl (mDlog2, check1, true); X break; X X case showDlog2: X SelectWindow (mDlog2); X ShowWindow (mDlog2); X SetDCtl (mDlog1, check1, true); X break; X X case quit: X SkelWhoa (); X break; X } X} X X X/* X Handle Edit menu items for text window X*/ X XDoEditMenu (item) Xint item; X{ XDialogPtr theDialog; X X theDialog = (DialogPtr) FrontWindow (); X if (((WindowPeek) theDialog)->windowKind != dialogKind) X return; X X switch (item) X { X case cut: X { X DlgCut (theDialog); X (void) ZeroScrap (); X (void) TEToScrap (); X break; X } X X case copy: X { X DlgCopy (theDialog); X (void) ZeroScrap (); X (void) TEToScrap (); X break; X } X X case paste: X { X (void) TEFromScrap (); X DlgPaste (theDialog); X break; X } X X case clear: X { X DlgDelete (theDialog); X break; X } X } X} X X X/* X Handle selection of AboutI item from Apple menu X*/ X XDoAbout () X{ X (void) Alert (aboutAlrtRes, nil); X} X X XDialogPtr DemoDialog (title, x, y) XStringPtr title; Xint x, y; X{ XDialogPtr theDialog; X X theDialog = GetNewDialog (mDlogRes, nil, -1L); X MoveWindow (theDialog, x, y, false); X SetWTitle (theDialog, title); X SkelDialog (theDialog, Event, Close, Clobber); X return (theDialog); X} X X Xmain () X{ XMenuHandle m; X X SkelInit (); X SkelApple ("\pAbout DialogSkelI", DoAbout); X X m = NewMenu (1000, "\pFile"); X AppendMenu (m, "\pShow Dialog 1;Show Dialog 2;(-"); X AppendMenu (m, "\pQuit/Q"); X SkelMenu (m, DoFileMenu, nil); X X m = NewMenu (1001, "\pEdit"); X AppendMenu (m, "\p(Undo/Z;(-;Cut/X;Copy/C;Paste/V;Clear"); X SkelMenu (m, DoEditMenu, nil); X X mDlog1 = DemoDialog ("\pModeless Dialog 1", 50, 50); X mDlog2 = DemoDialog ("\pModeless Dialog 2", 150, 200); X SetWRefCon (mDlog1, mDlog2); X SetWRefCon (mDlog2, mDlog1); X SetDText (mDlog1, edit1, "\pModeless Dialog 2"); X SetDText (mDlog2, edit1, "\pModeless Dialog 1"); X SetDProc (mDlog1, user1, DrawIcon); X SetDProc (mDlog2, user1, DrawIcon); X SetDCtl (mDlog1, radio1, true); X SetDCtl (mDlog2, radio1, true); X SetDCtl (mDlog1, check1, true); X SetDCtl (mDlog2, check1, true); X SetDCtl (mDlog1, check2, true); X SetDCtl (mDlog2, check2, true); X ShowWindow (mDlog1); X ShowWindow (mDlog2); X X SkelMain (); X SkelClobber (); X} SHAR_EOF exit