1 line
67 KiB
C
Executable File
1 line
67 KiB
C
Executable File
/* Copyright (c) 2017, Computer History Museum
|
|
All rights reserved.
|
|
Redistribution and use in source and binary forms, with or without modification, are permitted (subject to
|
|
the limitations in the disclaimer below) provided that the following conditions are met:
|
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
|
|
disclaimer in the documentation and/or other materials provided with the distribution.
|
|
* Neither the name of Computer History Museum nor the names of its contributors may be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
|
|
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
DAMAGE. */
|
|
|
|
#include "wazoo.h"
|
|
|
|
#define FILE_NUM 92
|
|
/* Copyright (c) 1997 by QUALCOMM Incorporated */
|
|
|
|
#pragma segment Wazoo
|
|
|
|
/*
|
|
* constants
|
|
*/
|
|
#define kEmbedderId 'Embr'
|
|
#define kTabsId 'Tabs'
|
|
#define kMaxTabs 16
|
|
|
|
// Tab drawing specs
|
|
#define kTabLeftMargin 3 // Start first tab here from left
|
|
#define kTabCtlTop (GetRLong(WAZOO_TOPMARGIN)-GetRLong(WAZOO_TABHEIGHT)-INSET)
|
|
|
|
// Constants used in saving contents of a MyWindow structure minus the WindowRecord
|
|
enum { kSaveDataOffset = 0, kSaveDataSize = sizeof(MyWindow) };
|
|
//enum { kSaveDataOffset = sizeof(DialogRecord), kSaveDataSize = sizeof(MyWindow)-kSaveDataOffset };
|
|
|
|
/*
|
|
* globals
|
|
*/
|
|
// List of wazooable windows, menu items, functions that open them
|
|
typedef struct
|
|
{
|
|
short kind; // window kind
|
|
short windRsrc; // resource ID of WIND resource
|
|
void (*openFunction)(void); // function to open this window
|
|
FeatureType dependentFeature; // feature this wazoo depends on (if any)
|
|
short temp; // used to remember which window are currently open when restoring wazoos
|
|
} WazooableItem;
|
|
|
|
static WazooableItem gWazooKinds[] =
|
|
{
|
|
#ifdef TASK_PROGRESS_ON
|
|
TASKS_WIN,TASKS_WIND,OpenTasksWin,featureNone,0,
|
|
#endif
|
|
MB_WIN,MBWIN_WIND,OpenMBWin,featureNone,0,
|
|
PH_WIN,PH_WIND,nil,featureNone,0, // The open function needs a parameter
|
|
ALIAS_WIN,ALIAS_WIND,OpenABWin,featureNone,0,
|
|
FILT_WIN,FILT_WIND,nil,featureNone,0,
|
|
PERS_WIN,PERSONALITIES_WIND,OpenPersonalitiesWin,featureMultiplePersonalities,0,
|
|
STA_WIN,STATIONERY_WIND,OpenStationeryWin,featureStationery,0,
|
|
SIG_WIN,SIGNATURES_WIND,OpenSignaturesWin,featureNone,0,
|
|
LINK_WIN,LINK_WIND,OpenLinkWin,featureLink,0,
|
|
STAT_WIN,STAT_WIND,OpenStatWin,featureNone,0
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
long winRefCon;
|
|
ControlHandle ctlEmbedder;
|
|
Byte winData[kSaveDataSize];
|
|
} SaveWazooData, *SaveWazooPtr, **SaveWazooHandle;
|
|
|
|
// Info saved in resource for each item in a wazoo
|
|
typedef struct
|
|
{
|
|
short kind;
|
|
SaveWazooHandle hSaveInfo;
|
|
Point minSize;
|
|
Str32 name;
|
|
} WazooItem;
|
|
|
|
// Wazoo list stored in resource of type kWazooListResType
|
|
typedef struct
|
|
{
|
|
short count; // Number of windows in list
|
|
Boolean zoomed;
|
|
Rect position;
|
|
WazooItem kindList[]; // List of window types in wazoo
|
|
} WazooRes, *WazooResPtr, **WazooResHandle;
|
|
|
|
// Wazoo list
|
|
typedef struct WazooDataStruct *WazooDataPtr, **WazooDataHandle;
|
|
enum { kIconsAndNames,kCondensedNames,kIconsOnly };
|
|
typedef struct WazooDataStruct
|
|
{
|
|
short current; // Which one is currently active? (0 - N-1)
|
|
WazooDataHandle next;
|
|
MyWindowPtr win;
|
|
WazooResHandle list; // Wazoo list resource
|
|
ControlHandle hTabCtrl;
|
|
ControlHandle hTabColorCtrl;
|
|
short tabDisplayMode; // Show names, condensed, tabs only
|
|
Rect tabRect[kMaxTabs+1]; // Rect of each tab
|
|
} WazooData;
|
|
|
|
// In debug builds, we check this somewhere else
|
|
#ifndef DEBUG
|
|
static
|
|
#endif
|
|
WazooDataHandle gWazooListHead;
|
|
|
|
// Info for dragging a wazoo tab
|
|
typedef struct
|
|
{
|
|
MyWindowPtr winSrc,winDest;
|
|
short tabIdx;
|
|
WazooItem tabData;
|
|
} DragData;
|
|
|
|
typedef enum { kDragInWazoo, kDragOutsideWazoo, kDragDone, kDragHid } DragDrawMode;
|
|
typedef struct
|
|
{
|
|
long a5;
|
|
RgnHandle rgnWindow;
|
|
Point lastMouse;
|
|
DragDrawMode mode,lastDrawMode;
|
|
RgnHandle tempRgn,saveClip;
|
|
} DragOutlineInfo;
|
|
|
|
static DragData gDragData;
|
|
static Boolean gDontDragHilite;
|
|
static Boolean gForceNewWazoo; // Make the next new window a wazoo?
|
|
static short gForceHPos, gForceVPos;
|
|
static DragOutlineInfo *gpDragOutline;
|
|
|
|
/*
|
|
* prototypes
|
|
*/
|
|
static void CheckTabResize(MyWindowPtr win,WazooDataHandle hWazooData,WazooResHandle hWazooRes,short tabDisplayMode);
|
|
static Boolean CloseAWazoo(MyWindowPtr win,WazooDataHandle hWazooData,WazooResHandle hWazooRes, short index);
|
|
static Boolean CloseAllButCurrent(MyWindowPtr win,WazooDataHandle hWazooData,WazooResHandle hWazooRes);
|
|
static void DisposeDragRgn(RgnHandle rgn);
|
|
static void DisposeWazoo(WazooDataHandle hWazooData,WazooResHandle hWazooRes);
|
|
static void DoDragHilite(MyWindowPtr win, DragReference drag, Rect *rHilite, Boolean fShow);
|
|
static void DragWazoo(MyWindowPtr win,Rect *rTab,Boolean *dontActivate,short tab);
|
|
static Boolean GetWazooData(MyWindowPtr win,WazooDataHandle *hWazooData,WazooResHandle *hWazooRes);
|
|
static Boolean IsKindWazooable(short thisKind);
|
|
static RgnHandle MakeDragRegion(Rect *rTab,short tab,WazooDataHandle hWazooData);
|
|
static void OpenWazoo(short kind);
|
|
static short PtInTab(MyWindowPtr win,Point pt);
|
|
static void RemoveTab(MyWindowPtr win,short tabIdx);
|
|
static Boolean RestoreWazooWindow(MyWindowPtr win, WazooDataHandle hWazooData, short idx,Boolean quietly);
|
|
static Boolean SaveCurrentWazoo(MyWindowPtr win, WazooDataHandle hWazooData, WazooResHandle hWazooRes, Boolean switching);
|
|
static void SelectWazoo(MyWindowPtr win,short idx);
|
|
static void SetWinFields(MyWindowPtr win, Ptr winData);
|
|
static WazooDataHandle FindWazoo(short windowKind,short *idx);
|
|
static ControlHandle EmbedTheControls(MyWindowPtr win,ControlHandle ctlEmbedder);
|
|
static void CalcWazooMinSize(MyWindowPtr win);
|
|
static void SetWazooMinSize(short kind,short h,short v);
|
|
static void CheckMinWinSize(MyWindowPtr win, Point minSize);
|
|
static Boolean MustSaveWazoo(MyWindowPtr win);
|
|
static void SetupTabs(WazooDataHandle hWazooData,WazooResHandle hWazooRes,Boolean draw);
|
|
static void SetCurrentTab(ControlHandle ctl, short tab);
|
|
static ControlHandle GetEmbedder(WazooDataHandle hWazooData, short idx, Boolean create);
|
|
static void SetupCustomTabs(MyWindowPtr win,WazooDataHandle hWazooData,WazooResHandle hWazooRes);
|
|
static RgnHandle GetTabRgn(Rect *r);
|
|
static void CalcTabRects(WazooDataHandle hWazooData,WazooResHandle hWazooRes);
|
|
|
|
#define SelectWazooWithUpdate(aMyWindowPtr,i) do{UpdateMyWindow(GetMyWindowWindowPtr(aMyWindowPtr));SelectWazoo(aMyWindowPtr,i);}while(0)
|
|
|
|
static pascal OSErr DrawDrag(DragRegionMessage message,
|
|
RgnHandle showRegion, Point showOrigin, RgnHandle hideRegion,
|
|
Point hideOrigin, void *dragDrawingRefCon, DragReference drag);
|
|
static pascal void SetupTabBackground(ControlHandle control, ControlBackgroundPtr info);
|
|
|
|
/*
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Translucent dragging stuff
|
|
//
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
enum
|
|
{
|
|
_DragDispatch = 0xABED
|
|
};
|
|
|
|
enum
|
|
{
|
|
gestaltDragMgrHasImageSupport = 3
|
|
};
|
|
|
|
typedef unsigned long DragImageFlags;
|
|
|
|
enum
|
|
{
|
|
dragStandardImage = 0x00000000,
|
|
dragDarkImage = 0x00000001,
|
|
dragDarkerImage = 0x00000002,
|
|
dragOpaqueImage = 0x00000003,
|
|
dragRegionAndImage = 0x00000010
|
|
};
|
|
|
|
pascal OSErr SetDragImage ( DragReference theDragRef,
|
|
PixMapHandle imagePixMap,
|
|
RgnHandle imageRgn,
|
|
Point imageOffsetPt,
|
|
DragImageFlags theImageFlags );
|
|
*/
|
|
|
|
|
|
/************************************************************************
|
|
* GetNewWazoo - a new window is being opened, is it a wazoo?
|
|
************************************************************************/
|
|
MyWindowPtr GetNewWazoo(short windowKind,Boolean *fIsWazoo)
|
|
{
|
|
MyWindowPtr win = nil;
|
|
short idx;
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
Str32 title;
|
|
|
|
if (hWazooData = FindWazoo(windowKind,&idx))
|
|
{
|
|
// It's a wazoo
|
|
*fIsWazoo = true;
|
|
hWazooRes = (*hWazooData)->list;
|
|
if (win = (*hWazooData)->win)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
// Wazoo window is already open, just switch
|
|
if (SaveCurrentWazoo(win,hWazooData,(*hWazooData)->list,true))
|
|
{
|
|
SetMyWindowPrivateData (win, 0);
|
|
win->pteList = nil;
|
|
PeteFocus(win,nil,true);
|
|
// Init everything to zero
|
|
SetWinFields(win, nil);
|
|
// Window has a new name
|
|
PCopy(title,(*hWazooRes)->kindList[idx].name);
|
|
SetWTitle(winWP, title);
|
|
UserSelectWindow(winWP);
|
|
|
|
// Don't let drawing take place until we're ready
|
|
// to display it
|
|
SetEmptyClipRgn(GetWindowPort(winWP));
|
|
win->noUpdates = true;
|
|
}
|
|
}
|
|
(*hWazooData)->current = idx;
|
|
}
|
|
else if (IsKindWazooable(windowKind))
|
|
*fIsWazoo = gForceNewWazoo; // Make this new window a wazoo?
|
|
else
|
|
*fIsWazoo = false;
|
|
return win;
|
|
}
|
|
|
|
/************************************************************************
|
|
* PositionWazoo - position the wazoo window
|
|
************************************************************************/
|
|
void PositionWazoo(MyWindowPtr win)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
Rect rPosition;
|
|
|
|
if (gForceNewWazoo && IsWazoo(winWP))
|
|
{
|
|
// Move to specified location
|
|
if (win->position)
|
|
{
|
|
(*win->position)(False,win);
|
|
MoveWindow(winWP, gForceHPos, gForceVPos, false);
|
|
MyWindowDidResize(win,nil);
|
|
}
|
|
}
|
|
else if (GetWazooData(win,&hWazooData,&hWazooRes))
|
|
{
|
|
rPosition = (*hWazooRes)->position;
|
|
utl_RestoreWindowPos(winWP,&rPosition,(*hWazooRes)->zoomed,1,TitleBarHeight(winWP),LeftRimWidth(winWP),(void*)FigureZoom,(void*)DefPosition);
|
|
MyWindowDidResize(win,nil);
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* SelectOpenWazoo - see if we can switch to a previous-opened wazoo
|
|
************************************************************************/
|
|
Boolean SelectOpenWazoo(short windowKind)
|
|
{
|
|
MyWindowPtr win;
|
|
short idx;
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
|
|
if ((hWazooData = FindWazoo(windowKind,&idx)) &&
|
|
(win = (*hWazooData)->win) &&
|
|
(hWazooRes = (*hWazooData)->list) &&
|
|
(idx == (*hWazooData)->current || (*hWazooRes)->kindList[idx].hSaveInfo))
|
|
{
|
|
SelectWazooWithUpdate(win,idx);
|
|
UserSelectWindow(GetMyWindowWindowPtr(win));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/************************************************************************
|
|
* FindOpenWazoo - return window ptr of wazoo based on window kind
|
|
************************************************************************/
|
|
MyWindowPtr FindOpenWazoo(short windowKind)
|
|
{
|
|
short idx;
|
|
WazooDataHandle hWazooData = FindWazoo(windowKind,&idx);
|
|
|
|
return hWazooData ? (*hWazooData)->win : nil;
|
|
}
|
|
|
|
/************************************************************************
|
|
* CloseWazoo - close wazoo window
|
|
************************************************************************/
|
|
Boolean CloseWazoo(MyWindowPtr win)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
|
|
if (GetWazooData(win,&hWazooData,&hWazooRes))
|
|
{
|
|
short current;
|
|
Rect rWindow;
|
|
Boolean zoomed;
|
|
|
|
// Close the other ones first
|
|
current = (*hWazooData)->current;
|
|
if (!CloseAllButCurrent(win,hWazooData,hWazooRes))
|
|
return false;
|
|
|
|
// Now close the current one
|
|
if (!CloseAWazoo(win,hWazooData,hWazooRes,current)) return false;
|
|
|
|
utl_SaveWindowPos(GetMyWindowWindowPtr(win),&rWindow,&zoomed);
|
|
if (!EqualRect(&rWindow, &(*hWazooRes)->position) || zoomed != (*hWazooRes)->zoomed)
|
|
{
|
|
(*hWazooRes)->position = rWindow;
|
|
(*hWazooRes)->zoomed = zoomed;
|
|
ChangedResource((Handle)hWazooRes);
|
|
}
|
|
|
|
(*hWazooData)->win = nil;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/************************************************************************
|
|
* PromoteToWazoo - convert a normal window to a wazoo window
|
|
************************************************************************/
|
|
void PromoteToWazoo(MyWindowPtr win)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
Str255 sTitle;
|
|
Rect r;
|
|
Boolean zoomed;
|
|
OSErr err;
|
|
ControlHandle ctl,ctlColor;
|
|
short windowKind;
|
|
ResType resType = IsFreeMode()?kFreeWazooListResType:kWazooListResType;;
|
|
|
|
windowKind = GetWindowKind(winWP);
|
|
// Verify that this window kind is wazooable. Shouldn't get here if it isn't (but
|
|
// apparently it has happened).
|
|
if (!IsWazooable(winWP))
|
|
return;
|
|
|
|
if (!(hWazooData = FindWazoo(windowKind,nil)))
|
|
{
|
|
// New wazoo
|
|
if (!(hWazooData=NuHandleClear(sizeof(WazooData))))
|
|
return; // Err
|
|
if (!(hWazooRes=NuHandleClear(sizeof(WazooRes)+sizeof(WazooItem))))
|
|
return; // Err
|
|
// Do wazoo list resource
|
|
(*hWazooRes)->count = 1;
|
|
(*hWazooRes)->kindList[0].kind = windowKind;
|
|
MyGetOriginalWTitle(win, sTitle);
|
|
if (*sTitle > 31) *sTitle = 31; // Make sure name isn't too long
|
|
PCopy((*hWazooRes)->kindList[0].name,sTitle);
|
|
(*hWazooRes)->kindList[0].minSize = win->minSize;
|
|
win->minSize.v += GetRLong(WAZOO_TOPMARGIN);
|
|
|
|
// Get window position
|
|
utl_SaveWindowPos(winWP,&r,&zoomed);
|
|
(*hWazooRes)->position = r;
|
|
(*hWazooRes)->zoomed = zoomed;
|
|
AddResource_(hWazooRes,resType,Unique1ID(resType),"");
|
|
|
|
// Do wazoo data for win
|
|
LL_Push(gWazooListHead,hWazooData);
|
|
(*hWazooData)->list = hWazooRes;
|
|
|
|
}
|
|
|
|
SetTopMargin(win,GetRLong(WAZOO_TOPMARGIN));
|
|
|
|
// Do win stuff
|
|
(*hWazooData)->win = win;
|
|
win->wazooData = (Handle)hWazooData;
|
|
CalcWazooMinSize(win);
|
|
|
|
// Set up a tab control
|
|
GetPortBounds(GetWindowPort(winWP),&r);
|
|
r.bottom = GetRLong(WAZOO_TOPMARGIN);
|
|
|
|
r.top = kTabCtlTop; r.left--; r.right++;
|
|
ctl = NewControl(winWP,&r,"",false,0,0,0,kControlTabLargeNorthProc,kTabsId);
|
|
|
|
if (ctl)
|
|
{
|
|
err = EmbedControl(ctl,win->topMarginCntl);
|
|
// ASSERT(!err);
|
|
(*hWazooData)->hTabCtrl = ctl;
|
|
SetupTabs(hWazooData,(*hWazooData)->list,false);
|
|
SetControlVisibility(ctl,true,false);
|
|
|
|
// Embed a control within the tab control so we can get it's background color
|
|
SetRect(&r,10,GetRLong(WAZOO_TABHEIGHT)+10,15,GetRLong(WAZOO_TABHEIGHT)+15);
|
|
if (ctlColor = NewControl(winWP,&r,"",false,0,0,0,kControlUserPaneProc,0))
|
|
{
|
|
err = EmbedControl(ctlColor,ctl);
|
|
ASSERT(!err);
|
|
(*hWazooData)->hTabColorCtrl = ctlColor;
|
|
}
|
|
}
|
|
|
|
// Make sure window isn't too small with the tabs
|
|
CheckMinWinSize(win,win->minSize);
|
|
|
|
MyWindowDidResize(win,nil);
|
|
}
|
|
|
|
/************************************************************************
|
|
* DemoteWazoo - demote a wazoo to a normal window
|
|
************************************************************************/
|
|
void DemoteWazoo(MyWindowPtr win)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
|
|
if (GetWazooData(win,&hWazooData,&hWazooRes))
|
|
{
|
|
Point minSize;
|
|
short i;
|
|
|
|
minSize = (*hWazooRes)->kindList[(*hWazooData)->current].minSize;
|
|
if (!CloseAllButCurrent(win,hWazooData,hWazooRes)) return;
|
|
DisposeControl((*hWazooData)->hTabCtrl);
|
|
DisposeControl((*hWazooData)->hTabColorCtrl);
|
|
|
|
// dispose of saved data for each window in wazoo
|
|
for(i=0;i<(*hWazooRes)->count;i++)
|
|
{
|
|
SaveWazooHandle hSaveInfo;
|
|
|
|
if (hSaveInfo = (*hWazooRes)->kindList[i].hSaveInfo)
|
|
{
|
|
ControlHandle ctlEmbedder;
|
|
|
|
if (ctlEmbedder = (*hSaveInfo)->ctlEmbedder)
|
|
{
|
|
// Un-embed all controls before disposing of embedder control
|
|
UInt16 count;
|
|
ControlHandle ctl,ctlRoot;
|
|
WindowPtr winWP = GetMyWindowWindowPtr(win);
|
|
|
|
GetRootControl(winWP, &ctlRoot);
|
|
if (!CountSubControls (ctlEmbedder, &count))
|
|
for (;count;count--)
|
|
if (!GetIndexedSubControl(ctlEmbedder,count,&ctl))
|
|
EmbedControl(ctl,ctlRoot);
|
|
DisposeControl(ctlEmbedder);
|
|
}
|
|
ZapHandle(hSaveInfo);
|
|
(*hWazooRes)->kindList[i].hSaveInfo = nil;
|
|
}
|
|
}
|
|
|
|
DisposeWazoo(hWazooData,hWazooRes);
|
|
SetTopMargin(win,0);
|
|
win->wazooData = nil;
|
|
win->minSize = minSize;
|
|
MyWindowDidResize(win,nil);
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* WazooPreUpdate - going to update a window. Handle tab control updates
|
|
************************************************************************/
|
|
void WazooPreUpdate(MyWindowPtr win)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
CGrafPtr winPort = GetWindowPort(winWP);
|
|
WazooDataHandle hWazooData;
|
|
Rect rTab;
|
|
|
|
if (IsWindowVisible(winWP) && GetWazooData(win,&hWazooData,nil))
|
|
{
|
|
// Draw tab control first so it's in the background.
|
|
// Need to temporarily resize embedder control so entire
|
|
// tab control will draw
|
|
ControlHandle hTabCtrl = (*hWazooData)->hTabCtrl;
|
|
RgnHandle clipRgn;
|
|
|
|
// draw the top margin control first to clean up old tabs
|
|
Draw1Control(win->topMarginCntl);
|
|
|
|
if (GetWindowKind(GetMyWindowWindowPtr(win))!=STAT_WIN)
|
|
{
|
|
// if statistics window, only redraw top part of tabs to avoid flicker
|
|
Rect rPort,rCtl;
|
|
GetPortBounds(winPort,&rPort);
|
|
GetControlBounds(hTabCtrl,&rCtl);
|
|
rCtl.bottom = rPort.bottom+1;
|
|
SetControlBounds(hTabCtrl,&rCtl);
|
|
}
|
|
// Don't draw in the dontGreyOnMe area
|
|
clipRgn = SavePortClipRegion(winPort);
|
|
RgnMumbleRect(clipRgn,&win->dontGreyOnMe,false);
|
|
RestorePortClipRegion(winPort,clipRgn);
|
|
GetControlBounds(hTabCtrl,&rTab);
|
|
rTab.top = kTabCtlTop;
|
|
SetControlBounds(hTabCtrl,&rTab);
|
|
Draw1Control(hTabCtrl);
|
|
InfiniteClip(winPort); // Restore clipping region
|
|
rTab.bottom = GetRLong(WAZOO_TOPMARGIN);
|
|
SetControlBounds(hTabCtrl,&rTab);
|
|
SetTabBackColor(win);
|
|
// SetControlVisibility((*hWazooData)->hTabCtrl,false,false); // Don't want tab control to draw again
|
|
|
|
// Don't need to draw tabs anymore on this update event
|
|
ValidWindowRect(winWP,&rTab);
|
|
|
|
// Make sure controls are embedded
|
|
GetEmbedder(hWazooData,-1,true);
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* SetupTabBackground - setup background color for tab control
|
|
************************************************************************/
|
|
static pascal void SetupTabBackground(ControlHandle control, ControlBackgroundPtr info)
|
|
{
|
|
SetTabBackColor(GetWindowMyWindowPtr(GetControlOwner(control)));
|
|
}
|
|
|
|
/************************************************************************
|
|
* IsKindWazooable - is this window kind wazooable?
|
|
************************************************************************/
|
|
static Boolean IsKindWazooable(short thisKind)
|
|
{
|
|
short kind;
|
|
for (kind=0;kind<sizeof(gWazooKinds)/sizeof(WazooableItem);kind++)
|
|
{
|
|
if (thisKind==gWazooKinds[kind].kind)
|
|
if (gWazooKinds[kind].dependentFeature && !HasFeature (gWazooKinds[kind].dependentFeature))
|
|
continue;
|
|
else
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/************************************************************************
|
|
* IsWazooable - is this window wazooable?
|
|
************************************************************************/
|
|
Boolean IsWazooable(WindowPtr winWP)
|
|
{
|
|
if (winWP)
|
|
return IsKindWazooable(GetWindowKind(winWP));
|
|
return false;
|
|
}
|
|
|
|
/************************************************************************
|
|
* IsWazoo - is this window a wazoo?
|
|
************************************************************************/
|
|
Boolean IsWazoo(WindowPtr winWP)
|
|
{
|
|
if (IsMyWindow(winWP)) {
|
|
MyWindowPtr win = GetWindowMyWindowPtr(winWP);
|
|
return (win->wazooData != 0);
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
/************************************************************************
|
|
* IsLonelyWazoo - is this window in a wazoo, all by itself?
|
|
************************************************************************/
|
|
Boolean IsLonelyWazoo(WindowPtr winWP)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
|
|
if (IsWazoo(winWP))
|
|
if (GetWazooData (GetWindowMyWindowPtr (winWP), &hWazooData, &hWazooRes))
|
|
return ((*hWazooRes)->count == 1);
|
|
return (false);
|
|
}
|
|
|
|
/************************************************************************
|
|
* IsKindWazoo - is this kind in a wazoo?
|
|
************************************************************************/
|
|
Boolean IsKindWazoo(short windowKind)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
short idx;
|
|
|
|
hWazooData = FindWazoo(windowKind,&idx);
|
|
return (hWazooData!=nil);
|
|
}
|
|
|
|
/************************************************************************
|
|
* ClickWazoo - check for and process clicks in a wazoo
|
|
************************************************************************/
|
|
Boolean ClickWazoo(MyWindowPtr win,EventRecord *event,Point pt,Boolean *dontActivate)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr(win);
|
|
short tab;
|
|
|
|
if (dontActivate) *dontActivate = False;
|
|
/*
|
|
if (event->modifiers & controlKey && IsWazooable(win) && !PrefIsSet(PREF_CONTROL_DRAG))
|
|
{
|
|
// Pop up contextual menu for window
|
|
Point globalPt = pt;
|
|
short menuItem;
|
|
MenuHandle mh = GetMHandle(WIND_PROP_HIER_MENU);
|
|
|
|
SetWindowPropMenu(win,true,False,diamondChar,event->modifiers);
|
|
SetWindowPropMenu(win,false,False,diamondChar,event->modifiers);
|
|
LocalToGlobal(&globalPt);
|
|
menuItem = AFPopUpMenuSelect(mh,globalPt.v,globalPt.h,-1);
|
|
DoWindowPropMenu(win,menuItem,event->modifiers);
|
|
return true;
|
|
}
|
|
|
|
*/
|
|
if ((tab = PtInTab(win,pt))>=0)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
Boolean moved;
|
|
Rect rTab;
|
|
|
|
if (!win->isActive)
|
|
{
|
|
SelectWindow_(winWP);
|
|
ActivateMyWindow(winWP,true);
|
|
}
|
|
|
|
GetWazooData(win,&hWazooData,nil);
|
|
|
|
rTab = (*hWazooData)->tabRect[tab];
|
|
if (tab != (*hWazooData)->current)
|
|
{
|
|
SetCurrentTab((*hWazooData)->hTabCtrl,tab);
|
|
SelectWazoo(win,tab);
|
|
}
|
|
moved = MyWaitMouseMoved(event->where,false);
|
|
if (moved)
|
|
{
|
|
// Started a drag
|
|
DragWazoo(win,&rTab,dontActivate,tab);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/************************************************************************
|
|
* DidResizeWazoo - wazoo was resized
|
|
************************************************************************/
|
|
void DidResizeWazoo(MyWindowPtr win,Rect *oldCont)
|
|
{
|
|
#pragma unused(oldCont)
|
|
|
|
// If tab width has changed, redraw the tabs
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
|
|
if (GetWazooData(win,&hWazooData,&hWazooRes))
|
|
{
|
|
Rect r;
|
|
|
|
GetPortBounds(GetMyWindowCGrafPtr(win),&r);
|
|
r.bottom = GetRLong(WAZOO_TOPMARGIN);
|
|
r.top = kTabCtlTop; r.left--; r.right++;
|
|
|
|
// Don't draw tab control when resizing
|
|
SetControlVisibility((*hWazooData)->hTabCtrl,false,false);
|
|
SizeControl((*hWazooData)->hTabCtrl,RectWi(r),RectHi(r));
|
|
SetControlVisibility((*hWazooData)->hTabCtrl,true,true);
|
|
|
|
SetupTabs(hWazooData,hWazooRes,false);
|
|
CheckTabResize(win,hWazooData,hWazooRes,(*hWazooData)->tabDisplayMode);
|
|
}
|
|
CalcWazooMinSize(win);
|
|
}
|
|
|
|
/************************************************************************
|
|
* KillWazoos - get rid of the list of wazoos
|
|
************************************************************************/
|
|
void KillWazoos(void)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
|
|
if (hWazooData = gWazooListHead)
|
|
{
|
|
// Dispose of current wazoo list. Probably switching settings files
|
|
while (hWazooData)
|
|
{
|
|
WazooDataHandle hNextWazooData;
|
|
|
|
hNextWazooData = (*hWazooData)->next;
|
|
ZapHandle(hWazooData);
|
|
hWazooData = hNextWazooData;
|
|
}
|
|
gWazooListHead = nil;
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* WazooHelp - display wazoo help balloon
|
|
************************************************************************/
|
|
Boolean WazooHelp(MyWindowPtr win,Point mouse)
|
|
{
|
|
Boolean result = false;
|
|
short tab;
|
|
Str255 sHelp;
|
|
Str32 title;
|
|
|
|
if ((tab = PtInTab(win,mouse))>=0)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
Rect rTab;
|
|
|
|
GetWazooData(win,&hWazooData,&hWazooRes);
|
|
rTab = (*hWazooData)->tabRect[tab];
|
|
PCopy(title,(*hWazooRes)->kindList[tab].name);
|
|
|
|
ComposeRString(sHelp,WAZOO_TAB_HELP,title,title);
|
|
MyBalloon(&rTab,100,0,0,0,sHelp);
|
|
|
|
result = true;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/************************************************************************
|
|
* InitWazoos - set up list of wazoos
|
|
************************************************************************/
|
|
void InitWazoos(void)
|
|
{
|
|
short saveFile = CurResFile();
|
|
short count,idx;
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
ResType resType = IsFreeMode()?kFreeWazooListResType:kWazooListResType;;
|
|
|
|
KillWazoos(); // just in case...
|
|
|
|
UseResFile(SettingsRefN);
|
|
count = Count1Resources(resType);
|
|
for(idx=1;idx<=count;idx++)
|
|
{
|
|
if (hWazooRes=(WazooResHandle)Get1IndResource(resType,idx))
|
|
{
|
|
short i;
|
|
WazooResPtr pWazooRes;
|
|
|
|
// Zero out hSaveInfo handle which may have been saved with the resource
|
|
pWazooRes = *hWazooRes;
|
|
for(i=0;i<pWazooRes->count;i++)
|
|
pWazooRes->kindList[i].hSaveInfo = nil;
|
|
|
|
if (hWazooData = NuHandleClear(sizeof(WazooData)))
|
|
{
|
|
(*hWazooData)->list = hWazooRes;
|
|
LL_Push(gWazooListHead,hWazooData);
|
|
}
|
|
}
|
|
}
|
|
UseResFile(saveFile);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* SetupDefaultWazoos - revert to default wazoos
|
|
**********************************************************************/
|
|
void SetupDefaultWazoos(void)
|
|
{
|
|
short i;
|
|
WindowPtr win,next;
|
|
ResType resType = IsFreeMode()?kFreeWazooListResType:kWazooListResType;
|
|
Boolean abort = false;
|
|
|
|
// Clear out temp field for each wazoo type
|
|
for (i=0;i<sizeof(gWazooKinds)/sizeof(WazooableItem);i++)
|
|
gWazooKinds[i].temp = false;
|
|
|
|
// Close every wazoo that is open and remember what was open
|
|
for (win=FrontWindow();win;win=next)
|
|
{
|
|
next = GetNextWindow(win); // We might close this window
|
|
if (IsWindowVisible(win) && IsWazooable(win))
|
|
{
|
|
for (i=0;i<sizeof(gWazooKinds)/sizeof(WazooableItem);i++)
|
|
if (gWazooKinds[i].kind == GetWindowKind(win))
|
|
{
|
|
if (!CloseMyWindow(win))
|
|
{
|
|
// couldn't close window. abort
|
|
abort = true;
|
|
next = nil;
|
|
}
|
|
gWazooKinds[i].temp = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!abort)
|
|
{
|
|
// Get rid of all wazoo resources and copy over default ones
|
|
UseResFile(SettingsRefN);
|
|
for(i=Count1Resources(resType);i;i--)
|
|
{
|
|
Handle resH;
|
|
|
|
SetResLoad(false);
|
|
resH=Get1IndResource(resType,i);
|
|
SetResLoad(true);
|
|
if (resH)
|
|
{
|
|
RemoveResource(resH);
|
|
ZapHandle(resH);
|
|
}
|
|
}
|
|
ResourceCpy(SettingsRefN,AppResFile,resType,kWazooRes1);
|
|
ResourceCpy(SettingsRefN,AppResFile,resType,kWazooRes2);
|
|
InitWazoos();
|
|
}
|
|
|
|
// Reopen wazoo windows that were previously open
|
|
for (i=0;i<sizeof(gWazooKinds)/sizeof(WazooableItem);i++)
|
|
if (gWazooKinds[i].temp)
|
|
{
|
|
gWazooKinds[i].temp = false;
|
|
OpenWazoo(gWazooKinds[i].kind);
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* DisposeWazoo - dispose of wazoo info for window
|
|
************************************************************************/
|
|
static void DisposeWazoo(WazooDataHandle hWazooData,WazooResHandle hWazooRes)
|
|
{
|
|
SaveWazooHandle hSaveInfo;
|
|
short current = (*hWazooData)->current;
|
|
|
|
LL_Remove(gWazooListHead,hWazooData,(WazooDataHandle));
|
|
RemoveResource((Handle)hWazooRes);
|
|
if (current >= 0)
|
|
if (hSaveInfo = (*hWazooRes)->kindList[current].hSaveInfo)
|
|
ZapHandle(hSaveInfo);
|
|
ZapHandle(hWazooRes);
|
|
ZapHandle(hWazooData);
|
|
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* SetTabBackColor - get tab background color
|
|
************************************************************************/
|
|
void SetTabBackColor(MyWindowPtr win)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
|
|
if (GetWazooData(win,&hWazooData,nil) && (*hWazooData)->hTabColorCtrl)
|
|
SetUpControlBackground((*hWazooData)->hTabColorCtrl,RectDepth(&win->contR),ThereIsColor);
|
|
}
|
|
|
|
/************************************************************************
|
|
* FindWazoo - search wazoo lists for the indicated type
|
|
************************************************************************/
|
|
static WazooDataHandle FindWazoo(short windowKind,short *idx)
|
|
{
|
|
WazooDataHandle hWazooData = gWazooListHead;
|
|
|
|
while (hWazooData)
|
|
{
|
|
WazooResPtr pWazooRes = *(*hWazooData)->list;
|
|
short i;
|
|
|
|
for(i=0;i<pWazooRes->count;i++)
|
|
{
|
|
if (pWazooRes->kindList[i].kind == windowKind)
|
|
{
|
|
if (idx)
|
|
*idx = i;
|
|
return hWazooData; // Found it!
|
|
}
|
|
}
|
|
hWazooData = (*hWazooData)->next;
|
|
}
|
|
return nil; // Not found
|
|
}
|
|
|
|
/************************************************************************
|
|
* SetWazooMinSize - set min size for this window and update wazoo's min size
|
|
************************************************************************/
|
|
static void SetWazooMinSize(short kind,short h,short v)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
short idx;
|
|
|
|
if (hWazooData = FindWazoo(kind,&idx))
|
|
{
|
|
// Make sure minimum size is set up correctly
|
|
Point minSize;
|
|
WazooResHandle hWazooRes;
|
|
MyWindowPtr win;
|
|
|
|
hWazooRes = (*hWazooData)->list;
|
|
if (win = (*hWazooData)->win)
|
|
{
|
|
Point newSize;
|
|
|
|
minSize = (*hWazooRes)->kindList[idx].minSize;
|
|
if (h && v)
|
|
{
|
|
newSize.h = h;
|
|
newSize.v = v;
|
|
}
|
|
else
|
|
{
|
|
// Need to get initial window size from WIND resource if we don't already have it
|
|
short kind;
|
|
|
|
if (minSize.h || minSize.v)
|
|
{
|
|
// Already have size
|
|
newSize = minSize;
|
|
}
|
|
else
|
|
{
|
|
newSize = minSize;
|
|
for (kind=0;kind<sizeof(gWazooKinds)/sizeof(WazooableItem);kind++)
|
|
if (GetWindowKind(GetMyWindowWindowPtr(win))==gWazooKinds[kind].kind)
|
|
{
|
|
Handle hWIND;
|
|
|
|
if (hWIND = GetResource('WIND',gWazooKinds[kind].windRsrc))
|
|
{
|
|
Rect r = **(Rect**)hWIND;
|
|
newSize.h = r.right-r.left;
|
|
newSize.v = r.bottom-r.top;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (minSize.h != newSize.h || minSize.v != newSize.v)
|
|
{
|
|
(*hWazooRes)->kindList[idx].minSize = newSize;
|
|
ChangedResource((Handle)hWazooRes);
|
|
}
|
|
CalcWazooMinSize(win);
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* OpenWindow - open a window based on the windowKind
|
|
************************************************************************/
|
|
static void OpenWazoo(short kind)
|
|
{
|
|
|
|
if (kind==PH_WIN)
|
|
OpenPh(nil); // Special case, requires a parameter
|
|
else if (kind==FILT_WIN)
|
|
OpenFiltersWindow(); // Special case, returns a value
|
|
else
|
|
{
|
|
short i;
|
|
for (i=0;i<sizeof(gWazooKinds)/sizeof(WazooableItem);i++)
|
|
{
|
|
// (jp) 12-16-99 Check to see if the kind is wazooable, just in case we're
|
|
// attempting to wazoo a window that isn't available in Light
|
|
if (kind==gWazooKinds[i].kind && IsKindWazooable(kind))
|
|
{
|
|
|
|
// Open the window
|
|
(*gWazooKinds[i].openFunction)();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
SetWazooMinSize(kind,0,0);
|
|
}
|
|
|
|
/************************************************************************
|
|
* GetWazooData - get wazoo data
|
|
************************************************************************/
|
|
static Boolean GetWazooData(MyWindowPtr win,WazooDataHandle *hWazooData,WazooResHandle *hWazooRes)
|
|
{
|
|
if (win && (*hWazooData = (WazooDataHandle)win->wazooData))
|
|
{
|
|
if (hWazooRes)
|
|
*hWazooRes = (**hWazooData)->list;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/************************************************************************
|
|
* SelectWazoo - select the window
|
|
************************************************************************/
|
|
static void SelectWazoo(MyWindowPtr win,short idx)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
|
|
if (GetWazooData(win,&hWazooData,&hWazooRes) && idx != (*hWazooData)->current)
|
|
{
|
|
if (MustSaveWazoo(win) && GetRLong(AUTOSAVE_INTERVAL))
|
|
// Auto save this wazoo window before switching out
|
|
DoMenu2(winWP,FILE_MENU,FILE_SAVE_ITEM,0);
|
|
|
|
if (SaveCurrentWazoo(win,hWazooData,hWazooRes,true))
|
|
{
|
|
if (!RestoreWazooWindow(win,hWazooData,idx,false))
|
|
{
|
|
// First time in this window. Open it.
|
|
// Set clip rgn to nil so the window doesn't
|
|
// get any garbage drawn to it while the window
|
|
// is being set up. Most of the window initialization
|
|
// is done with the assumption that the window is invisible.
|
|
SetEmptyClipRgn(GetWindowPort(winWP));
|
|
win->noUpdates = true;
|
|
OpenWazoo((*hWazooRes)->kindList[idx].kind);
|
|
win->noUpdates = false;
|
|
InfiniteClip(GetWindowPort(winWP)); // Restore clipping region
|
|
}
|
|
InvalContent(win);
|
|
InvalTopMargin(win);
|
|
CheckMinWinSize(win,win->minSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* PtInTab - see if point is in a tab (returns 0-based index), -1 if not found
|
|
************************************************************************/
|
|
static short PtInTab(MyWindowPtr win,Point pt)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
short tab;
|
|
|
|
if (GetWazooData(win,&hWazooData,&hWazooRes))
|
|
for(tab=0;tab<(*hWazooRes)->count;tab++)
|
|
{
|
|
Rect rTab = (*hWazooData)->tabRect[tab];
|
|
if (PtInRect(pt,&rTab))
|
|
return tab;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/************************************************************************
|
|
* EmbedTheControls - make sure every non-embedder control in the window is embedded within an embedder
|
|
************************************************************************/
|
|
static ControlHandle EmbedTheControls(MyWindowPtr win,ControlHandle ctlEmbedder)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr(win);
|
|
ControlHandle ctlRoot;
|
|
ControlHandle ctlTabs = nil;
|
|
ControlHandle ctlTemp,ctl;
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
|
|
if (GetWazooData(win,&hWazooData,&hWazooRes))
|
|
ctlTabs = (*hWazooData)->hTabCtrl;
|
|
|
|
if (!ctlEmbedder)
|
|
{
|
|
// Create an embedder control
|
|
Rect r;
|
|
DECLARE_UPP(SetupTabBackground,ControlUserPaneBackground);
|
|
|
|
INIT_UPP(SetupTabBackground,ControlUserPaneBackground);
|
|
SetRect(&r,-REAL_BIG/2,-REAL_BIG/2,REAL_BIG/2,REAL_BIG/2);
|
|
ctlEmbedder = NewControl(winWP, &r, "", true, kControlSupportsEmbedding+kControlWantsActivate+kControlHasSpecialBackground, 0, 0, kControlUserPaneProc, kEmbedderId);
|
|
SetControlData(ctlEmbedder,0,kControlUserPaneBackgroundProcTag,sizeof(SetupTabBackgroundUPP),(Ptr)&SetupTabBackgroundUPP);
|
|
}
|
|
|
|
// Make sure every non-embedder control in the window is embedded within this embedder
|
|
if (ctlEmbedder)
|
|
{
|
|
GetRootControl(winWP, &ctlRoot);
|
|
|
|
// Need to inspect every control embedded in the root control.
|
|
// Unfortunately, CountSubControls and GetIndexedSubControl don't appear
|
|
// to work correctly with the root control under Appearance Manager 1.0.
|
|
// We will therefore walk thru the control list checking for the root control
|
|
// as the super control
|
|
for(ctl=GetControlList(winWP);ctl;ctl=GetNextControl(ctl))
|
|
{
|
|
if (!GetSuperControl(ctl, &ctlTemp) && // Get super control
|
|
ctlTemp==ctlRoot && // Only want controls embedded within root control
|
|
GetControlReference(ctl)!=kEmbedderId && // Ignore embedders
|
|
ctl != win->topMarginCntl && // Ignore top margin control
|
|
ctl != ctlTabs) // Ignore tabs control
|
|
// Embed it in the embedder.
|
|
EmbedControl(ctl, ctlEmbedder);
|
|
}
|
|
}
|
|
|
|
return ctlEmbedder;
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* SaveCurrentWazoo - save the current wazoo window data
|
|
************************************************************************/
|
|
static Boolean SaveCurrentWazoo(MyWindowPtr win, WazooDataHandle hWazooData, WazooResHandle hWazooRes,Boolean switching)
|
|
{
|
|
SaveWazooHandle hSave;
|
|
short current;
|
|
ControlHandle embedder;
|
|
|
|
current = (*hWazooData)->current;
|
|
if (current < 0) return true; // Nothing to save
|
|
hSave = (*hWazooRes)->kindList[current].hSaveInfo;
|
|
if (!hSave)
|
|
{
|
|
hSave = NuHandleClear(sizeof(SaveWazooData));
|
|
(*hWazooRes)->kindList[current].hSaveInfo = hSave;
|
|
}
|
|
if (hSave)
|
|
{
|
|
// Make sure every non-embedder control in the window is embedded within an embedder
|
|
EmbedTheControls(win,embedder = GetEmbedder(hWazooData,current,true));
|
|
if (switching) {
|
|
// Switching out, hide controls
|
|
SetControlVisibility (embedder,false,false);
|
|
if (win->wazooSwitch) (*win->wazooSwitch)(win,false);
|
|
}
|
|
(*hSave)->winRefCon = GetMyWindowPrivateData(win);
|
|
BMD(((Ptr)win)+kSaveDataOffset,(*hSave)->winData,kSaveDataSize);
|
|
}
|
|
return hSave!=nil;
|
|
}
|
|
|
|
/************************************************************************
|
|
* RestoreWazooWindow - restore the wazoo window data
|
|
************************************************************************/
|
|
static Boolean RestoreWazooWindow(MyWindowPtr win,WazooDataHandle hWazooData,short idx,Boolean quietly)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr(win);
|
|
SaveWazooHandle hSave;
|
|
Str32 title;
|
|
WazooResHandle hWazooRes = (*hWazooData)->list;
|
|
ControlHandle embedder;
|
|
short current;
|
|
|
|
if (win->pte)
|
|
// Deactivate any Pete text
|
|
PeteActivate(win->pte,false,false);
|
|
// Hide former controls
|
|
current = (*hWazooData)->current;
|
|
if (current >= 0)
|
|
if ((hSave = (*hWazooRes)->kindList[current].hSaveInfo) &&
|
|
(embedder = GetEmbedder(hWazooData,-1,true))) {
|
|
SetControlVisibility (embedder,false,false);
|
|
if (win->wazooSwitch) (*win->wazooSwitch)(win,false);
|
|
}
|
|
|
|
if (hSave = (*hWazooRes)->kindList[idx].hSaveInfo)
|
|
{
|
|
SaveWazooPtr pSave = *hSave;
|
|
Boolean wasActive = win->isActive;
|
|
|
|
SetMyWindowPrivateData (win,pSave->winRefCon);
|
|
SetWindowKind(winWP,(*hWazooRes)->kindList[idx].kind);
|
|
SetWinFields(win, pSave->winData);
|
|
(*hWazooData)->current = idx;
|
|
if (embedder = GetEmbedder(hWazooData,idx,true)) {
|
|
// Make these controls visible
|
|
SetControlVisibility (embedder,true,false);
|
|
if (win->wazooSwitch) (*win->wazooSwitch)(win,true);
|
|
}
|
|
if (!quietly)
|
|
{
|
|
PCopy(title,(*hWazooRes)->kindList[idx].name);
|
|
SetWTitle(winWP, title);
|
|
if (win->pte)
|
|
// Reactivate any Pete text
|
|
PeteActivate(win->pte,true,true);
|
|
SetEmptyClipRgn(GetWindowPort(winWP));
|
|
MyWindowDidResize(win,nil);
|
|
if (wasActive != win->isActive)
|
|
// Make sure wazoo is activated/deactivated
|
|
ActivateMyWindow(winWP,wasActive);
|
|
InfiniteClip(GetWindowPort(winWP)); // Restore clipping region
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/************************************************************************
|
|
* CloseAllButCurrent - close all wazoo windows except one
|
|
************************************************************************/
|
|
static Boolean CloseAllButCurrent(MyWindowPtr win,WazooDataHandle hWazooData,WazooResHandle hWazooRes)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
short i,current;
|
|
Boolean fSelect = false;
|
|
|
|
current = (*hWazooData)->current;
|
|
SaveCurrentWazoo(win, hWazooData, hWazooRes,false);
|
|
for(i=0;i<(*hWazooRes)->count;i++)
|
|
{
|
|
if (i != current)
|
|
{
|
|
if (RestoreWazooWindow(win,hWazooData,i,true))
|
|
{
|
|
if (MustSaveWazoo(win))
|
|
{
|
|
// These windows will put up a WannaSave dialog.
|
|
// Need to switch to them
|
|
RestoreWazooWindow(win,hWazooData,i,false);
|
|
UpdateMyWindow(winWP);
|
|
fSelect = true;
|
|
}
|
|
|
|
if (!CloseAWazoo(win,hWazooData,hWazooRes,i))
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Need to go back to the current
|
|
RestoreWazooWindow(win,hWazooData,current,!fSelect);
|
|
if (fSelect)
|
|
UpdateMyWindow(winWP);
|
|
|
|
return true;
|
|
}
|
|
|
|
/************************************************************************
|
|
* CloseAWazoo - close a wazoo window
|
|
************************************************************************/
|
|
static Boolean CloseAWazoo(MyWindowPtr win,WazooDataHandle hWazooData,WazooResHandle hWazooRes, short index)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
SaveWazooHandle hSaveInfo;
|
|
PETEHandle pte, nextPTE;
|
|
ControlHandle embedder;
|
|
|
|
SetEmptyClipRgn(GetWindowPort(winWP));
|
|
if (win->close && !(*win->close)(win)) return(false);
|
|
for (pte=win->pteList;pte;pte=nextPTE)
|
|
{
|
|
nextPTE = PeteNext(pte);
|
|
PeteDispose(win,pte);
|
|
}
|
|
|
|
hSaveInfo = (*hWazooRes)->kindList[index].hSaveInfo;
|
|
if (embedder = GetEmbedder(hWazooData,-1,false))
|
|
DisposeControl(embedder);
|
|
if (hSaveInfo)
|
|
{
|
|
|
|
ZapHandle(hSaveInfo);
|
|
(*hWazooRes)->kindList[index].hSaveInfo = nil;
|
|
}
|
|
(*hWazooData)->current = -1;
|
|
InfiniteClip(GetWindowPort(winWP)); // Restore clipping region
|
|
return true;
|
|
}
|
|
|
|
/************************************************************************
|
|
* MakeDragRegion - make drag region for wazoo tab
|
|
************************************************************************/
|
|
static RgnHandle MakeDragRegion(Rect *rTab,short tab,WazooDataHandle hWazooData)
|
|
{
|
|
RgnHandle dragRgn;
|
|
|
|
if (dragRgn = NewRgn())
|
|
{
|
|
GetControlRegion((*hWazooData)->hTabCtrl,tab+1,dragRgn);
|
|
GlobalizeRgn(dragRgn);
|
|
OutlineRgn(dragRgn,1);
|
|
}
|
|
return dragRgn;
|
|
}
|
|
|
|
/************************************************************************
|
|
* DragWazoo - drag a wazoo tab to: same wazoo, different wazoo, new wazoo
|
|
************************************************************************/
|
|
static void DragWazoo(MyWindowPtr win,Rect *rTab,Boolean *dontActivate,short tab)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr(win);
|
|
RgnHandle dragRgn;
|
|
DragReference drag;
|
|
Str255 sTitle;
|
|
// OSErr err;
|
|
// PromiseHFSFlavor promise;
|
|
|
|
SetMyCursor(arrowCursor); SFWTC = True;
|
|
|
|
if (!MyNewDrag(win,&drag))
|
|
{
|
|
if (!FinderDragVoodoo(drag)) // pacify the evil gods in finder-land
|
|
if (!(AddDragItemFlavor(drag,1,kWazooDragType,nil,0,flavorSenderOnly|flavorNotSaved)))
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
|
|
if (GetWazooData(win,&hWazooData,&hWazooRes) &&
|
|
SaveCurrentWazoo(win,hWazooData,hWazooRes,false))
|
|
{
|
|
Rect rWind,rPosition;
|
|
Boolean zoomed;
|
|
DECLARE_UPP(DrawDrag,DragDrawing);
|
|
DragOutlineInfo dragOutline;
|
|
|
|
INIT_UPP(DrawDrag,DragDrawing);
|
|
gDragData.winSrc = win;
|
|
gDragData.winDest = nil;
|
|
gDragData.tabIdx = (*hWazooData)->current;
|
|
gDragData.tabData = (*hWazooRes)->kindList[gDragData.tabIdx];
|
|
gDragData.tabData.hSaveInfo = nil; // Don't want saved wazoo info to transfer to another window
|
|
|
|
// Set up a drawing proc for drawing the drag outline
|
|
dragRgn = MakeDragRegion(rTab,tab,hWazooData);
|
|
gpDragOutline = &dragOutline;
|
|
dragOutline.a5 = SetCurrentA5();
|
|
|
|
// Get outline of window region
|
|
dragOutline.rgnWindow = NewRgn();
|
|
GetStructureRgnBounds(winWP,&rWind);
|
|
GetWTitle(winWP, sTitle);
|
|
if (RestorePosPrefs(sTitle,&rPosition,&zoomed))
|
|
{
|
|
rWind.right = rWind.left + (rPosition.right-rPosition.left);
|
|
rWind.bottom = rWind.top + (rPosition.bottom-rPosition.top);
|
|
}
|
|
RectRgn(dragOutline.rgnWindow, &rWind);
|
|
OutlineRgn(dragOutline.rgnWindow,1);
|
|
GetMouse(&dragOutline.lastMouse);
|
|
LocalToGlobal(&dragOutline.lastMouse);
|
|
OffsetRgn(dragOutline.rgnWindow,rTab->left-kTabLeftMargin,0); // Normalize region so tab appears in 1st position
|
|
dragOutline.mode = kDragInWazoo;
|
|
if (!HaveOSX())
|
|
// Apple engineering: "Drag drawing proc is not supported on X."
|
|
SetDragDrawingProc(drag, DrawDragUPP, (void*)&dragOutline);
|
|
|
|
// Do drag
|
|
gDontDragHilite = true;
|
|
MyTrackDrag(drag,&MainEvent,dragRgn);
|
|
gDontDragHilite = false;
|
|
DisposeRgn(dragOutline.rgnWindow);
|
|
|
|
if (gDragData.winDest != gDragData.winSrc)
|
|
{
|
|
short fromIdx = (*hWazooData)->current;
|
|
|
|
if (dontActivate) *dontActivate = True;
|
|
|
|
// Moved from original window
|
|
if (gDragData.winDest)
|
|
{
|
|
// Drag to a different window
|
|
// Do a soft close in old window
|
|
if (!CloseAWazoo(win,hWazooData,hWazooRes,fromIdx))
|
|
{
|
|
// The window won't close. Leave the tab in the source
|
|
// and remove it from the destination
|
|
WazooDataHandle hWazooDataDest;
|
|
WazooResHandle hWazooResDest;
|
|
|
|
RemoveTab(gDragData.winDest,gDragData.tabIdx);
|
|
GetWazooData(gDragData.winDest,&hWazooDataDest,&hWazooResDest);
|
|
SetupTabs(hWazooDataDest,hWazooResDest,true);
|
|
}
|
|
else
|
|
{
|
|
// Remove from old window
|
|
if ((*hWazooRes)->count<2)
|
|
{
|
|
// No tabs left in window. Get rid of the window
|
|
DisposeWazoo(hWazooData,hWazooRes);
|
|
win->close = nil; // Don't call close proc
|
|
win->position = nil;
|
|
win->wazooData = nil;
|
|
CloseMyWindow(winWP);
|
|
}
|
|
else
|
|
{
|
|
SelectWazoo(win,fromIdx ? 0 : 1); // Select first tab in source window
|
|
RemoveTab(win,fromIdx);
|
|
SetupTabs(hWazooData,hWazooRes,true);
|
|
UpdateMyWindow(winWP);
|
|
}
|
|
|
|
// Select tab in new window
|
|
SelectWazooWithUpdate(gDragData.winDest,gDragData.tabIdx);
|
|
}
|
|
|
|
CheckMinWinSize(gDragData.winDest, gDragData.tabData.minSize);
|
|
}
|
|
else
|
|
{
|
|
Point mouse;
|
|
Rect rMenuBar;
|
|
|
|
// Drag to nowhere.
|
|
GetDragMouse(drag, &mouse, nil);
|
|
|
|
// Don't move if drag to menu bar
|
|
rMenuBar = (*GetMainDevice())->gdRect;
|
|
rMenuBar.bottom = rMenuBar.top + GetMBarHeight();
|
|
if (!PtInRect(mouse,&rMenuBar))
|
|
{
|
|
|
|
gForceHPos = mouse.h - 24; // Position new window
|
|
gForceVPos = mouse.v - 14;
|
|
if ((*hWazooRes)->count > 1)
|
|
{
|
|
// Still got at least one left.
|
|
// Drag out to new window
|
|
// Need to soft close first
|
|
short kind;
|
|
|
|
kind = (*hWazooRes)->kindList[fromIdx].kind;
|
|
if (CloseAWazoo(win,hWazooData,hWazooRes,fromIdx))
|
|
{
|
|
SelectWazoo(win,fromIdx ? 0 : 1); // Select first tab in source window
|
|
RemoveTab(win,fromIdx); // Remove tab from source window
|
|
SetupTabs(hWazooData,hWazooRes,true);
|
|
UpdateMyWindow(winWP);
|
|
|
|
// Create new window
|
|
gForceNewWazoo = true;
|
|
OpenWazoo(kind);
|
|
gForceNewWazoo = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Drag single tab out of any window. Just move this window
|
|
Rect oldContR = win->contR;
|
|
Rect r;
|
|
long sysVers;
|
|
|
|
GetPortBounds(GetWindowPort(winWP),&r);
|
|
r.right = r.right-r.left+gForceHPos;
|
|
r.bottom = r.bottom-r.top+gForceVPos;
|
|
r.left = gForceHPos;
|
|
r.top = gForceVPos;
|
|
|
|
if ((!Gestalt(gestaltSystemVersion, &sysVers) && sysVers<0x0850) ||
|
|
// utl_CouldDrag doesn't work correctly with visible windows with OS < 8.5
|
|
utl_CouldDrag(winWP,&r,4,TitleBarHeight(winWP),LeftRimWidth(winWP)))
|
|
MoveWindow(winWP,r.left,r.top,False);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
gDragData.winSrc = nil;
|
|
DisposeDragRgn(dragRgn);
|
|
}
|
|
}
|
|
}
|
|
if (drag)
|
|
DisposeDrag(drag);
|
|
}
|
|
|
|
/************************************************************************
|
|
* RemoveTab - remove a tab from a window
|
|
************************************************************************/
|
|
static void RemoveTab(MyWindowPtr win,short tabIdx)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
|
|
if (GetWazooData(win,&hWazooData,&hWazooRes))
|
|
{
|
|
WazooItem *pKindList;
|
|
long len;
|
|
short count;
|
|
Boolean tabDisplayMode = (*hWazooData)->tabDisplayMode;
|
|
|
|
pKindList = (*hWazooRes)->kindList;
|
|
count = (*hWazooRes)->count-1;
|
|
if (len = sizeof(WazooItem)*(count - tabIdx))
|
|
// Move items after it
|
|
BMD(&pKindList[tabIdx+1],&pKindList[tabIdx],len);
|
|
SetHandleSize((Handle)hWazooRes,sizeof(WazooRes)+sizeof(WazooItem)*count);
|
|
(*hWazooRes)->count = count;
|
|
ChangedResource((Handle)hWazooRes);
|
|
if (len)
|
|
{
|
|
if (tabIdx <= (*hWazooData)->current)
|
|
(*hWazooData)->current--;
|
|
}
|
|
CheckTabResize(win,hWazooData,hWazooRes,tabDisplayMode);
|
|
CalcWazooMinSize(win);
|
|
|
|
// Redraw
|
|
Draw1Control((*hWazooData)->hTabCtrl);
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* DraggingWazoo - drag/receive handler if we are dragging a wazoo
|
|
************************************************************************/
|
|
Boolean DraggingWazoo(MyWindowPtr win,DragTrackingMessage message,DragReference drag,OSErr *err)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
Boolean result=false;
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
Boolean isWazooWindow;
|
|
Point pt;
|
|
short tab,lastTab;
|
|
|
|
*err = dragNotAcceptedErr;
|
|
isWazooWindow = GetWazooData(win,&hWazooData,&hWazooRes);
|
|
if (!gDragData.winSrc)
|
|
{
|
|
// Not dragging a wazoo tab
|
|
if (isWazooWindow)
|
|
{
|
|
// If we are over a wazoo tab, do a wazoo switch
|
|
SetPort_(GetWindowPort(winWP));
|
|
GetMouse(&pt);
|
|
if ((tab = PtInTab(win,pt))>=0 && tab != (*hWazooData)->current)
|
|
{
|
|
unsigned long waitTicks = TickCount()+GetRLong(DRAG_EXPAND_TICKS);
|
|
|
|
// Highlight tab then wait here a while
|
|
SetCurrentTab((*hWazooData)->hTabCtrl,tab);
|
|
lastTab = tab;
|
|
while(WaitMouseUp() && tab == lastTab && waitTicks > TickCount())
|
|
{
|
|
GetMouse(&pt);
|
|
lastTab = PtInTab(win,pt);
|
|
}
|
|
if (tab == lastTab)
|
|
{
|
|
SetupTabs(hWazooData,hWazooRes,true);
|
|
SelectWazoo(win,tab);
|
|
UpdateMyWindow(winWP);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Dragging a wazoo tab
|
|
if (isWazooWindow)
|
|
{
|
|
// Dragging a wazoo tab within a wazoo window
|
|
Rect rHilite;
|
|
WazooItem *pKindList;
|
|
short count;
|
|
GrafPtr savePort;
|
|
Boolean tabDisplayMode = (*hWazooData)->tabDisplayMode;
|
|
|
|
SetPort_(GetWindowPort(winWP));
|
|
|
|
switch (message)
|
|
{
|
|
case kDragTrackingEnterWindow:
|
|
rHilite = win->contR;
|
|
rHilite.top = 0;
|
|
if (!gDontDragHilite)
|
|
DoDragHilite(win, drag, &rHilite, true);
|
|
|
|
if (win == gDragData.winSrc)
|
|
{
|
|
// Going back into original window
|
|
gDragData.tabIdx = (*hWazooData)->current;
|
|
}
|
|
else
|
|
{
|
|
// Add the tab to the end if not original window
|
|
count = (*hWazooRes)->count+1;
|
|
SetHandleSize((Handle)hWazooRes,sizeof(WazooRes)+sizeof(WazooItem)*(count));
|
|
if (!MemError())
|
|
{
|
|
(*hWazooRes)->count = count;
|
|
gDragData.tabIdx = count-1;
|
|
(*hWazooRes)->kindList[gDragData.tabIdx] = gDragData.tabData;
|
|
ChangedResource((Handle)hWazooRes);
|
|
CalcWazooMinSize(win);
|
|
GetPort(&savePort);
|
|
SetPort_(GetWindowPort(winWP));
|
|
CheckTabResize(win,hWazooData,hWazooRes,tabDisplayMode);
|
|
SetupTabs(hWazooData,hWazooRes,true);
|
|
SetPort(savePort);
|
|
}
|
|
}
|
|
|
|
gpDragOutline->mode = kDragInWazoo;
|
|
break;
|
|
|
|
case kDragTrackingLeaveWindow:
|
|
if (!gDontDragHilite)
|
|
if (win) DoDragHilite(win, drag, nil, false);
|
|
else
|
|
gDontDragHilite = false; // Make sure we hilite next time coming into this window
|
|
|
|
// Remove the tab if not the original window
|
|
// Check for destination window since the drag manager does
|
|
// a dragTrackingLeaveWindow on the drop also
|
|
if (win && win != gDragData.winSrc && !gDragData.winDest)
|
|
{
|
|
RemoveTab(win,gDragData.tabIdx);
|
|
SetupTabs(hWazooData,hWazooRes,true);
|
|
}
|
|
gpDragOutline->mode = kDragOutsideWazoo;
|
|
break;
|
|
|
|
case kDragTrackingInWindow:
|
|
GetDragMouse(drag, &pt, nil);
|
|
GlobalToLocal(&pt);
|
|
if ((tab = PtInTab(win,pt))>=0)
|
|
{
|
|
if (tab != gDragData.tabIdx)
|
|
{
|
|
// Make sure that we are far enough into the other tab that after
|
|
// we switch, we won't immediately switch back
|
|
Rect rFrom,rTo;
|
|
short wdTo;
|
|
|
|
rFrom = (*hWazooData)->tabRect[gDragData.tabIdx];
|
|
rTo = (*hWazooData)->tabRect[tab];
|
|
wdTo = rTo.right - rTo.left;
|
|
|
|
if (gDragData.tabIdx < tab)
|
|
rFrom.right = rFrom.left + wdTo;
|
|
else
|
|
rFrom.left = rFrom.right - wdTo;
|
|
|
|
if (!PtInRect(pt, &rFrom))
|
|
{
|
|
|
|
// Reposition item in tabs
|
|
WazooItem tempWazooItem;
|
|
|
|
pKindList = (*hWazooRes)->kindList;
|
|
tempWazooItem = pKindList[gDragData.tabIdx];
|
|
pKindList[gDragData.tabIdx] = pKindList[tab];
|
|
pKindList[tab] = tempWazooItem;
|
|
if (gDragData.winSrc == win)
|
|
(*hWazooData)->current = tab;
|
|
else
|
|
{
|
|
// Make sure current tab stays the same
|
|
if (tab == (*hWazooData)->current)
|
|
(*hWazooData)->current = gDragData.tabIdx;
|
|
}
|
|
SetupTabs(hWazooData,hWazooRes,true);
|
|
ChangedResource((Handle)hWazooRes);
|
|
gDragData.tabIdx = tab;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0xfff:
|
|
// Drop
|
|
gDragData.winDest = win;
|
|
break;
|
|
}
|
|
}
|
|
result = true;
|
|
*err = noErr;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/************************************************************************
|
|
* DoDragHilite - show/hide drag hilite
|
|
************************************************************************/
|
|
// Need to change the background color of the window to match the
|
|
// color that is displayed
|
|
static void DoDragHilite(MyWindowPtr win, DragReference drag, Rect *rHilite, Boolean fShow)
|
|
{
|
|
RGBColor saveColor;
|
|
|
|
GetBackColor(&saveColor);
|
|
SetTabBackColor(win);
|
|
if (fShow)
|
|
ShowDragRectHilite(drag, rHilite, true);
|
|
else
|
|
HideDragHilite(drag);
|
|
RGBBackColor(&saveColor);
|
|
}
|
|
|
|
/************************************************************************
|
|
* CheckTabResize - see if the tabs need to be redrawn because of size change
|
|
************************************************************************/
|
|
static void CheckTabResize(MyWindowPtr win,WazooDataHandle hWazooData,WazooResHandle hWazooRes,short tabDisplayMode)
|
|
{
|
|
if (tabDisplayMode != (*hWazooData)->tabDisplayMode)
|
|
{
|
|
// Tab drawing mode has changed. Redraw.
|
|
Draw1Control((*hWazooData)->hTabCtrl);
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* SetWinFields - change or initialize window fields
|
|
************************************************************************/
|
|
static void SetWinFields(MyWindowPtr win, Ptr winData)
|
|
{
|
|
struct MyWindowStruct oldWin;
|
|
|
|
// Save fields
|
|
oldWin = *win;
|
|
|
|
if (winData)
|
|
BMD(winData,((Ptr)win)+kSaveDataOffset,kSaveDataSize);
|
|
else
|
|
// Init everything to zero
|
|
WriteZero(((Ptr)win)+kSaveDataOffset,kSaveDataSize);
|
|
|
|
//Restore a few fields
|
|
win->theWindow = oldWin.theWindow;
|
|
win->privateData = oldWin.privateData;
|
|
win->dialogRefcon = oldWin.dialogRefcon;
|
|
win->windowType = oldWin.windowType;
|
|
win->wazooData = oldWin.wazooData;
|
|
win->noUpdates = oldWin.noUpdates;
|
|
win->topMarginCntl = oldWin.topMarginCntl;
|
|
win->topMargin = oldWin.topMargin;
|
|
win->windex = oldWin.windex;
|
|
win->uselessHi = oldWin.uselessHi;
|
|
win->uselessWi = oldWin.uselessWi;
|
|
win->titleBarHi = oldWin.titleBarHi;
|
|
win->leftRimWi = oldWin.leftRimWi;
|
|
win->minSize = oldWin.minSize;
|
|
// win->isActive = oldWin.isActive;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* DisposeDragRgn - dispose of drag region
|
|
**********************************************************************/
|
|
static void DisposeDragRgn(RgnHandle rgn)
|
|
{
|
|
if (rgn)
|
|
DisposeRgn(rgn);
|
|
#if 0
|
|
if (gworld)
|
|
DisposeGWorld(gworld);
|
|
if (hDrawRgn)
|
|
DisposeRgn(hDrawRgn);
|
|
#endif
|
|
}
|
|
|
|
/**********************************************************************
|
|
* DrawDrag - drag drag region proc
|
|
**********************************************************************/
|
|
static pascal OSErr DrawDrag(DragRegionMessage message,
|
|
RgnHandle showRegion, Point showOrigin, RgnHandle hideRegion,
|
|
Point hideOrigin, void *dragDrawingRefCon, DragReference drag)
|
|
{
|
|
#pragma unused (showOrigin, hideOrigin)
|
|
Rect rClip;
|
|
DragOutlineInfo *pInfo;
|
|
RgnHandle paintRgn,tempRgn;
|
|
OSErr err = noErr;
|
|
Pattern gray;
|
|
|
|
pInfo = dragDrawingRefCon;
|
|
tempRgn = pInfo->tempRgn;
|
|
|
|
switch (message)
|
|
{
|
|
case kDragRegionBegin:
|
|
pInfo->tempRgn = NewRgn();
|
|
if (pInfo->saveClip = NewRgn())
|
|
GetClip(pInfo->saveClip); // Save wmgr clip region
|
|
pInfo->lastDrawMode = kDragInWazoo;
|
|
break;
|
|
|
|
case kDragRegionEnd:
|
|
DisposeRgn(tempRgn);
|
|
if (pInfo->saveClip)
|
|
{
|
|
SetClip(pInfo->saveClip);
|
|
DisposeRgn(pInfo->saveClip);
|
|
}
|
|
break;
|
|
|
|
case kDragRegionDraw:
|
|
case kDragRegionHide:
|
|
if (!tempRgn)
|
|
break;
|
|
SetRect(&rClip,-REAL_BIG,-REAL_BIG,REAL_BIG,REAL_BIG);
|
|
ClipRect(&rClip);
|
|
PenPat(GetQDGlobalsDarkGray(&gray)); // Need our gray pattern for XOR'ing
|
|
PenMode(notPatXor);
|
|
paintRgn = nil;
|
|
if (message==kDragRegionDraw)
|
|
{
|
|
if (pInfo->lastDrawMode == kDragOutsideWazoo)
|
|
{
|
|
// Hide window region
|
|
CopyRgn(pInfo->rgnWindow,tempRgn);
|
|
hideRegion = tempRgn;
|
|
}
|
|
if (pInfo->mode == kDragOutsideWazoo)
|
|
{
|
|
// Show window region
|
|
Point mouse;
|
|
|
|
GetDragMouse(drag, &mouse, nil);
|
|
OffsetRgn(pInfo->rgnWindow,mouse.h-pInfo->lastMouse.h,mouse.v-pInfo->lastMouse.v);
|
|
showRegion = pInfo->rgnWindow;
|
|
pInfo->lastMouse = mouse;
|
|
}
|
|
if (pInfo->lastDrawMode == kDragHid)
|
|
paintRgn = showRegion; // Nothing to hide
|
|
else
|
|
{
|
|
XorRgn(showRegion, hideRegion, tempRgn);
|
|
paintRgn = tempRgn;
|
|
}
|
|
pInfo->lastDrawMode = pInfo->mode;
|
|
}
|
|
else
|
|
{
|
|
// Hide region
|
|
if (pInfo->lastDrawMode == kDragInWazoo)
|
|
{
|
|
paintRgn = hideRegion;
|
|
}
|
|
else if (pInfo->lastDrawMode == kDragOutsideWazoo)
|
|
{
|
|
paintRgn = pInfo->rgnWindow;
|
|
pInfo->lastDrawMode = kDragHid;
|
|
}
|
|
}
|
|
if (paintRgn) PaintRgn(paintRgn);
|
|
PenNormal();
|
|
break;
|
|
|
|
}
|
|
return err;
|
|
}
|
|
|
|
/************************************************************************
|
|
* SafeWazooControl - make sure this control will be properly hidden in a wazoo
|
|
************************************************************************/
|
|
void SafeWazooControl(MyWindowPtr win,ControlHandle ctl,short windowKind)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
|
|
if (GetWindowKind(GetMyWindowWindowPtr(win)) == windowKind)
|
|
return; // This window is the current wazoo window. It's already safe.
|
|
|
|
if (GetWazooData(win,&hWazooData,&hWazooRes))
|
|
{
|
|
short idx;
|
|
|
|
FindWazoo(windowKind,&idx);
|
|
// Embed the control in the embedder control
|
|
EmbedControl(ctl,GetEmbedder(hWazooData,idx,true));
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* DirtyWazoo - make this wazooable window dirty
|
|
************************************************************************/
|
|
void DirtyWazoo(MyWindowPtr win,short windowKind)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
struct MyWindowStruct tempWin;
|
|
|
|
if (GetWindowKind(GetMyWindowWindowPtr(win)) == windowKind)
|
|
win->isDirty = true; // This window is the current wazoo window. It's easy
|
|
else if (GetWazooData(win,&hWazooData,&hWazooRes))
|
|
{
|
|
// Need to change isDirty flag in saved wazoo data
|
|
short idx;
|
|
SaveWazooHandle hSave;
|
|
|
|
FindWazoo(windowKind,&idx);
|
|
if (hSave = (*hWazooRes)->kindList[idx].hSaveInfo)
|
|
{
|
|
// get saved window data
|
|
BMD((*hSave)->winData,((Ptr)&tempWin)+kSaveDataOffset,kSaveDataSize);
|
|
tempWin.isDirty = true;
|
|
// put save window data back
|
|
BMD(((Ptr)&tempWin)+kSaveDataOffset,(*hSave)->winData,kSaveDataSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* CalcWazooMinSize - set wazoo minimum size
|
|
************************************************************************/
|
|
static void CalcWazooMinSize(MyWindowPtr win)
|
|
{
|
|
short count;
|
|
Point minSize;
|
|
WazooItem *pItem;
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
|
|
if (GetWazooData(win,&hWazooData,&hWazooRes))
|
|
{
|
|
minSize.h = minSize.v = 0;
|
|
pItem = (*hWazooRes)->kindList;
|
|
for(count=(*hWazooRes)->count;count--;)
|
|
{
|
|
// Get maximum minimum size
|
|
if (minSize.h < pItem->minSize.h) minSize.h = pItem->minSize.h;
|
|
if (minSize.v < pItem->minSize.v+GetRLong(WAZOO_TOPMARGIN)) minSize.v = pItem->minSize.v+GetRLong(WAZOO_TOPMARGIN);
|
|
pItem++;
|
|
}
|
|
win->minSize = minSize;
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* SetWinMinSize - set window minimum size
|
|
************************************************************************/
|
|
void SetWinMinSize(MyWindowPtr win,short h,short v)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr(win);
|
|
Boolean initialSize = h<=0 || v<=0;
|
|
|
|
if (IsWazoo(winWP))
|
|
{
|
|
if (initialSize)
|
|
h = v = 0;
|
|
|
|
// Set min size for this window and update wazoo's min size
|
|
SetWazooMinSize(GetWindowKind(winWP),h,v);
|
|
}
|
|
else
|
|
{
|
|
// Not a wazoo
|
|
if (initialSize)
|
|
{
|
|
// Use current window size
|
|
Rect r;
|
|
GetPortBounds(GetWindowPort(winWP),&r);
|
|
h = r.right-r.left;
|
|
v = r.bottom-r.top;
|
|
}
|
|
win->minSize.h = h;
|
|
win->minSize.v = v;
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* CheckMinWinSize - make sure the window isn't too small
|
|
************************************************************************/
|
|
static void CheckMinWinSize(MyWindowPtr win, Point minSize)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
Rect rWinSize;
|
|
Point winSize,origSize;
|
|
|
|
GetPortBounds(GetWindowPort(winWP),&rWinSize);
|
|
winSize.h = rWinSize.right-rWinSize.left;
|
|
winSize.v = rWinSize.bottom-rWinSize.top;
|
|
origSize = winSize;
|
|
if (minSize.h > winSize.h) winSize.h = minSize.h;
|
|
if (minSize.v > winSize.v) winSize.v = minSize.v;
|
|
if (winSize.h != origSize.h || winSize.v != origSize.v)
|
|
{
|
|
Rect oldContR;
|
|
|
|
oldContR = win->contR;
|
|
SizeWindow(winWP,winSize.h,winSize.v,TRUE);
|
|
MyWindowDidResize(win,&oldContR);
|
|
UpdateMyWindow(winWP);
|
|
win->saveSize = True;
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* MustSaveWazoo - does this window need to be saved?
|
|
************************************************************************/
|
|
static Boolean MustSaveWazoo(MyWindowPtr win)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
return ((win->isDirty && GetWindowKind(winWP)==FILT_WIN) || (ABDirty (win) && GetWindowKind(winWP)==ALIAS_WIN));
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* IsWazooEmbedderCntl - is this control a wazoo embedder?
|
|
************************************************************************/
|
|
Boolean IsWazooEmbedderCntl(ControlHandle cntl)
|
|
{
|
|
return GetControlReference(cntl)==kEmbedderId;
|
|
}
|
|
|
|
/************************************************************************
|
|
* IsWazooTabCntl - is this control the tab control?
|
|
************************************************************************/
|
|
Boolean IsWazooTabCntl(ControlHandle cntl)
|
|
{
|
|
return GetControlReference(cntl)==kTabsId;
|
|
}
|
|
|
|
/************************************************************************
|
|
* SetCurrentTab - set current tab in control
|
|
************************************************************************/
|
|
static void SetCurrentTab(ControlHandle ctl, short tab)
|
|
{
|
|
if (GetControlValue(ctl) != tab+1)
|
|
{
|
|
RgnHandle rgn = NewRgn();
|
|
|
|
if (rgn)
|
|
{
|
|
Rect r;
|
|
short saveBottom;
|
|
|
|
GetClip(rgn);
|
|
GetControlBounds(ctl,&r);
|
|
ClipRect(&r);
|
|
saveBottom = r.bottom;
|
|
r.bottom = 1000; // Avoid drawing line at bottom of tab
|
|
SetControlBounds(ctl,&r);
|
|
SetControlValue(ctl,tab+1);
|
|
r.bottom = saveBottom;
|
|
SetControlBounds(ctl,&r);
|
|
SetClip(rgn);
|
|
DisposeRgn(rgn);
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* SetupTabs - setup tab icons and names
|
|
************************************************************************/
|
|
static void SetupTabs(WazooDataHandle hWazooData,WazooResHandle hWazooRes,Boolean drawIt)
|
|
{
|
|
ControlHandle ctl = (*hWazooData)->hTabCtrl;
|
|
ControlTabInfoRec tabInfo;
|
|
short tabIdx;
|
|
ControlFontStyleRec fontStyle;
|
|
Rect rCtl;
|
|
CGrafPtr port = GetMyWindowCGrafPtr((*hWazooData)->win);
|
|
RgnHandle clipRgn = SavePortClipRegion(port);
|
|
Rect rPort;
|
|
|
|
GetControlBounds(ctl,&rCtl);
|
|
SetPort(port);
|
|
ClipRect(&rCtl); // Don't want to redraw the whole window
|
|
// SetControlMaximum(ctl,(*hWazooRes)->count>1?(*hWazooRes)->count:2);
|
|
SetControlMaximum(ctl,(*hWazooRes)->count);
|
|
RestorePortClipRegion(port,clipRgn);
|
|
tabInfo.version = 0;
|
|
|
|
fontStyle.flags = kControlUseFontMask+kControlUseSizeMask+kControlUseFaceMask;
|
|
fontStyle.font = SmallSysFontID();
|
|
fontStyle.size = SmallSysFontSize();
|
|
fontStyle.style = bold;
|
|
SetControlData(ctl,0,kControlFontStyleTag,sizeof(fontStyle),(Ptr)&fontStyle);
|
|
|
|
// Put names on tabs
|
|
for(tabIdx=0;tabIdx<(*hWazooRes)->count;tabIdx++)
|
|
{
|
|
PCopy(tabInfo.name,(*hWazooRes)->kindList[tabIdx].name);
|
|
tabInfo.iconSuiteID = Names2Icon(tabInfo.name,"\p");
|
|
SetControlData(ctl,tabIdx+1,kControlTabInfoTag,sizeof(ControlTabInfoRec),(Ptr)&tabInfo);
|
|
}
|
|
|
|
|
|
// Determine which tab mode fits in the window
|
|
CalcTabRects(hWazooData,hWazooRes);
|
|
|
|
(*hWazooData)->tabDisplayMode = kIconsAndNames;
|
|
GetPortBounds(port,&rPort);
|
|
|
|
// Too wide?
|
|
if ((*hWazooData)->tabRect[(*hWazooRes)->count-1].right > rPort.right)
|
|
{
|
|
// Try condensed style
|
|
fontStyle.style = condense;
|
|
SetControlData(ctl,0,kControlFontStyleTag,sizeof(fontStyle),(Ptr)&fontStyle);
|
|
(*hWazooData)->tabDisplayMode = kCondensedNames;
|
|
|
|
CalcTabRects(hWazooData,hWazooRes);
|
|
|
|
// Still too wide?
|
|
if ((*hWazooData)->tabRect[(*hWazooRes)->count-1].right > rPort.right)
|
|
{
|
|
// Take off names
|
|
for(tabIdx=0;tabIdx<(*hWazooRes)->count;tabIdx++)
|
|
{
|
|
PCopy(tabInfo.name,(*hWazooRes)->kindList[tabIdx].name);
|
|
tabInfo.iconSuiteID = Names2Icon(tabInfo.name,"\p");
|
|
*tabInfo.name = 0;
|
|
SetControlData(ctl,tabIdx+1,kControlTabInfoTag,sizeof(ControlTabInfoRec),(Ptr)&tabInfo);
|
|
}
|
|
(*hWazooData)->tabDisplayMode = kIconsOnly;
|
|
|
|
CalcTabRects(hWazooData,hWazooRes);
|
|
}
|
|
}
|
|
|
|
SetCurrentTab(ctl,(*hWazooData)->current);
|
|
|
|
if (HaveTheDiseaseCalledOSX())
|
|
{
|
|
// bugs in the Jaguar control manager, if you ask me...
|
|
(*hWazooData)->win->topMargin += 20;
|
|
InvalTopMargin((*hWazooData)->win);
|
|
(*hWazooData)->win->topMargin -= 20;
|
|
}
|
|
else if (drawIt)
|
|
{
|
|
Draw1Control((*hWazooData)->win->topMarginCntl);
|
|
Draw1Control((*hWazooData)->hTabCtrl);
|
|
}
|
|
else
|
|
{
|
|
Rect r;
|
|
GetControlBounds((*hWazooData)->hTabCtrl,&r);
|
|
InvalWindowRect(GetMyWindowWindowPtr((*hWazooData)->win),&r);
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* CalcTabRects - get bounds of each tab
|
|
************************************************************************/
|
|
static void CalcTabRects(WazooDataHandle hWazooData,WazooResHandle hWazooRes)
|
|
{
|
|
RgnHandle rgn;
|
|
short tab;
|
|
Rect rTab;
|
|
|
|
rgn = NewRgn();
|
|
for(tab=0;tab<(*hWazooRes)->count;tab++)
|
|
{
|
|
GetControlRegion((*hWazooData)->hTabCtrl,tab+1,rgn);
|
|
GetRegionBounds(rgn,&rTab);
|
|
(*hWazooData)->tabRect[tab] = rTab;
|
|
}
|
|
DisposeRgn(rgn);
|
|
}
|
|
|
|
/************************************************************************
|
|
* GetEmbedder - get embedder control for a wazoo
|
|
************************************************************************/
|
|
static ControlHandle GetEmbedder(WazooDataHandle hWazooData, short idx, Boolean create)
|
|
{
|
|
ControlHandle ctlEmbedder = nil;
|
|
WazooResHandle hWazooRes;
|
|
SaveWazooHandle hSaveInfo;
|
|
|
|
if (idx<0) idx = (*hWazooData)->current;
|
|
hWazooRes = (*hWazooData)->list;
|
|
if (hSaveInfo = (*hWazooRes)->kindList[idx].hSaveInfo)
|
|
ctlEmbedder = (*hSaveInfo)->ctlEmbedder;
|
|
if (!ctlEmbedder && create)
|
|
{
|
|
ctlEmbedder = EmbedTheControls((*hWazooData)->win,nil);
|
|
if (!hSaveInfo)
|
|
{
|
|
hSaveInfo = NuHandleClear(sizeof(SaveWazooData));
|
|
(*hWazooRes)->kindList[idx].hSaveInfo = hSaveInfo;
|
|
}
|
|
if (hSaveInfo)
|
|
(*hSaveInfo)->ctlEmbedder = ctlEmbedder;
|
|
}
|
|
return ctlEmbedder;
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* EmbedInWazoo - embed control in wazoo embedder.
|
|
* Need to do this for OS X, otherwise may not be able to click
|
|
* on control
|
|
************************************************************************/
|
|
void EmbedInWazoo(ControlRef cntl,WindowPtr winWP)
|
|
{
|
|
WazooDataHandle hWazooData;
|
|
WazooResHandle hWazooRes;
|
|
SaveWazooHandle hSaveInfo;
|
|
ControlHandle ctlEmbedder;
|
|
MyWindowPtr win;
|
|
|
|
if (win=GetWindowMyWindowPtr(winWP))
|
|
if (GetWazooData(win,&hWazooData,&hWazooRes))
|
|
if (hSaveInfo = (*hWazooRes)->kindList[(*hWazooData)->current].hSaveInfo)
|
|
if (ctlEmbedder = (*hSaveInfo)->ctlEmbedder)
|
|
EmbedControl(cntl,ctlEmbedder);
|
|
} |