eudora-mac/toolbar.c

1 line
105 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. */
#define FILE_NUM 70
/* Copyright (c) 1994 by QUALCOMM Incorporated */
#include "toolbar.h"
#include "toolbarpopup.h"
#pragma segment Toolbar
typedef struct ButtonData
{
TBButtonEnum kind;
long select;
long modifiers;
Handle data;
ControlHandle cntl;
Str255 title;
Style style;
Boolean reinitBox;
short slots;
} ButtonData, *BDPtr, **BDHandle;
typedef struct TBGlobals
{
ToolbarVEnum varCode;
Boolean vertical;
short wi;
short hi;
short exCount;
short exPixels;
short space;
BDHandle bd;
//ControlHandle controls[2];
Rect strucRect;
uLong downTicks;
uLong dragTicks;
Boolean ignore;
DragReference oldDrag;
ControlHandle beingDragged;
Boolean droppedOnMe;
Boolean dragInteresting;
ControlHandle dragHilite;
ControlHandle lastCntl;
Boolean messageBeingDragged;
Boolean deleted;
Boolean forceEnable;
short n;
Boolean fKeys;
Rect tip;
ControlHandle tipCntl;
PortSaveStuff stuff;
uLong idleTicks;
uLong lastIdleRunTicks;
ControlRef taskProgButton;
ControlHandle searchUserPane;
ControlHandle searchGo;
ControlHandle searchEdit;
ControlHandle searchPopup;
PETEHandle searchPTE;
short searchItem;
StackHandle searchStack;
Rect screenRect;
} TBG, **TBGHandle;
typedef struct TBMenu
{
Boolean doingButton;
Boolean doingMenuSelect;
short menuId;
short item;
} TBMenu;
#ifdef DEBUG
TBGHandle TBGDB;
#endif
#define ForceEnable (*(TBGHandle)GetMyWindowPrivateData(Win))->forceEnable
#define VarCode (*(TBGHandle)GetMyWindowPrivateData(Win))->varCode
#define Deleted (*(TBGHandle)GetMyWindowPrivateData(Win))->deleted
#define Vertical (*(TBGHandle)GetMyWindowPrivateData(Win))->vertical
#define Controls (*(TBGHandle)GetMyWindowPrivateData(Win))->controls
#define Hi (*(TBGHandle)GetMyWindowPrivateData(Win))->hi
#define Space (*(TBGHandle)GetMyWindowPrivateData(Win))->space
#define Wi (*(TBGHandle)GetMyWindowPrivateData(Win))->wi
#define ExCount (*(TBGHandle)GetMyWindowPrivateData(Win))->exCount
#define ExPixels (*(TBGHandle)GetMyWindowPrivateData(Win))->exPixels
#define BD (*(TBGHandle)GetMyWindowPrivateData(Win))->bd
#define Dirty Win->isDirty
#define DroppedOnMe (*(TBGHandle)GetMyWindowPrivateData(Win))->droppedOnMe
#define StrucRect (*(TBGHandle)GetMyWindowPrivateData(Win))->strucRect
#define N (*(TBGHandle)GetMyWindowPrivateData(Win))->n
#define DownTicks (*(TBGHandle)GetMyWindowPrivateData(Win))->downTicks
#define DragTicks (*(TBGHandle)GetMyWindowPrivateData(Win))->dragTicks
#define Ignore (*(TBGHandle)GetMyWindowPrivateData(Win))->ignore
#define OldDrag (*(TBGHandle)GetMyWindowPrivateData(Win))->oldDrag
#define DragInteresting (*(TBGHandle)GetMyWindowPrivateData(Win))->dragInteresting
#define BeingDragged (*(TBGHandle)GetMyWindowPrivateData(Win))->beingDragged
#define DragHilite (*(TBGHandle)GetMyWindowPrivateData(Win))->dragHilite
#define LastCntl (*(TBGHandle)GetMyWindowPrivateData(Win))->lastCntl
#define TipCntl (*(TBGHandle)GetMyWindowPrivateData(Win))->tipCntl
#define FKeys (*(TBGHandle)GetMyWindowPrivateData(Win))->fKeys
#define MessageBeingDragged (*(TBGHandle)GetMyWindowPrivateData(Win))->messageBeingDragged
#define Tip (*(TBGHandle)GetMyWindowPrivateData(Win))->tip
#define ForceEnable (*(TBGHandle)GetMyWindowPrivateData(Win))->forceEnable
#define Stuff (*(TBGHandle)GetMyWindowPrivateData(Win))->stuff
#define IdleTicks (*(TBGHandle)GetMyWindowPrivateData(Win))->idleTicks
#define LastIdleRunTicks (*(TBGHandle)GetMyWindowPrivateData(Win))->lastIdleRunTicks
#define TaskProgButton (*(TBGHandle)GetMyWindowPrivateData(Win))->taskProgButton
#define SearchUserPane (*(TBGHandle)GetMyWindowPrivateData(Win))->searchUserPane
#define SearchGo (*(TBGHandle)GetMyWindowPrivateData(Win))->searchGo
#define SearchEdit (*(TBGHandle)GetMyWindowPrivateData(Win))->searchEdit
#define SearchPopup (*(TBGHandle)GetMyWindowPrivateData(Win))->searchPopup
#define SearchPTE (*(TBGHandle)GetMyWindowPrivateData(Win))->searchPTE
#define SearchItem (*(TBGHandle)GetMyWindowPrivateData(Win))->searchItem
#define SearchStack (*(TBGHandle)GetMyWindowPrivateData(Win))->searchStack
#define ScreenRect (*(TBGHandle)GetMyWindowPrivateData(Win))->screenRect
void TBMonitorMonitor(void);
Boolean TBButtonInterested(ControlHandle theCtl);
long TBExtractMenu(BDPtr bd,short *mnu,short *item);
OSErr TBSetButtonType(ControlHandle button);
#define IsRecipMenu(m) (NEW_TO_HIER_MENU<=(m) && (m)<=INSERT_TO_HIER_MENU)
#define IsStationMenu(m) ((m)==REPLY_WITH_HIER_MENU || (m)==NEW_WITH_HIER_MENU)
#define ToolbarStrnID (HasFeature (featureCustomizeToolbar) ? ToolbarProStrn : ToolbarLightStrn)
#define TBAR_DRAG_FLAVOR 'TBAR'
#define TB_ALIAS_TYPE 'EuTA'
typedef struct
{
short id;
OSType type;
OSType creator;
} TBAliasData, *TBAliasPtr, **TBAliasHandle;
MyWindowPtr Win;
TBMenu gTBMenu;
#define HideControl(c) SetControlVisibility((c),false,false)
#define ShowControl(c) SetControlVisibility((c),true,false)
/**********************************************************************
* Prototypes
**********************************************************************/
void TBPlaceControls(Rect *screenRect,short *windowWide, short *windowHi);
OSErr TBNewButton(short which);
void ToolbarButton(MyWindowPtr win,ControlHandle button,long modifiers,short part);
OSErr LoadToolbarButton(short i);
void SizeToolbar(short max);
short Menu2Icon(short menu,short item,short modifiers);
short Key2Icon(short key,short modifiers);
Boolean ConfigureTBButton(short which);
void ToolClick(MyWindowPtr win, EventRecord *event);
void InstallButtonMenu(short i, short menu, short item,PStr itemText,short modifiers,void *data,long size);
void InstallButtonFile(short i, FSSpecPtr spec);
void InstallButtonKey(short i, long key,short modifiers);
Boolean ToolbarClose(MyWindowPtr win);
void SaveToolbar(void);
void FlipToolbar(void);
void ToolbarUpdate(MyWindowPtr win);
PStr ModifierNames(PStr string,short modifiers);
Boolean TBInterStice(Point pt,short *which);
void TBBalloon(ControlHandle cntl);
Boolean TBInstSpecialMenus(short menu,short item,short modifiers,PStr itemStr,PStr titleStr);
Boolean TBSpecialStr(short menu,PStr itemStr,short *item,short *modifiers);
Boolean TBMovedMenu(short *menu,PStr itemStr,short *item);
Boolean ToolControl(Point pt, MyWindowPtr win);
void TBButton2String(ButtonData *bd, PStr s);
void TBDelButton(ControlHandle cntl);
Boolean ToolDrag(ControlHandle theCtl, EventRecord *event);
OSErr TBDragHandler(MyWindowPtr win,DragTrackingMessage which,DragReference drag);
void TBDragHilite(DragReference drag,ControlHandle cntl);
OSErr TBDrop(DragReference drag, short which, Boolean replacing);
void InstallButtonSpec(short which, FSSpecPtr spec);
void TBZapButtonData(short which);
void InstallButtonAliasId(short which,short id,OSType type, OSType creator,PStr name);
void TBFileButton(BDPtr bdp);
OSErr LoadButtonString(short i,PStr s);
OSErr ToolbarMailbox(short which,FSSpecPtr spec);
OSErr TBMessageDrop(DragReference drag,short which);
Boolean TBIsMboxButton(ControlHandle theCtl);
Boolean TBIsNicknameButton(ControlHandle theCtl);
void TBTipLo(ControlHandle cntl);
void TBDrawTip(void);
Boolean ToolbarMenu(MyWindowPtr win, int menu, int item, short modifiers);
OSErr SetPrinterIcon(ControlHandle button);
OSErr SetNicknameIcon(ControlHandle button, PStr nickname);
#define TBTip(x) do{if (Win && TipCntl!=(x)) TBTipLo(x);}while(0)
void TBButtonClose(short which);
PStr TBGetCTitle(ControlHandle cntl,PStr title);
void TBSetCTitle(ControlHandle theCtl,PStr title);
void TBIdle(MyWindowPtr win);
void InstallButtonAd(short i,TBAdInfo *pAd);
void InstallButtonNickname (short i, PStr nickname);
Boolean TBRename (TBButtonEnum kind, PStr oldName, PStr newName);
short TBBoxishMenu(short which,FSSpecPtr spec,PStr s,short mnu,short itm);
OSErr TBReinitBox(short which);
void DeletingButton(BDPtr pBD);
void MessageDragPopup (ControlHandle button, Boolean vertical);
static void TaskProgAnimate(ControlRef control);
#define TB_RESTORE_STUFF do{LDRef((TBGHandle)GetMyWindowPrivateData(Win));SetPortStuff(&Stuff);UL((TBGHandle)GetMyWindowPrivateData(Win));}while(0);
#define TB_SAVE_STUFF do{LDRef((TBGHandle)GetMyWindowPrivateData(Win));DisposePortStuff(&Stuff);SavePortStuff(&Stuff);UL((TBGHandle)GetMyWindowPrivateData(Win));}while(0);
ControlHandle TBNewSearchEdit(WindowPtr winWP);
void TBSearchStart(PStr searchMe);
void TBSearchEmpty(void);
void TBSearchPopup(Point pt);
void TBSearchFocus(Boolean focus);
void TBDragPreProcess(PETEHandle pte,DragTrackingMessage message,DragReference drag);
void TBDragPostProcess(PETEHandle pte,DragTrackingMessage message,DragReference drag);
#pragma segment Toolbar
/**********************************************************************
* OpenToolbar - open the toolbar
**********************************************************************/
void OpenToolbar(void)
{
MyWindowPtr win;
WindowPtr winWP;
short i,n;
if (Win) {CloseMyWindow(GetMyWindowWindowPtr(Win)); Win=nil; return;}
win = GetNewMyWindowWithClass(TBAR_WIND,nil,nil,BehindModal,False,False,TBAR_WIN,PrefIsSet(PREF_TB_FLOATING) ? kFloatingWindowClass: kToolbarWindowClass);
winWP = GetMyWindowWindowPtr (win);
if (win)
{
Win = win;
SetMyWindowPrivateData(Win,(long)NewZH(TBG));
#ifdef DEBUG
TBGDB = (TBGHandle)GetMyWindowPrivateData(Win);
#endif
i = GetPrefLong(PREF_TB_VARIATION)+1;
VarCode = i;
if (PrefIsSet(PREF_TB_VERT)) Vertical = True; else Vertical = False;
SetPort_(GetWindowPort(winWP));
TextFont(SmallSysFontID());
TextSize(9);
MySetThemeWindowBackground(win,kThemeActiveUtilityWindowBackgroundBrush,False);
SetThemeTextColor(kThemeActiveWindowHeaderTextColor,RectDepth(&Win->contR),True);
TB_SAVE_STUFF;
n = CountStrn(ToolbarStrnID);
SizeToolbar(n);
for (i=1;i<=n;i++)
{
if (LoadToolbarButton(i)) break;
}
win->button = ToolbarButton;
win->click = ToolClick;
win->isRunt = True;
win->bgClick = ToolClick;
win->close = ToolbarClose;
win->update = ToolbarUpdate;
win->cursor = ToolbarCursor;
win->menu = ToolbarMenu;
win->dontControl = True;
win->dontActivate = True;
win->idle = TBIdle;
win->idleInterval = 60;
win->drag = HasFeature (featureCustomizeToolbar) ? TBDragHandler : nil;
win->position = PositionPrefsTitle;
win->dontDrawControls = True;
win->windowType = PrefIsSet(PREF_TB_FLOATING) ? kFloating : kDockable;
ShowMyWindow(winWP);
PositionDockedWindow(winWP);
// Because of the mini-dialog, we no longer do this
// Add web search
// if (!GetPrefBit(PREF_SEARCH_WEB_BITS,prefSearchWebTBButtonInstalled))
// TBAddMenuButton(FIND_HIER_MENU,FIND_SEARCH_WEB_ITEM,ComposeRString(GlobalTemp,SEARCH_NOTHING_FMT,SEARCH_FOR_WEB));
// Add any in-your-face plug-ins to the toolbar
ETLAddToToolbar();
GetStructureRgnBounds(winWP,&StrucRect);
ToolbarNudgeAll(true);
PositionDockedWindows();
}
}
/**********************************************************************
* TBIdle - idle loop for the toolbar
* Will ordinarily defer to other events, but if called with nil does not defer
**********************************************************************/
void TBIdle(MyWindowPtr win)
{
WindowPtr WinWP = GetMyWindowWindowPtr(Win); // Yeah, seems like these are the same... or are they?
WindowPtr winWP = GetMyWindowWindowPtr(win); // Safer for now to just treat them as different
ButtonData bd;
short mnu, item;
short i;
short lite;
Boolean fiddle = False;
Style style;
MenuHandle mh;
static uLong styleTicks;
Boolean reStyle;
ControlHandle cntl;
if (win && (FrontWindowNeedsUpdate(WinWP) || !IsWindowVisible(winWP)))
{
return; // if there's anything else to do or toolbar is invisible, go away
}
if (LastIdleRunTicks >= NonNullTicks) return; // nothing has happened lately; go away
LastIdleRunTicks = NonNullTicks;
if (!InBG)
{
SetPort_(GetMyWindowCGrafPtr(Win));
TB_RESTORE_STUFF;
TBMonitorMonitor();
if (reStyle = (TickCount()-styleTicks>90)) styleTicks = TickCount();
GetRootControl(WinWP,&cntl);
ActivateControl(cntl);
EnableMenuItems(False);
// clear labels
if (keyFocusedFloater==Win && Win->pte) PeteNoLabel(Win->pte,0,0xffffffff,0xff);
// Update buttons
for (i=0;i<N;i++)
{
if ((*BD)[i].reinitBox) TBReinitBox(i);
bd = (*BD)[i];
if (bd.kind==tbkMenu)
{
if (TBExtractMenu(&bd,&mnu,&item))
{
if (reStyle && (mh=GetMHandle(mnu)))
{
GetItemStyle(mh,item,&style);
if (bd.style != style)
{
(*BD)[i].style = style;
SetBevelStyle(bd.cntl,style);
}
if (mnu==LABEL_HIER_MENU)
{
Str255 s;
MyGetItem(mh,item,s);
TBSetCTitle(bd.cntl,s);
}
#ifdef NEVER // unfortunately, doesn't work
GetItemColor(mnu,item,&color);
SetBevelColor(bd.cntl,&color);
#endif
}
if (mnu==MAILBOX_MENU || mnu==TRANSFER_MENU) item=1; //avoid looking at the separator bar, dummy.
mnu = MailboxKindaMenu(mnu,item,nil,nil);
if (mnu==MAILBOX_MENU || mnu==TRANSFER_MENU) item=1; //avoid looking at the separator bar, dummy.
if (mnu==FILE_MENU && item==FILE_QUIT_ITEM && HaveTheDiseaseCalledOSX())
{
// enable Quit anytime In is enabled
mnu=MAILBOX_MENU;
item=1;
}
lite = !ModalWindow&&(ForceEnable||IsEnabled(mnu,item))?0:255;
}
}
else
lite = ModalWindow||NoMenus ? 255 : 0;
if (GetControlHilite(bd.cntl)!=lite)
{
HiliteControl(bd.cntl,lite);
if (Space<0 && lite==255)
{
fiddle = True;
if (i>0 && GetControlHilite((*BD)[i-1].cntl)!=255)
Draw1Control((*BD)[i-1].cntl);
}
else fiddle = False;
}
else
{
if (fiddle && GetControlHilite(bd.cntl)!=255)
Draw1Control(bd.cntl);
fiddle = False;
}
}
}
}
/**********************************************************************
* TBMonitorMonitor - watch the monitor and see if it changes
**********************************************************************/
void TBMonitorMonitor(void)
{
Rect screenRect;
GDHandle junk;
short i = GetPrefLong(PREF_NW_DEV);
Boolean hasMB;
if (i)
{
utl_GetIndGD(i,&junk,&screenRect,&hasMB);
if (hasMB) screenRect.top += GetMBarHeight();
}
else
{
GetQDGlobalsScreenBitsBounds(&screenRect);
screenRect.top += GetMBarHeight();
}
if (!AboutSameRect(&screenRect,&ScreenRect)) SizeToolbar(N);
}
/**********************************************************************
* TBReinitBox - read the mailbox back out of a toolbar button
**********************************************************************/
OSErr TBReinitBox(short which)
{
// Yowza. We be changin' it
short mnu = (((*BD)[which].select)>>16)&0xffff;
short item;
Str63 s;
FSSpec spec;
Boolean xfer = mnu==TRANSFER_MENU;
if (!ToolbarMailbox(which+1,&spec))
if (!Spec2Menu(&spec,xfer,&mnu,&item))
{
*s = 0;
if (xfer) GetRString(s,TRANSFER_PREFIX);
PSCat(s,spec.name);
mnu = TBBoxishMenu(which,&spec,s,mnu,item);
InstallButtonMenu(GetControlReference((*BD)[which].cntl),mnu,0,s,0,&spec,sizeof(FSSpec));
Dirty = true;
}
(*BD)[which].reinitBox = false;
return noErr;
}
/**********************************************************************
* TBForceIdle - force the toolbar through an idle loop
**********************************************************************/
void TBForceIdle(void)
{
if (Win) LastIdleRunTicks = 0;
}
/**********************************************************************
*
**********************************************************************/
Boolean TBButtonInterested(ControlHandle theCtl)
{
Str255 sTitle;
GetControlTitle(theCtl,sTitle);
return (!MessageBeingDragged && !*sTitle ||
MessageBeingDragged && (TBIsMboxButton(theCtl)||TBIsNicknameButton(theCtl))); // Don't drag onto ads
}
/**********************************************************************
*
**********************************************************************/
OSErr TBDragHandler(MyWindowPtr win,DragTrackingMessage which,DragReference drag)
{
#pragma unused(win)
WindowPtr WinWP = GetMyWindowWindowPtr(Win);
OSErr err=noErr;
Point mouse;
short stice;
Rect r;
RgnHandle rgn;
ControlHandle theCtl=nil;
if (drag!=OldDrag)
{
Boolean interesting = DragIsInteresting(drag,TBAR_DRAG_FLAVOR,flavorTypeHFS,flavorTypeDirectory,TOC_FLAVOR,MESS_FLAVOR,kMBDragType,kNickDragType,nil);
OldDrag = drag;
DragInteresting = interesting;
if (interesting && DragIsInteresting(drag,TOC_FLAVOR,MESS_FLAVOR,nil))
MessageBeingDragged = True;
else MessageBeingDragged = False;
}
if (!DragInteresting) return(dragNotAcceptedErr);
SetPort_(GetMyWindowCGrafPtr(Win));
TB_RESTORE_STUFF;
GetDragMouse(drag,&mouse,nil);
GlobalToLocal(&mouse);
switch (which)
{
case kDragTrackingInWindow:
if (!MessageBeingDragged && TBInterStice(mouse,&stice) && (rgn=NewRgn()))
{
if (DragHilite) TBDragHilite(drag,nil);
SetMyCursor(Vertical ? SPREAD_CURS_V : SPREAD_CURS);
if (Vertical)
InsetRect(&r,-10,3);
else
InsetRect(&r,3,-10);
RectRgn(rgn,&r);
ShowDragHilite(drag,rgn,True);
DisposeRgn(rgn);
}
else if (FindControl(mouse,WinWP,&theCtl) && theCtl!=TaskProgButton)
{
SetMyCursor(arrowCursor);
if (!TBButtonInterested(theCtl))
TBDragHilite(drag,nil);
else
TBDragHilite(drag,theCtl);
}
else TBDragHilite(drag,nil);
err = noErr;
break;
case kDragTrackingLeaveWindow:
SetMyCursor(arrowCursor);
TBDragHilite(drag,nil);
err = noErr;
break;
case 0xfff:
DroppedOnMe = True;
if (!DragInteresting) return(dragNotAcceptedErr);
if (TBInterStice(mouse,&stice))
{
err = TBDrop(drag,stice,False);
}
else if (FindControl(mouse,WinWP,&theCtl))
{
if (!TBButtonInterested(theCtl)) return(dragNotAcceptedErr);
err = TBDrop(drag,GetControlReference(theCtl),True);
}
else err = dragNotAcceptedErr;
break;
}
TBTip(theCtl);
return(err);
}
/**********************************************************************
* TBDrop - handle something dropped on the toolbar
**********************************************************************/
OSErr TBDrop(DragReference drag, short which, Boolean replacing)
{
short i, n;
OSErr err = noErr;
Boolean dirty = False;
Handle data = nil;
FSSpec spec;
Str255 string;
n = MyCountDragItems(drag);
TBDragHilite(drag,nil);
if (MessageBeingDragged)
{
TBMessageDrop(drag,which);
}
else
{
for (i=1;i<=n && !err; i++, which++)
{
if (!(err=MyGetDragItemData(drag,i,TBAR_DRAG_FLAVOR,&data)))
{
if (BeingDragged)
{
if (!replacing) {TBNewButton(which); which++;}
if (replacing && GetControlReference(BeingDragged)==which)
{
err = dragNotAcceptedErr;
}
else
{
DeletingButton(&(*BD)[which-1]);
PCopy(string,*data);
LoadButtonString(which,string);
}
}
else
{
if (!replacing) {TBNewButton(which); which++;}
else DeletingButton(&(*BD)[which-1]);
PCopy(string,*data);
LoadButtonString(which,string);
}
if (!err) Dirty = True;
}
else if (!(err=MyGetDragItemData(drag,i,flavorTypeHFS,&data)))
{
// File drag from Finder
if (!replacing) {TBNewButton(which);}
else { replacing = False; DeletingButton(&(*BD)[which-1]); which--;}
spec = (*(struct HFSFlavor**)data)->fileSpec;
InstallButtonSpec(which+1,&spec);
Dirty = True;
}
else if (!(err=MyGetDragItemData(drag,i,kMBDragType,&data)))
{
// Mailbox drag from Mailboxes window
MBDragPtr pDragData;
if (!replacing) {TBNewButton(which);}
else { replacing = False; DeletingButton(&(*BD)[which-1]); which--;}
pDragData = (MBDragPtr)*data;
InstallButtonMenu(which+1, MailboxKindaMenu(pDragData->menuID,pDragData->menuItem,pDragData->name,&pDragData->spec),0,pDragData->name,nil,&pDragData->spec,sizeof(FSSpec));
Dirty = True;
}
else if (!(err=MyGetDragItemData(drag,i,kNickDragType,&data)))
{
Str31 nickname;
Handle notes;
long offset;
short ab,
nick;
notes = nil;
offset = 0;
if (!GetNickFlavorDragData (data, &offset, &ab, &nick, nickname, nil, &notes)) {
if (!replacing) {TBNewButton(which);}
else { replacing = False; DeletingButton(&(*BD)[which-1]); which--;}
// Make the toolbar button link to this recipient in the "New Message To" menu
InstallButtonNickname (which + 1, nickname);
Dirty = True;
}
ZapHandle (notes);
}
ZapHandle(data);
}
}
return(err);
}
/**********************************************************************
* TBMessageDrop - Drop a message (or group of messages from a TOC) onto
* a toolbar button.
*
* If the drop is on a nickname button, the message(s)
* will be sent to the target nickname. Without any
* modifiers accompanying the drop, the action will be
* "forward to". By holding down some as of yet defined
* modifier the action is changed to "redirect to".
**********************************************************************/
OSErr TBMessageDrop(DragReference drag,short which)
{
FSSpec spec;
OSErr err;
FSSpec ***data;
err = noErr;
// Are we dropping the message onto a nickname?
if ((*BD)[which-1].kind == tbkNick) {
UHandle data=nil;
TOCHandle tocH = nil;
TextAddrHandle toWhom;
if (toWhom = NuHandle ((*BD)[which-1].title[0]))
BlockMoveData (&(*BD)[which-1].title[1], *toWhom, (*BD)[which-1].title[0]);
if (!(err=MyGetDragItemData(drag,1,MESS_FLAVOR,(void*)&data)))
{
tocH = (***(MessHandle**)data)->tocH;
}
else if (!(err=MyGetDragItemData(drag,1,TOC_FLAVOR,(void*)&data)))
tocH = **(TOCHandle**) data;
// Make sure the toolbar popup is closed if we're tracking
CloseToolbarPopup ();
if (tocH)
DoIterativeThingy (tocH, PrefIsSet (PREF_REDIRECT_MSG_DROPS_ON_TB_NICKS) ? MESSAGE_REDISTRIBUTE_ITEM : MESSAGE_FORWARD_ITEM, CurrentModifiers (), toWhom);
ZapHandle(data);
ZapHandle(toWhom);
}
else {
// tell the dragger where the destination is and let it do the work
if (!(err=ToolbarMailbox(which,&spec)))
if (!(err=MyGetDragItemData(drag,1,'euXX',(void*)&data)))
{
***data = spec;
}
}
return(err);
}
/**********************************************************************
*
**********************************************************************/
Boolean TBIsMboxButton(ControlHandle theCtl)
{
ButtonData bd = (*BD)[GetControlReference(theCtl)-1];
long mnu;
if (bd.kind!=tbkMenu) return(False);
mnu = (bd.select>>16)&0xffff;
return ((mnu==MAILBOX_MENU || mnu==TRANSFER_MENU) && bd.data);
}
/**********************************************************************
* TellToolMBRename - make sure we know that a mailbox is being renamed
**********************************************************************/
OSErr TellToolMBRename(FSSpecPtr spec,FSSpecPtr newSpec,Boolean folder,Boolean will,Boolean dontWarn)
{
short i;
Boolean isIMAPMailbox = IsIMAPCacheFolder(newSpec);
if (ToolbarShowing() && !will)
{
for (i=0;i<N;i++)
{
if (TBIsMboxButton((*BD)[i].cntl))
{
FSSpec buttonSpec;
if (!ToolbarMailbox(i+1,&buttonSpec))
{
if (isIMAPMailbox)
{
FSSpec scratch;
// IMAP mailbox cache _files_ are stored in the toolbar buttonSpec.
Zero(scratch);
ParentSpec(&buttonSpec, &scratch);
buttonSpec.parID = scratch.parID;
}
if (SameSpec(&buttonSpec,spec))
{
(*BD)[i].reinitBox = true;
**(FSSpecPtr*)(*BD)[i].data = *newSpec;
}
}
}
}
}
return noErr;
}
/**********************************************************************
*
**********************************************************************/
Boolean TBIsNicknameButton(ControlHandle theCtl)
{
return ((*BD)[GetControlReference(theCtl)-1].kind==tbkNick);
}
/**********************************************************************
*
**********************************************************************/
void TBSetCTitle(ControlHandle theCtl,PStr title)
{
PCopy((*BD)[GetControlReference(theCtl)-1].title,title);
if (VarHasName(VarCode)) MySetControlTitle(theCtl,title);
}
/**********************************************************************
*
**********************************************************************/
void InstallButtonSpec(short which, FSSpecPtr spec)
{
ButtonData bd;
AliasHandle alias;
FSSpec settings;
short id;
FInfo info;
TBZapButtonData(which);
bd = (*BD)[which-1];
bd.kind = tbkFile;
TBSetCTitle(bd.cntl,spec->name);
PCopy(bd.title,spec->name);
GetFileByRef(SettingsRefN,&settings);
if (NewAlias(&settings,spec,&alias)) return;
UseResFile(SettingsRefN);
id = MyUniqueID(TB_ALIAS_TYPE);
AddMyResource_(alias,TB_ALIAS_TYPE,id,"");
if (ResError())
{
ZapHandle(alias);
return;
}
MyUpdateResFile(SettingsRefN);
if (FSpIsItAFolder(spec)) info.fdType = 'fdrp';
else AFSpGetFInfo(spec,spec,&info);
if (bd.data = NuHandle(sizeof(TBAliasData)))
{
(*(TBAliasHandle)bd.data)->id = id;
(*(TBAliasHandle)bd.data)->type = info.fdType;
(*(TBAliasHandle)bd.data)->creator = info.fdCreator;
}
if (VarHasIcon(VarCode))
if (info.fdType=='fdrp')
SetBevelIcon(bd.cntl,kGenericFolderIconResource,nil,nil,nil);
else
SetBevelIcon(bd.cntl,0,info.fdType,info.fdCreator,nil);
(*BD)[which-1] = bd;
if (TaskProgButton==bd.cntl) TaskProgButton = nil;
}
/**********************************************************************
*
**********************************************************************/
void TBZapButtonData(short which)
{
RGBColor color;
Zero(color);
//if ((*BD)[which-1].kind == tbkFile && (*BD)[which-1].data)
//ZapSettingsResource(TB_ALIAS_TYPE,(*(TBAliasHandle)((*BD)[which-1].data))->id);
ZapHandle((*BD)[which-1].data);
if ((*BD)[which-1].cntl) SetBevelColor((*BD)[which-1].cntl,&color);
}
/**********************************************************************
*
**********************************************************************/
void TBButtonClose(short which)
{
if ((*BD)[which-1].cntl) KillBevelIcon((*BD)[which-1].cntl);
ZapHandle((*BD)[which-1].data);
}
/**********************************************************************
*
**********************************************************************/
void TBDragHilite(DragReference drag,ControlHandle cntl)
{
ControlHandle oldDragHilite = DragHilite;
Point mouse;
HideDragHilite(drag);
if (DragHilite && DragHilite!=BeingDragged && DragHilite!=cntl) {
SetControlValue(DragHilite,0);
// Don't close a toolbar popup if the mouse isin the window
GetDragMouse (drag, &mouse, nil);
if (!MouseInToolbarPopup (mouse, cntl ? false : true))
CloseToolbarPopup ();
}
if (cntl) SetControlValue(cntl,1);
DragHilite = cntl;
if (MessageBeingDragged)
if (cntl && (*BD)[GetControlReference(cntl) - 1].kind == tbkNick)
if (oldDragHilite != DragHilite && (!oldDragHilite || (oldDragHilite && (*BD)[GetControlReference(oldDragHilite) - 1].kind != tbkNick)))
DragTicks = TickCount ();
else
if (TickCount () > DragTicks + GetRLong (NICK_BUTTON_DRAG_TICKS))
MessageDragPopup (cntl, !Vertical);
}
/**********************************************************************
* ToolbarNudgeAll - nudge all windows
**********************************************************************/
void ToolbarNudgeAll(Boolean gently)
{
WindowPtr winWP;
MyWindowPtr win;
for (winWP=FrontWindow_();winWP;winWP=GetNextWindow(winWP)) {
win = GetWindowMyWindowPtr (winWP);
if (win!=Win) ToolbarNudge(win,gently);
}
}
/**********************************************************************
* ToolbarUpdate - update the toolbar; really just sets the bg color
**********************************************************************/
void ToolbarUpdate(MyWindowPtr win)
{
WindowPtr WinWP;
short i;
Str15 numStr;
ControlHandle cntl;
ControlHandle root;
Rect r, rr;
SAVE_STUFF;
TextFont(SmallSysFontID());
TextSize(9);
if (FKeys && PrefIsSet(PREF_SHOW_FKEYS))
{
short h,v;
short bh, bv;
bh = bv = 0;
TextSize(9);
TextFace(condense|italic);
if (ThereIsColor) SetForeGrey(k8Grey7);
for (i=0;i<N && i<15;i++)
{
ComposeRString(numStr,FKEY_FMT,i+1);
GetControlBounds((*BD)[i].cntl,&r);
rr = r;
if (Vertical)
{
h = r.right+INSET;
v = r.bottom-INSET;
}
else
{
h = r.left+INSET;
v = r.bottom+10;
}
MoveTo(h,v);
DrawString(numStr);
}
}
REST_STUFF;
PenNormal();
WinWP = GetMyWindowWindowPtr(Win);
GetRootControl(GetMyWindowWindowPtr(win),&root);
// Draw dimmed cntls first
for (cntl=GetControlList(WinWP);cntl;cntl=GetNextControl(cntl))
if (cntl!=root && !IsControlActive(cntl)) Draw1Control(cntl);
// Undimmed ones next
for (cntl=GetControlList(WinWP);cntl;cntl=GetNextControl(cntl))
if (cntl!=root && IsControlActive(cntl)) Draw1Control(cntl);
TBDrawTip();
}
/**********************************************************************
*
**********************************************************************/
void TBDrawTip(void)
{
Rect r=Tip;
if (TipCntl)
{
PortSaveStuff old;
Str255 title;
//Style style;
PushGWorld();
SetPort_(GetMyWindowCGrafPtr(Win));
SavePortStuff(&old);
TextSize(9);
TextFace(0);
EraseRect(&r);
TBGetCTitle(TipCntl,title);
MoveTo(Tip.left,Tip.bottom-2);
//if (!GetBevelStyle(TipCntl,&style)) TextFace(style); //seems to be bug in GetControlData for bevels; this isn't working correctly
DrawString(title);
SetPortStuff(&old);
DisposePortStuff(&old);
PopGWorld();
}
}
/**********************************************************************
*
**********************************************************************/
void TBTipLo(ControlHandle cntl)
{
Rect r = Tip,rCntl;
Str255 title;
// anything to do?
if (TipCntl==cntl) return;
if (r.bottom==0) return;
PushGWorld();
SetPort_(GetMyWindowCGrafPtr(Win));
TB_RESTORE_STUFF;
// clear the old one
if (r.left!=r.right)
{
EraseRect(&r);
InvalWindowRect(GetMyWindowWindowPtr(Win),&r);
r.left = r.right = 0;
}
// show the new one
TipCntl = nil;
if (cntl)
{
long controlRef = GetControlReference(cntl)-1;
if (0<=controlRef && controlRef<N)
{
TBGetCTitle(cntl,title);
if (*title)
{
GetControlBounds(cntl,&rCntl);
r.left = rCntl.left + INSET;
r.right = r.left + StringWidth(title) + 2;
r.top = rCntl.bottom;
r.bottom = r.top+12;
if (r.right>Win->contR.right) OffsetRect(&r,Win->contR.right-2-r.right,0);
r.right += 6;
Tip = r;
InvalWindowRect(GetMyWindowWindowPtr(Win),&r);
}
TipCntl = cntl;
}
}
UpdateMyWindow(GetMyWindowWindowPtr(Win));
PopGWorld();
}
/**********************************************************************
*
**********************************************************************/
PStr TBGetCTitle(ControlHandle cntl,PStr title)
{
Str31 menuStr;
MenuHandle mh;
ButtonData bd = (*BD)[GetControlReference(cntl)-1];
short menu;
PCopy(title,bd.title);
if (bd.kind==tbkMenu)
{
menu = bd.select>>16;
if ((IsRecipMenu(menu) || IsStationMenu(menu)) && (mh=GetMHandle(bd.select>>16)))
{
GetMenuTitle(mh,menuStr);
PCatC(menuStr,' ');
PInsert(title,256,menuStr,title+1);
}
}
return(title);
}
/**********************************************************************
* TBInterStice - is a point (local coords) in a toolbar interstice?
**********************************************************************/
Boolean TBInterStice(Point pt,short *which)
{
short i;
Boolean found = false;
short slop = MAX(4,ExPixels/2);
short hSlop = Vertical ? 0 : slop;
short vSlop = Vertical ? slop : 0;
Rect rOuter,rInner;
for (i=0;i<N;i++)
{
GetControlBounds((*BD)[i].cntl,&rInner);
rOuter = rInner;
InsetRect(&rOuter,-hSlop,-vSlop);
InsetRect(&rInner,hSlop,vSlop);
if (PtInRect(pt,&rOuter) && !PtInRect(pt,&rInner))
{
if (Vertical && pt.v > (rOuter.bottom+rOuter.top)/2) i++;
if (!Vertical && pt.h > (rOuter.right+rOuter.left)/2) i++;
*which = i;
return true;
}
}
return(false);
}
/**********************************************************************
* ToolbarClose - deallocate memory
**********************************************************************/
Boolean ToolbarClose(MyWindowPtr win)
{
#pragma unused(win)
short i, n;
if (Dirty) SaveToolbar();
if (BD)
{
n = HandleCount(BD);
for (i=1;i<=n;i++) TBButtonClose(i);
}
DisposeHandle((Handle)GetMyWindowPrivateData(Win));
SetMyWindowPrivateData(Win,0);
Win = nil;
return(True);
}
/**********************************************************************
*
**********************************************************************/
void SaveToolbar(void)
{
Handle r = nil;
ButtonData bd;
Str255 s;
short i;
short n = HandleCount(BD);
UseResFile(SettingsRefN);
ZapSettingsResource('STR#',ToolbarStrnID);
if (r = NuHTempOK(2))
{
**(short**)r = 0;
AddMyResource(r,'STR#',ToolbarStrnID,"");
}
else return;
for (i=0;i<n;i++)
{
bd = (*BD)[i];
TBButton2String(&bd,s);
ChangeStrn(ToolbarStrnID,i+1,s);
}
Dirty = False;
}
/**********************************************************************
*
**********************************************************************/
void TBButton2String(ButtonData *bd, PStr s)
{
MenuHandle mh;
Str255 menuStr, itemStr;
TBAliasData tbd;
Str63 mods;
short menu, item;
short cookedMods;
FSSpec spec, junk;
Str255 title;
*s = 0;
switch(bd->kind)
{
case tbkMenu:
PCopy(title,bd->title);
// Save the entire pathname for mailboxes
TBExtractMenu(bd,&menu,&item);
if (IsMailboxChoice(menu,item) && menu!=MAILBOX_MENU && menu!=TRANSFER_MENU)
{
GetTransferParams(menu,item,&spec,nil);
// I don't understand why the following was done:
// if (IsIMAPMailboxFile(&spec)) spec.parID = SpecDirId(&spec);
// sd 3/10/03
// grab its full path name, unless we're dealing with a grafted mailbox.
if (!IsAlias(&spec,&junk)) Box2Path(&spec, title);
}
menu = (bd->select>>16)&0xffff;
item = (bd->select)&0xffff;
if (mh=GetMHandle(menu))
{
if (menu==LABEL_HIER_MENU)
NumToString(Menu2Label(item),itemStr);
else
PCopy(itemStr,title);
cookedMods = bd->modifiers;
if (menu==MESSAGE_MENU && item==MESSAGE_REPLY_ITEM) cookedMods &= ~optionKey;
ModifierNames(mods,cookedMods);
if (*itemStr > *mods && !CompareText(mods+1,itemStr+1,*mods,*mods,nil))
{
*itemStr -= *mods;
BMD(itemStr+1+*mods,itemStr+1,*itemStr);
}
GetMenuTitle(mh,menuStr);
ComposeRString(s,TB_FMT,bd->modifiers,TBButtonStrn+bd->kind,menuStr,itemStr);
}
break;
case tbkKey:
NumToString(bd->select,itemStr);
ComposeRString(s,TB_FMT,bd->modifiers,TBButtonStrn+bd->kind,itemStr,"");
break;
case tbkFile:
tbd = **(TBAliasHandle)bd->data;
NumToString(tbd.id,menuStr);
PCopy(itemStr,bd->title);
PCatC(itemStr,':');
*itemStr += 8;
BMD(&tbd.type,itemStr+*itemStr-7,4);
BMD(&tbd.creator,itemStr+*itemStr-3,4);
ComposeRString(s,TB_FMT,bd->modifiers,TBButtonStrn+bd->kind,menuStr,itemStr);
break;
case tbkAd:
NumToString(bd->select,itemStr);
ComposeRString(s,TB_FMT,bd->modifiers,TBButtonStrn+bd->kind,itemStr,bd->title);
break;
case tbkNick:
ComposeRString(s,TB_FMT,bd->modifiers,TBButtonStrn+bd->kind,bd->title,"");
break;
}
}
/**********************************************************************
* ToolClick - handle a click in the toolbar
**********************************************************************/
void ToolClick(MyWindowPtr win, EventRecord *event)
{
WindowPtr winWP = GetMyWindowWindowPtr(win);
Point pt = event->where;
short which;
Boolean did;
// Don't allow command clicks in light
if (!HasFeature (featureCustomizeToolbar) && event->modifiers&cmdKey)
return;
UseFeature (featureCustomizeToolbar);
SetPort_(GetMyWindowCGrafPtr(Win));
TB_RESTORE_STUFF;
GlobalToLocal(&pt);
LastIdleRunTicks = 0;
TBIdle(nil);
if (event->modifiers&cmdKey && TBInterStice(pt,&which))
{
while (WaitMouseUp()) {WNE(0,nil,0);}
GetMouse(&pt);
if (TBInterStice(pt,&which))
{
TBNewButton(which);
Deleted = false;
did = ConfigureTBButton(which+1);
if (!Deleted && !did)
TBDelButton((*BD)[which].cntl);
AuditHit((event->modifiers&shiftKey)!=0, (event->modifiers&controlKey)!=0, (event->modifiers&optionKey)!=0, (event->modifiers&cmdKey)!=0, false, GetWindowKind(winWP), AUDITCONTROLID(GetWindowKind(winWP),which), event->what);
}
}
else if ((event->modifiers&(cmdKey+optionKey))==cmdKey+optionKey)
{
// Drag toolbar
DragMyWindow(winWP,event->where);
}
else if (SearchPTE && PtInPETE(pt,SearchPTE))
{
// Focus in the search field if we haven't already
if (!Win->pte)
{
TBSearchFocus(true);
}
else
PeteEditWFocus (Win, SearchPTE, peeEvent, (void *) event, nil);
}
else
{
if (SearchPopup && PtInControl(pt,SearchPopup))
{
if (!(event->modifiers&cmdKey)) TBSearchPopup(pt);
}
else if (SearchGo && PtInControl(pt,SearchGo) && (event->modifiers&cmdKey))
;// ignore
else
{
if (event->modifiers&cmdKey)
{
ForceEnable = True;
LastIdleRunTicks = 0;
TBIdle(nil);
ForceEnable = False;
}
ToolControl(pt,Win);
}
}
}
Boolean ToolDrag(ControlHandle theCtl, EventRecord *event)
{
DragReference drag;
ButtonData bd;
Str255 s;
RgnHandle rgn;
Rect r;
Boolean result = False;
if (!Ignore && MyWaitMouseMoved(event->where,True))
{
Ignore = True;
/*
* allow the item to be dragged
*/
if (MyNewDrag(Win,&drag)) return(False);
/*
* the flavor is toolbar button
*/
bd = (*BD)[GetControlReference(theCtl)-1];
TBButton2String(&bd,s);
AddDragItemFlavor(drag, 1, TBAR_DRAG_FLAVOR, s, *s+1, 0);
BeingDragged = theCtl;
DroppedOnMe = False;
/*
* build the region
*/
if (rgn = NewRgn())
{
GetControlBounds(theCtl,&r);
RectRgn(rgn,&r);
InsetRect(&r,1,1);
RgnMinusRect(rgn,&r);
GlobalizeRgn(rgn);
GetRegionBounds(rgn,&r); SetDragItemBounds(drag, 1, &r);
if (!MyTrackDrag(drag,event,rgn))
{
/*
* drag accepted
*/
if (!(MainEvent.modifiers&optionKey) && !(CurrentModifiers()&optionKey))
result = (DroppedOnMe || DragTargetWasTrash(drag));
}
DisposeRgn(rgn);
}
MyDisposeDrag(drag);
BeingDragged = nil;
}
return(result);
}
/**********************************************************************
* ToolControl - handle controls in the toolbar
**********************************************************************/
Boolean ToolControl(Point pt, MyWindowPtr win)
{
WindowPtr winWP = GetMyWindowWindowPtr (win);
ControlHandle cntl;
short part;
EventRecord event;
Deleted = False;
if (part = FindControl(pt,winWP,&cntl))
{
DownTicks = TickCount();
Ignore = False;
event = MainEvent;
HiliteControl(cntl,1);
if (HasFeature (featureCustomizeToolbar) && event.modifiers&cmdKey && ToolDrag(cntl,&event))
{
UseFeature (featureCustomizeToolbar);
TBDelButton(cntl);
}
else
{
part = TrackControl(cntl,pt,nil);
HiliteControl(cntl,1);
if (!Ignore && part) (*win->button)(win,cntl,event.modifiers,part);
}
if (!Deleted) HiliteControl(cntl,0);
AuditHit((event.modifiers&shiftKey)!=0, (event.modifiers&controlKey)!=0, (event.modifiers&optionKey)!=0, (event.modifiers&cmdKey)!=0, false, GetWindowKind(winWP), AUDITCONTROLID(GetWindowKind(winWP),GetControlReference(cntl)), event.what);
return(True);
}
return(False);
}
/**********************************************************************
*
**********************************************************************/
OSErr TBNewButton(short which)
{
WindowPtr WinWP = GetMyWindowWindowPtr (Win);
ButtonData bd;
OSErr err;
short n = HandleCount(BD);
ControlHandle button = GetNewControl(TB_CNTL,WinWP);
short i;
Zero(bd);
if (!button) err = MemError();
else err=PtrPlusHand_(&bd,BD,sizeof(bd));
if (err) WarnUser(MEM_ERR,err);
else
{
TBSetButtonType(button);
for (i=n;i>which;i--) (*BD)[i] = (*BD)[i-1];
bd.cntl = button;
(*BD)[which] = bd;
Dirty = True;
if (button)
{
(*BD)[which].cntl = button;
for (i=0;i<=n;i++)
if ((*BD)[i].cntl) SetControlReference((*BD)[i].cntl,i+1);
SizeToolbar(n+1);
UpdateMyWindow(WinWP);
}
}
return(err);
}
/************************************************************************
* TBSetButtonType - set the appropriate uglification button type
************************************************************************/
OSErr TBSetButtonType(ControlHandle button)
{
ControlButtonContentInfo ci;
OSErr err;
// set font and size while we're at it
SetBevelFontSize(button,SmallSysFontID(),GetRLong(TB_BUTTON_FONT_SIZE));
// now set the type
Zero(ci);
ci.contentType = !VarHasIcon(VarCode) ? kControlContentTextOnly : kControlContentIconSuiteRes;
err = SetControlData(button,0,kControlBevelButtonContentTag,sizeof(ci),(void*)&ci);
ShowControl(button);
return(err);
}
/**********************************************************************
*
**********************************************************************/
void FlipToolbar(void)
{
VarCode++;
if (VarCode==tbvLimit)
{
VarCode = 1;
Vertical = !Vertical;
}
SizeToolbar(CountStrn(ToolbarStrnID));
UpdateMyWindow(GetMyWindowWindowPtr(Win));
ToolbarNudgeAll(true);
}
/**********************************************************************
* ToolbarRect - Rect of the toolbar
**********************************************************************/
void ToolbarRect(Rect *r)
{
if (Win)
{
*r = StrucRect;
if(!EmptyRect(r)) InsetRect(r,-1,-1);
}
else SetRect(r,-REAL_BIG,-REAL_BIG,-REAL_BIG,-REAL_BIG);
}
/**********************************************************************
* ToolbarNudge - nudge a window out of the way of any docked windows
**********************************************************************/
Boolean ToolbarNudge(MyWindowPtr win,Boolean gently)
{
WindowPtr winWP = GetMyWindowWindowPtr (win);
Rect newRect;
Point corner;
Boolean intersects;
#ifdef FLOAT_WIN
if (IsFloating(winWP)) return (false);
#endif //FLOAT_WIN
if (intersects=ToolbarNudgeRect(win, &newRect, gently))
{
SetPort_(GetWindowPort(winWP));
corner.h=newRect.left;
corner.v=newRect.top;
LocalToGlobal(&corner);
MoveWindow(winWP,corner.h,corner.v,False);
}
return(intersects);
}
/**********************************************************************
* ToolbarNudgeRect - nudge a rect out of the way of any docked windows
**********************************************************************/
Boolean ToolbarNudgeRect(MyWindowPtr win, Rect *newRect, Boolean gently)
{
WindowPtr winWP = GetMyWindowWindowPtr(win);
Rect bounds;
Rect intersect;
Rect winRect;
Point corner;
MyWindowPtr dockWin;
WindowPtr dockWinWP;
Boolean nudged = false;
Rect testRect;
GetStructureRgnBounds(winWP,&winRect);
// "Gently" means we'll only move windows whose title bars are completely covered
if (gently)
{
RgnHandle rgn = NewRgn();
if (rgn)
{
if (GetWindowRegion)
if (!GetWindowRegion(winWP,kWindowTitleBarRgn,rgn))
if (!EmptyRgn(rgn))
GetRegionBounds(rgn,&testRect);
DisposeRgn(rgn);
}
}
GetPortBounds(GetWindowPort(winWP),newRect);
for (dockWinWP=FrontWindow();dockWinWP;dockWinWP=GetNextWindow(dockWinWP))
{
dockWin = GetWindowMyWindowPtr (dockWinWP);
if (IsKnownWindowMyWindow(dockWinWP) && dockWin->windowType == kDockable && IsWindowVisible(dockWinWP))
{
GetStructureRgnBounds(dockWinWP,&bounds);
// For gentle motion, check for only completely covered title bars
if (gently)
{
SectRect(&bounds,&testRect,&intersect);
if (!AboutSameRect(&intersect,&testRect)) continue; // ignore
}
// Either title bar is covered, or we're being rough
if (SectRect(&bounds,&winRect,&intersect))
{
short overlapTop, overlapBottom, overlapLeft, overlapRight, overlapHi, overlapWi;
corner.h = corner.v = 0;
// The first order of business is to figure out exactly how we're overlapping
overlapBottom = intersect.top == bounds.top ? RectHi(intersect) : 0;
overlapTop = intersect.bottom == bounds.bottom ? RectHi(intersect) : 0;
overlapRight = intersect.left == bounds.left ? RectWi(intersect) : 0;
overlapLeft = intersect.right == bounds.right ? RectWi(intersect) : 0;
overlapHi = MAX(overlapTop,overlapBottom);
overlapWi = MAX(overlapLeft,overlapRight);
// We'll move the window the least we can
if (overlapHi && (!overlapWi || overlapHi < overlapWi))
{
if (overlapTop) corner.v = overlapTop;
else corner.v = - overlapBottom;
}
else if (overlapWi)
{
if (overlapLeft) corner.h = overlapLeft;
else corner.h = -overlapRight;
}
OffsetRect(newRect, corner.h, corner.v);
nudged = true;
}
}
}
return nudged;
}
/**********************************************************************
* ToolbarSect - does a rectangle overlap the toolbar?
**********************************************************************/
Boolean ToolbarSect(Rect *r)
{
Rect tb, sect;
if (Win)
{
ToolbarRect(&tb);
return (SectRect(&tb,r,&sect));
}
else return(False);
}
/**********************************************************************
* ToolbarReduce - reduce a rectangle to fit the toolbar
**********************************************************************/
void ToolbarReduce(Rect *r)
{
if (Win)
{
Rect tb;
ToolbarRect(&tb);
if (Vertical) r->left += RectWi(tb);
else r->top += RectHi(tb);
}
}
#pragma segment ToolbarMain
#ifdef TASK_PROGRESS_ON
/**********************************************************************
* ToolbarIdleControls
**********************************************************************/
void ToolbarIdleControls(void)
{
WindowPtr WinWP = GetMyWindowWindowPtr (Win);
if (WinWP && TaskProgButton && IsWindowVisible(WinWP) && TickCount()-IdleTicks>20)
{
PushGWorld();
SetPort_(GetWindowPort(WinWP));
TaskProgAnimate(TaskProgButton);
PopGWorld();
IdleTicks=TickCount();
}
}
/**********************************************************************
* ToolbarUserPaneIdle
**********************************************************************/
#define NUM_TP_ICONS (TASK_PROGRESS5_ICON - TASK_PROGRESS_ICON + 1)
static void TaskProgAnimate(ControlRef control)
{
short id;
static short frame=0;
static unsigned long lastTick=0;
if (NewError)
{
if (TickCount() - lastTick < 60)
return;
id = frame ? TASK_PROGRESS_ERROR_ICON : TASK_PROGRESS_ICON;
if (frame++)
frame=0;
}
else
{
// if (TickCount() - lastTick < 12)
// return;
if (!(CheckThreadRunning || SendThreadRunning))
{
if (frame == 1)
return;
}
id = TASK_PROGRESS_ICON + frame;
if (++frame >= (NUM_TP_ICONS - 1))
frame = 0;
}
lastTick = TickCount();
SetBevelIcon(control,id,0,0,nil);
}
/**********************************************************************
* IsTPIdleControlVisible
**********************************************************************/
Boolean IsTPIdleControlVisible(void)
{
return Win && VarHasIcon(VarCode) && TaskProgButton != nil;
}
#endif
/**********************************************************************
* ToolbarCursor - set the cursor for the toolbar
**********************************************************************/
void ToolbarCursor(Point mouse)
{
WindowPtr WinWP = GetMyWindowWindowPtr (Win);
ControlHandle cntl;
Rect r;
short which;
static long firstTicks;
LocalToGlobal(&mouse);
if (PtInRgn(mouse,MyGetWindowContentRegion(WinWP)))
{
PushGWorld();
SetPort_(GetWindowPort(WinWP));
TBIdle(nil);
GlobalToLocal(&mouse);
if (HasFeature (featureCustomizeToolbar) && CurrentModifiers()&cmdKey && TBInterStice(mouse,&which))
{
TBTip(nil);
SetMyCursor(Vertical ? SPREAD_CURS_V : SPREAD_CURS);
}
else if (PeteCursorList(Win->pteList,mouse))
;
else if (FindControl(mouse,WinWP,&cntl))
{
SetMyCursor(arrowCursor);
GetControlBounds(cntl,&r);
TBTip(cntl);
}
else
{
TBTip(nil);
SetRect(&r,mouse.h,mouse.v,mouse.h+1,mouse.v+1);
SetMyCursor(arrowCursor);
}
PopGWorld();
}
else
{
SetMyCursor(arrowCursor);
PushGWorld();
SetPort_(GetWindowPort(WinWP));
TBTip(nil);
PopGWorld();
}
}
/**********************************************************************
*
**********************************************************************/
void ShowToolbar(void)
{
WindowPtr WinWP = GetMyWindowWindowPtr (Win);
if (WinWP && !IsWindowVisible(WinWP))
{
//DebugStr("\pShowToolbar;sc");
TBIdle(nil);
ShowHide(WinWP,true);
StashStructure(Win);
GetStructureRgnBounds(WinWP,&StrucRect);
TBTip(nil);
}
}
void HideToolbar(void)
{
WindowPtr WinWP = GetMyWindowWindowPtr (Win);
if (WinWP && IsWindowVisible(WinWP))
{
//DebugStr("\pHideToolbar;sc");
StashStructure(Win);
ShowHide(WinWP,false);
//TBTip(nil);
}
}
void ToolbarBack(void)
{
// if (Win && GetNextWindow(GetMyWindowWindowPtr(Win)))
// SendBehind(GetMyWindowWindowPtr(Win),nil);
}
Boolean ToolbarShowing(void) {return(Win!=nil);}
/**********************************************************************
* TBEventFilter - filter events to see if the toolbar is interested
**********************************************************************/
Boolean TBEventFilter(EventRecord *event,Boolean oldResult)
{
if (Win)
{
OldDrag = (DragReference)-1;
if (!InBG)
if (event->what==activateEvt)
TBSearchFocus(false);
else if (event->what==mouseDown)
{
WindowPtr winWP;
short wPart = FindWindow_(event->where,&winWP);
MyWindowPtr win = GetWindowMyWindowPtr (winWP);
if (win && win!=Win) TBSearchFocus(false);
}
else
{
if (event->what==keyDown)
if (!(event->modifiers&cmdKey))
if (!ModalWindow)
if (!DragFxxkOff)
{
short b;
Byte k;
Byte c = event->message&charCodeMask;
if ((c==returnChar || c==enterChar) && Win->pte)
{
// hit return with focus in the search field
// start search
TBSearchStart(nil);
event->what = nullEvent;
}
else if (FKeys)
{
k = (event->message&keyCodeMask)>>8;
for (b=0;b<N && b<15;b++)
if (FunctionKeys[b]==k)
{
TBIdle(nil);
if (IsControlActive((*BD)[b].cntl))
{
HiliteControl((*BD)[b].cntl,1);
ToolbarButton(Win,(*BD)[b].cntl,event->modifiers,1);
HiliteControl((*BD)[b].cntl,0);
}
else SysBeep(20L);
event->what = nullEvent;
return(False);
}
}
}
}
}
return(oldResult);
}
/************************************************************************
* TBDisable - turn off the toolbar completely
************************************************************************/
void TBDisable(void)
{
WindowPtr WinWP = GetMyWindowWindowPtr (Win);
ControlHandle cntl;
if (ToolbarShowing())
{
PushGWorld();
SetPort_(GetWindowPort(WinWP));
GetRootControl(WinWP,&cntl);
DeactivateControl(cntl);
PopGWorld();
}
}
/**********************************************************************
*
**********************************************************************/
Boolean ToolbarMenu(MyWindowPtr win, int menu, int item, short modifiers)
{
#pragma unused(win,modifiers)
if (menu==FILE_MENU && item==FILE_SAVE_ITEM)
{
if (Dirty) SaveToolbar();
return(True);
}
else return(False);
}
#pragma segment Toolbar
/**********************************************************************
*
**********************************************************************/
void TBDelButton(ControlHandle cntl)
{
short which = GetControlReference(cntl);
short n = HandleCount(BD);
short i;
TBZapButtonData(which);
if (which<n)
{
BMD(&(*BD)[which],&(*BD)[which-1],sizeof(**BD)*(n-which));
for (i=which;i<n;i++) SetControlReference((*BD)[i-1].cntl,i);
}
SetHandleSize((Handle)BD,GetHandleSize((Handle)BD)-sizeof(**BD));
Dirty = True;
Deleted = True;
DisposeControl(cntl);
if (cntl == TaskProgButton)
TaskProgButton = nil;
SizeToolbar(n-1);
TipCntl = LastCntl = nil;
}
/**********************************************************************
* TBRemoveDefunctMenuButton - remove a button referring to a menu item
* we no longer have
**********************************************************************/
OSErr TBRemoveDefunctMenuButton(short menu,short item)
{
short i;
ButtonData bd;
for (i=0;i<N;i++)
{
bd = (*BD)[i];
if (bd.kind == tbkMenu && (bd.select>>16L)==menu && ((unsigned short)bd.select)==item)
{
TBDelButton(bd.cntl);
i--; //reexamine buttons
}
}
return noErr; /* nothing to return here */
}
/**********************************************************************
* TBRemoveDefunctNicknameButton - remove a button referring to a nickname
* we no longer have
**********************************************************************/
void TBRemoveDefunctNicknameButton(PStr nickname)
{
ButtonData bd;
short i;
if (Win)
for (i = 0;i < N; i++) {
bd = (*BD)[i];
if (bd.kind == tbkNick && StringSame (bd.title, nickname)) {
TBDelButton (bd.cntl);
i--; //reexamine buttons
}
}
}
/**********************************************************************
* LoadToolbarButton - load buttons in the toolbar
**********************************************************************/
OSErr LoadToolbarButton(short i)
{
Str255 s;
return(LoadButtonString(i,GetRString(s,ToolbarStrnID+i)));
}
/**********************************************************************
* LoadButtonString - load a string into a button
**********************************************************************/
OSErr LoadButtonString(short i,PStr s)
{
Str255 menuStr, itemStr;
Str31 pfix;
short menu, item;
UPtr spot;
FSSpec spec;
void *dataPtr = nil;
long size;
Boolean wasXfer;
short modifiers;
long key;
Boolean mailbox;
ControlHandle button = (*BD)[i-1].cntl;
OSType type, creator;
Str255 scratch;
if (button)
{
TBSetCTitle(button,"");
spot = s+1;
if (PToken(s,menuStr,&spot,":"))
{
StringToNum(menuStr,&key);
modifiers = key;
if (PToken(s,menuStr,&spot,":"))
{
TBButtonEnum buttonKind = FindSTRNIndex(TBButtonStrn,menuStr);
if (buttonKind==tbkMenu)
{
if (PToken(s,menuStr,&spot,":") &&
PToken(s,itemStr,&spot,"\377"))
{
if (menu=FindMenuByName(menuStr))
{
if (menu==FILE_MENU && HaveTheDiseaseCalledOSX() && EqualStrRes(itemStr,FILE_QUIT_ITEM_STR))
{
item = FILE_QUIT_ITEM;
}
else
{
SetMenuTexts(modifiers,True);
item = 0;
PCopy(scratch,itemStr);
PSCat(scratch,"\p<I");
if (mailbox = ((menu==MAILBOX_MENU||menu==TRANSFER_MENU) &&
!EqualStrRes(scratch,NEW_ITEM_TEXT) &&
!EqualStrRes(scratch,OTHER_ITEM_TEXT)))
{
if (wasXfer = (menu==TRANSFER_MENU))
{
menu==MAILBOX_MENU;
TrimPrefix(itemStr,GetRString(pfix,TRANSFER_PREFIX));
}
if (EqualStrRes(itemStr,FILE_ALIAS_IN)) GetRString(scratch,IN);
else if (EqualStrRes(itemStr,FILE_ALIAS_OUT)) GetRString(scratch,OUT);
else if (EqualStrRes(itemStr,FILE_ALIAS_JUNK)) GetRString(scratch,JUNK);
else if (EqualStrRes(itemStr,FILE_ALIAS_TRASH)) GetRString(scratch,TRASH);
else PCopy(scratch,itemStr);
if (!BoxSpecByName(&spec,scratch))
{
dataPtr = &spec;
size = sizeof(FSSpec);
// Display only the mailbox name in the toolbar.
Zero(scratch);
BMD(itemStr+1, scratch, itemStr[0]);
PathToMailboxName (scratch, itemStr, ':');
PCopy(scratch,itemStr);
if (wasXfer) PCopy(itemStr,pfix);
else *itemStr = 0;
PCat(itemStr,scratch);
}
else menu=0;
}
}
if (TBSpecialStr(menu,itemStr,&item,&modifiers) ||
TBMovedMenu(&menu,itemStr,&item) ||
GetMHandle(menu) && (mailbox || (item=FindItemByName(GetMHandle(menu),itemStr))))
{
InstallButtonMenu(i,menu,item,itemStr,modifiers,dataPtr,size);
}
}
}
}
else if (buttonKind==tbkKey)
{
if (PToken(s,menuStr,&spot,":"))
{
StringToNum(menuStr,&key);
InstallButtonKey(i,key,modifiers);
}
}
else if (buttonKind==tbkFile)
{
if (PToken(s,menuStr,&spot,":"))
if (PToken(s,itemStr,&spot,":"))
{
StringToNum(menuStr,&key);
BMD(spot,&type,4);
BMD(spot+4,&creator,4);
InstallButtonAliasId(i,key,type,creator,itemStr);
}
}
else if (buttonKind==tbkAd)
{
TBAdInfo adInfo;
if (PToken(s,menuStr,&spot,":"))
if (PToken(s,adInfo.title,&spot,":"))
{
adInfo.adId.server = modifiers;
StringToNum(menuStr,&adInfo.adId.ad);
adInfo.deleted = false;
adInfo.iconSuite = AdGetTBIcon(adInfo.adId);
InstallButtonAd(i,&adInfo);
}
}
else if (buttonKind==tbkNick)
{
if (PToken(s,menuStr,&spot,":"))
InstallButtonNickname(i, menuStr);
}
}
}
HiliteControl(button,255);
}
return(0);
}
/**********************************************************************
*
**********************************************************************/
void InstallButtonAliasId(short which,short id,OSType type,OSType creator,PStr name)
{
ButtonData bd;
TBAliasData tbd;
TBZapButtonData(which);
bd = (*BD)[which-1];
bd.kind = tbkFile;
bd.modifiers = 0;
tbd.id = id;
tbd.type = type;
tbd.creator = creator;
if (bd.data = NuHandle(sizeof(tbd)))
**(TBAliasHandle)bd.data = tbd;
if (VarHasIcon(VarCode))
if (type=='fdrp')
SetBevelIcon(bd.cntl,kGenericFolderIconResource,nil,nil,nil);
else
SetBevelIcon(bd.cntl,nil,type,creator,nil);
(*BD)[which-1] = bd;
TBSetCTitle(bd.cntl,name);
if (TaskProgButton==bd.cntl) TaskProgButton = nil;
}
/**********************************************************************
* TBSpecialStr - fix up some menu items that vary with preferences
**********************************************************************/
Boolean TBSpecialStr(short menu,PStr itemStr,short *item,short *modifiers)
{
Str63 searchWebStr;
if (menu==FILE_MENU && EqualStrRes(itemStr,CHECK_MAIL))
*item = FILE_CHECK_ITEM;
else if (menu==EDIT_MENU && EqualStrRes(itemStr,UNDO))
*item = EDIT_UNDO_ITEM;
else if (menu==FIND_HIER_MENU && StringSame(itemStr,ComposeRString(searchWebStr,SEARCH_NOTHING_FMT,SEARCH_FOR_WEB)))
*item = FIND_SEARCH_WEB_ITEM;
else if (menu==MESSAGE_MENU && (EqualStrRes(itemStr,REPLY)||EqualStrRes(itemStr,REPLY_ALL)))
{
*item = MESSAGE_REPLY_ITEM;
if ((0==EqualStrRes(itemStr,REPLY_ALL)) != (0==PrefIsSet(PREF_REPLY_ALL)))
*modifiers |= optionKey;
else
*modifiers &= ~optionKey;
}
else if (menu==MESSAGE_MENU &&
(EqualStrRes(itemStr,QUEUE_M_ITEM)||EqualStrRes(itemStr,SEND_M_ITEM)||
EqualStrRes(itemStr,OLD_QUEUE_M_ITEM)||EqualStrRes(itemStr,OLD_SEND_M_ITEM)))
{
*item = MESSAGE_QUEUE_ITEM;
if ((0==EqualStrRes(itemStr,SEND_M_ITEM)) != (0==PrefIsSet(PREF_AUTO_SEND)))
*modifiers |= optionKey;
else
*modifiers &= ~optionKey;
}
else if (menu==LABEL_HIER_MENU && AllDigits(itemStr+1,*itemStr) && *itemStr<3)
{
long label;
StringToNum(itemStr,&label);
*item = Label2Menu(label);
MyGetItem(GetMHandle(menu),*item,itemStr);
return true;
}
#ifdef IMAP
else if (menu==SERVER_HIER_MENU)
{
*item = FindSTRNIndex(ServerMenuStrnStrn,itemStr);
if (*item > ksvmLimit) *item -= ksvmLimit;
return (true); // leave itemStr set to be used on the button
}
#endif
else if (menu==TABLE_HIER_MENU)
;// no fixup needed
else return(False);
*itemStr = 0;
return(True);
}
/**********************************************************************
* TBMovedMenu - fix up some menu items that have moved since the last version
**********************************************************************/
Boolean TBMovedMenu(short *menu,PStr itemStr,short *item)
{
short winItems[] = { WIN_ALIASES_ITEM,WIN_PH_ITEM,WIN_FILTERS_ITEM,WIN_MAILBOX_ITEM };
short i;
Str32 s;
if (*menu==SPECIAL_MENU)
{
// Tool windows moved from Speical menu to Window menu
MenuHandle windowMenu = GetMHandle(WINDOW_MENU);
for (i=0;i<sizeof(winItems)/sizeof(short);i++)
{
if (StringSame(itemStr,MyGetItem(windowMenu,winItems[i],s)))
{
*menu = WINDOW_MENU;
*item = winItems[i];
return true;
}
}
}
return false;
}
/**********************************************************************
* ToolbarAddMenuButton - add a menu item to the end of the toolbar
**********************************************************************/
Boolean TBAddMenuButton(short menu,short item,PStr itemText)
{
short i;
short n;
ButtonData bd;
if (!Win) return false; // No toolbar!
// Make sure the item isn't already in the toolbar
n = N;
for (i=0;i<n;i++)
{
bd = (*BD)[i];
if (bd.kind == tbkMenu && (bd.select>>16L)==menu && ((unsigned short)bd.select)==item)
{
return false; // It's already there
}
}
// Create new button
if (!TBNewButton(n))
InstallButtonMenu(n+1,menu,item,itemText,0,nil,0);
return true; // Successfully added
}
/**********************************************************************
* TBAddAdButton - add an ad to the toolbar
**********************************************************************/
void TBAddAdButtons(TBAdHandle hTBAds)
{
short numAds,buttonIdx,i;
short n;
if (!Win) return; // No toolbar!
// Delete any ad buttons no longer in use
numAds = HandleCount(hTBAds);
for(buttonIdx=N-1;buttonIdx>=0;buttonIdx--)
{
BDPtr pBD = &(*BD)[buttonIdx];
if (pBD->kind == tbkAd)
{
Boolean found = false;
AdId adId;
adId.ad = pBD->select;
adId.server = pBD->modifiers;
for(i=0;i<numAds;i++)
{
if (SameAd(&(*hTBAds)[i].adId,&adId))
{
if (!(*hTBAds)[i].deleted)
{
found = true;
(*hTBAds)[i].deleted = true; // We don't want to ad it again
}
break;
}
}
if (!found)
TBDelButton(pBD->cntl);
}
}
// Install ad buttons
LDRef(hTBAds);
for(i=0;i<numAds;i++)
{
// Create new button
if (!(*hTBAds)[i].deleted && !TBNewButton(n=N))
InstallButtonAd(n+1,&(*hTBAds)[i]);
}
UL(hTBAds);
}
/**********************************************************************
* InstallButtonAd - put an ad in a button
**********************************************************************/
void InstallButtonAd(short i,TBAdInfo *pAd)
{
BDPtr pBD = &(*BD)[i-1];
ControlHandle button = (*BD)[i-1].cntl;
pBD->kind = tbkAd;
pBD->select = pAd->adId.ad;
pBD->modifiers = pAd->adId.server;
PCopy(pBD->title,pAd->title);
if (VarHasIcon(VarCode)) SetBevelIcon(pBD->cntl,0,0,0,pAd->iconSuite);
TBSetCTitle(button,pAd->title);
}
/**********************************************************************
* TBUpdateAdButtonIcon - need to redraw this button ad
**********************************************************************/
void TBUpdateAdButtonIcon(AdId setAdId,Handle iconSuite)
{
short i;
AdId adId;
if (Win)
{
for (i=0;i<N;i++)
{
BDPtr pBD = &(*BD)[i];
if (pBD->kind == tbkAd)
{
adId.ad = pBD->select;
adId.server = pBD->modifiers;
if (SameAd(&setAdId,&adId))
{
if (VarHasIcon(VarCode)) SetBevelIcon(pBD->cntl,0,0,0,iconSuite);
break;
}
}
}
}
}
/**********************************************************************
* InstallButtonNickname - put a nickname in a button
**********************************************************************/
void InstallButtonNickname (short i, PStr nickname)
{
ButtonData bd;
ControlHandle button = (*BD)[i-1].cntl;
button = (*BD)[i - 1].cntl;
Zero (bd);
bd.cntl = button;
bd.kind = tbkNick;
PCopy (bd.title, nickname);
(*BD)[i - 1] = bd;
if (VarHasIcon(VarCode))
SetNicknameIcon (button, nickname);
TBSetCTitle (button, nickname);
if (TaskProgButton==button) TaskProgButton = nil;
}
/**********************************************************************
* TBRename - rename a toolbar button of a particular kind
**********************************************************************/
Boolean TBRename (TBButtonEnum kind, PStr oldName, PStr newName)
{
ButtonData bd;
short i;
// Find the button with the old name
if (Win)
for (i = 0; i < N; ++i) {
bd = (*BD)[i];
if (bd.kind == kind && StringSame (bd.title, oldName)) {
PCopy (bd.title, newName);
(*BD)[i] = bd;
TBSetCTitle (bd.cntl, newName);
Dirty = True;
return (true);
}
}
return (false);
}
Boolean TBRenameNickButton (PStr oldName, PStr newName)
{
return (TBRename (tbkNick, oldName, newName));
}
/**********************************************************************
* InstallButtonMenu - put a menu choice in a button
**********************************************************************/
void InstallButtonMenu(short i, short menu, short item,PStr itemText,short modifiers,void *data,long size)
{
Handle dataH;
ControlHandle button = (*BD)[i-1].cntl;
Str255 itemStr;
Str255 titleStr;
ButtonData bd;
short id;
Boolean special=False;
MenuHandle mh;
Handle suite;
Byte type;
Zero(bd);
bd.select = (menu<<16L)|item;
bd.modifiers = modifiers;
bd.kind = tbkMenu;
bd.cntl = button;
TBZapButtonData(i);
if (menu==FIND_HIER_MENU && item==FIND_SEARCH_WEB_ITEM) SetPrefBit(PREF_SEARCH_WEB_BITS,prefSearchWebTBButtonInstalled);
if (data)
{
if (dataH = NuHandle(size)) BMD(data,*dataH,size);
bd.data = dataH;
}
if (mh=GetMHandle(menu))
{
if (!itemText || !*itemText)
{
if (!(special=TBInstSpecialMenus(menu,item,modifiers,itemStr,titleStr)))
MyGetItem(GetMHandle(menu),item,itemStr);
}
else PCopy(itemStr,itemText);
}
else *itemStr = 0;
if (IsRecipMenu(menu) || IsStationMenu(menu))
bd.data = NuDHTempOK(itemStr,*itemStr+1);
(*BD)[i-1] = bd;
if (!special) ModifierNames(titleStr,modifiers);
PSCat(titleStr,itemStr);
if (VarHasIcon(VarCode))
{
#ifdef TASK_PROGRESS_ON //
if (menu==WINDOW_MENU && item==WIN_TASKS_ITEM)
{
TaskProgButton = button;
}
else if (TaskProgButton==button)
{
TaskProgButton = nil;
}
#endif
if (menu==FILE_MENU && (item==FILE_PRINT_ITEM||item==FILE_PRINT_ONE_ITEM) && !SetPrinterIcon(button))
;
else if (menu==SCRIPTS_MENU)
{
FSSpec spec;
SInt32 gestaltResult;
IconRef iconRef;
SInt16 theLabel;
Boolean custIcon = false;
// Check for a custom icon. We need Icon Services to do this
if (!GetScriptFolderSpec(&spec))
if (!Gestalt(gestaltIconUtilitiesAttr,&gestaltResult) &&
(gestaltResult&gestaltIconUtilitiesHasIconServices) &&
GetIconRefFromFile)
{
GetMenuItemText(GetMHandle(menu),item,spec.name);
if (!GetIconRefFromFile(&spec,&iconRef,&theLabel))
{
SetBevelIconIconRef(bd.cntl,iconRef);
custIcon = true;
}
}
if (!custIcon)
SetBevelIcon(bd.cntl,nil,'osas','ToyS',nil);
}
/* I don't believe we really want to do this anymore since we now have true nickname buttons (jp)...
else if (menu == NEW_TO_HIER_MENU && !SetNicknameIcon(button, itemText))
; */
else if (suite = ETLMenu2Icon(menu,item))
{
SetBevelIcon(button,0,0,0,suite);
}
else if (menu==MESSAGE_MENU && item==MESSAGE_JUNK_ITEM)
{
SetBevelIcon(button,MAKE_JUNK_ICON,0,0,nil);
}
else if (menu==EMOTICON_HIER_MENU && !GetMenuItemIconHandle(GetMHandle(menu),item,&type,&suite) && suite)
{
Handle dupSuite;
DupIconSuite(suite,&dupSuite,false);
SetBevelIcon(button,0,0,0,dupSuite);
}
else
{
if (!(id = Names2Icon(itemStr,titleStr))) id = Menu2Icon(menu,item,modifiers);
SetBevelIcon(button,id,0,0,nil);
}
}
TBSetCTitle(button,titleStr);
}
/**********************************************************************
* SetPrinterIcon - put the current printer in a toolbar button icon
**********************************************************************/
OSErr SetPrinterIcon(ControlHandle button)
{
AliasHandle res = GetResource_('alis',-8192);
FSSpec spec;
Boolean changed;
OSErr err;
FInfo info;
if (!res) return(resNotFound);
Zero(spec);
if (!(err=ResolveAlias(nil,res,&spec,&changed)))
if (!(err=FSpGetFInfo(&spec,&info)))
{
KillBevelIcon(button);
SetBevelIcon(button,0,info.fdType,info.fdCreator,nil);
}
return(err);
}
/**********************************************************************
* SetNicknameIcon - put a nickname photo into a toolbar button icon
**********************************************************************/
OSErr SetNicknameIcon(ControlHandle button, PStr nickname)
{
FSSpec urlSpec;
Str255 tag;
Handle urlString;
OSErr theError;
IconRef iconRef;
SInt32 gestaltResult;
SInt16 theLabel;
long hashName;
short ab,
nick;
theError = resNotFound;
urlString = nil;
if (nickname) {
hashName = NickHash (nickname);
for (ab = 0; ab < NAliases; ++ab) {
nick = NickMatchFound(((*Aliases)[ab].theData), hashName, nickname, ab);
if (ValidNickname (nick))
break;
}
if (ValidNickname (nick))
if (urlString = GetTaggedFieldValue (ab, nick, GetRString (tag, ABReservedTagsStrn + abTagPicture))) {
theError = URLStringToSpec (urlString, &urlSpec);
if (!theError)
if (!Gestalt(gestaltIconUtilitiesAttr,&gestaltResult) && (gestaltResult&gestaltIconUtilitiesHasIconServices) && GetIconRefFromFile)
if (!GetIconRefFromFile (&urlSpec, &iconRef, &theLabel)) {
KillBevelIcon(button);
theError = SetBevelIconIconRef (button, iconRef);
}
}
}
// If an error occurs -- or if we're actually intending to assign a generic icon,
// assign a generic nickname icon
if (theError || !urlString)
SetBevelIcon (button, ValidNickname (nick) ? ABSetIcon (ab, nick) : NICKNAME_ICON, 0, 0, nil);
ZapHandle (urlString);
return (theError);
}
/**********************************************************************
* TBInstSpecialMenus - install special menus
**********************************************************************/
Boolean TBInstSpecialMenus(short menu,short item,short modifiers,PStr itemStr,PStr titleStr)
{
ModifierNames(titleStr,modifiers);
if (menu==FILE_MENU && item==FILE_CHECK_ITEM)
{
if (!(modifiers&optionKey)) GetRString(itemStr,CHECK_MAIL);
else return(false);
}
else if (menu==FILE_MENU && item==FILE_QUIT_ITEM && HaveTheDiseaseCalledOSX())
{
GetRString(itemStr,FILE_QUIT_ITEM_STR);
return true;
}
else if (menu==FIND_HIER_MENU && item==FIND_SEARCH_WEB_ITEM)
{
ComposeRString(itemStr,SEARCH_NOTHING_FMT,SEARCH_FOR_WEB);
return true;
}
else if (menu==EDIT_MENU && item==EDIT_UNDO_ITEM) GetRString(itemStr,UNDO);
//#ifdef NEVER
else if (menu==MESSAGE_MENU && item==MESSAGE_REPLY_ITEM)
{
ModifierNames(titleStr,modifiers&~optionKey);
if (modifiers & optionKey)
GetRString(itemStr,PrefIsSet(PREF_REPLY_ALL)?REPLY:REPLY_ALL);
else
GetRString(itemStr,PrefIsSet(PREF_REPLY_ALL)?REPLY_ALL:REPLY);
}
else if (menu==MESSAGE_MENU && item==MESSAGE_QUEUE_ITEM)
{
ModifierNames(titleStr,modifiers&~optionKey);
if (modifiers & optionKey)
GetRString(itemStr,PrefIsSet(PREF_AUTO_SEND)?QUEUE_M_ITEM:SEND_M_ITEM);
else
GetRString(itemStr,PrefIsSet(PREF_AUTO_SEND)?SEND_M_ITEM:QUEUE_M_ITEM);
}
//#endif
else return(False);
return(True);
}
/**********************************************************************
* ModifierNames - write out the names of the modifier keys
**********************************************************************/
PStr ModifierNames(PStr string,short modifiers)
{
*string = 0;
if (modifiers & shiftKey) PCatR(string,SHIFT_PLUS);
if (modifiers & optionKey) PCatR(string,OPTION_PLUS);
if (modifiers & cmdKey && HasFeature (featureCustomizeToolbar)) PCatR(string,COMMAND_PLUS);
if (modifiers & controlKey) PCatR(string,CONTROL_PLUS);
return(string);
}
/**********************************************************************
* InstallButtonKey - put a keystroke in a button
**********************************************************************/
void InstallButtonKey(short i, long key,short modifiers)
{
short id = Key2Icon(key,modifiers);
ControlHandle button = (*BD)[i-1].cntl;
Str255 itemStr;
Str63 modStr;
Str31 keyName;
short fmt = SPECIAL_KEY_FMT;
uShort smallKey;
(*BD)[i-1].select = key;
(*BD)[i-1].modifiers = modifiers;
(*BD)[i-1].kind = tbkKey;
TBZapButtonData(i);
if (VarHasIcon(VarCode)) SetBevelIcon(button,id,0,0,nil);
smallKey = key & 0xff;
if (smallKey<=' ')
{
GetRString(keyName,KeyNameStrn+(smallKey+1));
fmt = SPECIAL_KEY_FMT;
}
else
{
keyName[0] = 1;
keyName[1] = (UnadornKey(key,modifiers))&0xff;
fmt = KEY_FMT;
}
ComposeRString(itemStr,fmt,ModifierNames(modStr,modifiers),keyName);
TBSetCTitle(button,itemStr);
if (TaskProgButton==button) TaskProgButton = nil;
}
/**********************************************************************
* Key2Icon - find the right icon for a keystroke
**********************************************************************/
short Key2Icon(short key, short modifiers)
{
#pragma unused(key,modifiers)
return(KEY_ICON);
}
/**********************************************************************
* Menu2Icon - get the icon for a menu item
**********************************************************************/
short Menu2Icon(short menu,short item,short modifiers)
{
Handle r;
Str255 menuName;
Str63 modName;
MenuHandle mh;
short id;
RGBColor color;
if (menu==kHMHelpMenuID) menu = HELP_NOTMENU;
if (mh=GetMHandle(menu)) GetMenuTitle(mh,menuName);
if (id=Names2Icon(menuName,ModifierNames(modName,modifiers))) return(id);
SetResLoad(false);
r = GetResource('ICN#',menu*20+item);
SetResLoad(true);
if (r) return(menu*20+item);
SetResLoad(false);
r = GetResource('ICN#',menu*20);
SetResLoad(true);
if (r) return(menu*20);
switch(menu)
{
case MAILBOX_MENU:
return(MAILBOX_ICON);
break;
case HELP_NOTMENU: return(-16490);
#ifdef LABEL_ICONS
case LABEL_HIER_MENU:
if (item<=2) return(LABEL_SICN_TEMPLATE);
else if (item<=9) return(LABEL_SICN_BASE+item-3);
else return(LABEL_SICN_BASE+item-4);
break;
case COLOR_HIER_MENU:
id = TOOLBAR_COLOR_SICN_BASE+item;
if (item<=2) DEFAULT_COLOR(color);
else GetItemColor(menu,item,&color);
RefreshRGBIcon(id,&color,TOOLBAR_COLOR_SICN_TEMPLATE,nil);
return(id);
break;
#endif
default: return(MENU_ICON);
}
}
/**********************************************************************
* ToolbarMailbox - return the mailbox represented by a toolbar button
**********************************************************************/
OSErr ToolbarMailbox(short which,FSSpecPtr spec)
{
ButtonData bd;
short mnu;
bd = (*BD)[which-1];
if (bd.kind!=tbkMenu) return(fnfErr);
mnu = (bd.select>>16)&0xffff;
if ((mnu==MAILBOX_MENU || mnu==TRANSFER_MENU) && bd.data)
{
if (spec) *spec = **(FSSpecHandle)bd.data;
return(noErr);
}
return(fnfErr);
}
/**********************************************************************
* ToolbarButton - execute a button press in the toolbar
**********************************************************************/
void ToolbarButton(MyWindowPtr win,ControlHandle button,long modifiers,short part)
{
#pragma unused(win,part)
WindowPtr topWin = FrontWindow_();
short mnu, item;
long select;
EventRecord event;
short controlRef = GetControlReference(button)-1;
ButtonData bd;
Boolean hasBD;
Boolean swap;
AdId adId;
SetPort_(GetMyWindowCGrafPtr(Win));
TB_RESTORE_STUFF;
if (hasBD = (0<=controlRef && controlRef<N)) bd = (*BD)[controlRef];
if (!hasBD && modifiers&cmdKey) return; // punt if we try to customize something we can't
if (HasFeature (featureCustomizeToolbar) && modifiers&cmdKey)
{
UseFeature (featureCustomizeToolbar);
ConfigureTBButton(GetControlReference(button));
}
else if (button==SearchGo)
{
if (!(modifiers&cmdKey)) TBSearchStart(nil);
}
else if (hasBD)
{
modifiers |= bd.modifiers;
// hmmmmmmmmmmmmm. A few things check this rather than the
// modifiers passed in. I'm not sure this is a good idea,
// but I'm going to try it for now. SD 3/19/03
MainEvent.modifiers = modifiers;
switch(bd.kind)
{
case tbkMenu:
if (select = bd.select)
{
EnableMenuItems(False);
select = TBExtractMenu(&bd,&mnu,&item);
if (mnu==FILE_MENU && item==FILE_QUIT_ITEM)
PleaseQuit = true;
else if (IsEnabled(mnu,item))
{
if (DoWebFindWarning(mnu,item))
{
swap = (mnu==MESSAGE_MENU && item==MESSAGE_QUEUE_ITEM && (modifiers&optionKey));
if (swap) {TogglePref(PREF_AUTO_SEND);modifiers&=~optionKey;}
DoMenu(topWin,select,modifiers);
if (swap) TogglePref(PREF_AUTO_SEND);
}
}
else
SysBeep(20);
}
break;
case tbkKey:
Zero(event);
event.what = keyDown;
event.modifiers = modifiers;
event.message = bd.select;
event.when = TickCount();
HandleEvent(&event);
break;
case tbkFile:
TBFileButton(&bd);
break;
case tbkAd:
adId.ad = bd.select;
adId.server = bd.modifiers;
AdUserClick(adId);
break;
case tbkNick:
// A click on a nickname toolbar button should behave like a click in the recipient buttons of the address book
{
MyWindowPtr win = TopCompositionWindow (false, false);
GrafPtr oldPort;
MessHandle messH;
HeadSpec hs;
long start;
Boolean wantExpansion;
if (win && CompHeadFind (messH = Win2MessH(win), TO_HEAD, &hs)) {
wantExpansion = ((modifiers & optionKey) != 0);
if (HasFeature (featureNicknameWatching) && PrefIsSet (PREF_NICK_AUTO_EXPAND))
wantExpansion = true;
GetPort (&oldPort);
SetPort_ (GetMyWindowCGrafPtr (win));
PeteSelect (win, win->pte, hs.stop, hs.stop);
PetePrepareUndo (win->pte, peUndoPaste, -1, -1, &start, nil);
InsertCommaIfNeedBe (TheBody, &hs);
InsertAlias (win->pte, &hs, bd.title, wantExpansion, start, false);
ShowMyWindow (GetMyWindowWindowPtr (win));
UpdateSum (messH, SumOf(messH)->offset, SumOf(messH)->length);
SetPort_ (oldPort);
}
}
break;
default:
ConfigureTBButton(GetControlReference(button));
break;
}
}
}
/**********************************************************************
* TBExtractMenu - get menu stuff from a button
**********************************************************************/
long TBExtractMenu(BDPtr bd,short *mnu,short *item)
{
long select = bd->select;
Str255 itemStr;
FSSpec spec;
*mnu = (select>>16)&0xffff;
*item = select&0xffff;
if (IsRecipMenu(*mnu) || IsStationMenu(*mnu))
{
if (bd->data)
{
PCopy(itemStr,*bd->data);
if (*item=FindItemByName(GetMHandle(*mnu),itemStr))
select = (*mnu)<<16L | *item;
}
}
else if ((*mnu==MAILBOX_MENU || *mnu==TRANSFER_MENU) && *item!=MAILBOX_NEW_ITEM && *item!=MAILBOX_OTHER_ITEM)
{
spec = **(FSSpecHandle)bd->data;
Spec2Menu(&spec,*mnu==TRANSFER_MENU,mnu,item);
select = *mnu<<16L | *item;
}
return(select);
}
/**********************************************************************
*
**********************************************************************/
void TBFileButton(BDPtr bdp)
{
short id = (*(TBAliasHandle)bdp->data)->id;
AliasHandle res = GetResource_(TB_ALIAS_TYPE,id);
FSSpec settings, spec;
Boolean changed;
OSErr err;
Str255 name;
GetControlTitle(bdp->cntl,name);
if (res)
{
GetFileByRef(SettingsRefN,&settings);
err = ResolveAlias(&settings,res,&spec,&changed);
if (!err)
{
if (changed) ChangedResource((Handle)res);
OpenOtherDoc(&spec,False,false,nil);
}
else FileSystemError(TB_NO_FILE,name,err);
}
else
{
if (AlertStr(TBAR_REM_ALRT,Note,name)==OK)
TBDelButton(bdp->cntl);
}
}
/**********************************************************************
* ConfigureTBButton - configure a toolbar button
**********************************************************************/
Boolean ConfigureTBButton(short which)
{
WindowPtr theWindow;
DialogPtr dgPtr;
MyWindowPtr dgPtrWin;
EventRecord event;
Str255 s;
FSSpec spec;
ControlHandle button = (*BD)[which-1].cntl;
Boolean val = False;
TBTip(button);
TBTipLo(nil);
HiliteControl(button,1);
EnableMenus(nil,True);
EnableMenuItems(True);
DrawMenuBar();
SetMyCursor(arrowCursor); SFWTC = True;
// dgPtr = GetNewDialog(TBAR_MENU_DLOG,nil,InFront);
// DrawDialog(dgPtr);
dgPtrWin = GetNewMyDialog (TBAR_MENU_DLOG,nil,nil,InFront);
dgPtr = GetMyWindowDialogPtr (dgPtrWin);
if (!dgPtrWin || !dgPtr)
return (false);
SetPort_(GetWindowPort(GetDialogWindow(dgPtr)));
ActivateMyWindow(GetDialogWindow(dgPtr),true);
PushModalWindow(GetDialogWindow(dgPtr));
Zero(gTBMenu);
gTBMenu.doingButton = true;
/*
* now, let the user choose something:
*/
again:
FlushEvents(mDownMask|mUpMask|keyDownMask,0);
for (;!InBG;)
{
if (WNE(mDownMask|keyDownMask|updateMask,&event,REAL_BIG))
{
SetPort_(GetWindowPort(GetDialogWindow(dgPtr)));
if (event.what==updateEvt) MiniMainLoop(&event);
else if (gTBMenu.menuId)
break;
else if (event.what==mouseDown)
{
ControlHandle cntl;
short wPart = FindWindow_(event.where,&theWindow);
if (wPart==inMenuBar) break;
else if (wPart==inContent)
{
Point pt = event.where;
GlobalToLocal(&pt);
if (FindControl(pt,theWindow,&cntl)) break;
}
}
else if (event.what==keyDown)
break;
}
}
SetPort_(GetMyWindowCGrafPtr(Win));
if (gTBMenu.menuId) goto stupidApplicationMenuCrap;
if (((event.message&charCodeMask)=='.') && (event.modifiers&cmdKey) ||
((event.message&charCodeMask)==escChar) &&
(((event.message&keyCodeMask)>>8)==escKey)) event.what=nullEvent;
//Dprintf("\p%d %d.%d",event.what,event.where.h,event.where.v);
if (event.what==mouseDown)
{
switch(FindWindow_(event.where,&theWindow))
{
case inContent:
{
Point pt = event.where;
ControlHandle cntl, remove;
Rect r;
short junk;
SetPort_(GetWindowPort(GetDialogWindow(dgPtr)));
GlobalToLocal(&pt);
if (FindControl(pt,theWindow,&cntl))
{
if (!TrackControl(cntl,pt,nil))
if (!HaveTheDiseaseCalledOSX()) goto again; // Under Jaguar, this TrackControl
// fails the first time, for reasons
// I do not understand and do not currently
// have the patience to discover. The user who
// pulls the mouse of the button will just
// have to suffer SD 9/4/02
GetDialogItem(dgPtr,2,&junk,(void*)&remove,&r);
if (cntl==remove) //remove button
{
SetPort_(GetMyWindowCGrafPtr(Win));
DeletingButton(&(*BD)[GetControlReference(button)-1]);
TBDelButton(button);
Deleted = True;
}
}
break;
}
case inMenuBar:
{
long mSelect;
short mnu, itm;
SetMenuTexts(event.modifiers,True);
gTBMenu.doingMenuSelect = true;
gTBMenu.menuId = gTBMenu.item = 0;
mSelect = MenuSelect(event.where);
gTBMenu.doingMenuSelect = false;
stupidApplicationMenuCrap: if (gTBMenu.menuId)
{
// We received an AppleEvent indicating which
// menu item
mnu = gTBMenu.menuId;
itm = gTBMenu.item;
event.modifiers = CurrentModifiers()&~cmdKey;
}
else if (PleaseQuit)
{
mnu = FILE_MENU;
itm = FILE_QUIT_ITEM;
PleaseQuit = false;
}
else
{
mnu = (mSelect>>16)&0xffff;
itm = mSelect & 0xffff;
}
HiliteMenu(0);
if (!itm)
{
short menuItem;
// No item selected. See if it's an IMAP hybrid mailbox. Since
// it has a submenu, we have to call MenuChoice.
mSelect = MenuChoice();
mnu = (mSelect>>16)&0xffff;
menuItem = mSelect & 0xffff;
if (IsMailboxChoice(mnu,menuItem) && mnu!=MAILBOX_MENU && mnu!=TRANSFER_MENU)
{
short vRef;
long dirID;
MenuID2VD(mnu,&vRef,&dirID);
if (IsIMAPVD(vRef,dirID))
itm = menuItem; // IMAP hybrid mailbox
}
}
*spec.name = 0;
if (mnu&&itm)
{
MyGetItem(GetMHandle(mnu),itm,s);
if (IsMailboxChoice(mnu,itm))
mnu = TBBoxishMenu(which,&spec,s,mnu,itm);
if (mnu)
{
if (*spec.name)
InstallButtonMenu(GetControlReference(button),mnu,0,s,event.modifiers,&spec,sizeof(FSSpec));
else
InstallButtonMenu(GetControlReference(button),mnu,itm,nil,event.modifiers,nil,0);
Dirty = True;
val = True;
}
}
break;
}
}
}
else if (event.what==keyDown)
{
SetPort_(GetMyWindowCGrafPtr(Win));
InstallButtonKey(GetControlReference(button),event.message,event.modifiers);
Dirty = True;
val = True;
}
PopModalWindow();
TBTip(nil);
DisposeDialog_(dgPtr);
if (!Deleted) HiliteControl(button,0);
SFWTC = True;
Zero(gTBMenu);
return(val);
}
short TBBoxishMenu(short which,FSSpecPtr spec,PStr s,short mnu,short itm)
{
if ((mnu==MAILBOX_MENU || mnu==TRANSFER_MENU) && (itm==MAILBOX_NEW_ITEM ||itm==MAILBOX_OTHER_ITEM))
;
else if (!(mnu==MAILBOX_MENU || mnu==TRANSFER_MENU) &&
(itm==TRANSFER_NEW_ITEM-TRANSFER_BAR1_ITEM || itm==TRANSFER_OTHER_ITEM-TRANSFER_BAR1_ITEM))
{
Boolean doWarn = true;
if (itm==TRANSFER_OTHER_ITEM-TRANSFER_BAR1_ITEM)
{
// If IMAP mailbox, this is actually "This Mailbox", not "Other..."
short vRefNum;
long dirID;
MenuID2VD(mnu,&vRefNum,&dirID);
if (IsIMAPVD(vRefNum,dirID))
{
// IMAP. It's "This Mailbox"
mnu = MailboxKindaMenu(mnu,itm,s,spec);
if (*spec->name) PCopy(s,spec->name);
doWarn = false;
}
}
if (doWarn)
{
mnu = 0;
WarnUser(CANT_ADD_NESTED,0);
}
}
else
mnu = MailboxKindaMenu(mnu,itm,s,spec);
return mnu;
}
/**********************************************************************
* SizeToolbar - how big should the toobar be?
**********************************************************************/
void SizeToolbar(short max)
{
WindowPtr WinWP = GetMyWindowWindowPtr (Win);
Str63 s;
Str31 token;
UPtr spot;
long h, v;
short totalHi, totalWi;
ControlHandle button;
short i;
Boolean big = VarCode==tbvBig||VarCode==tbvBigName;
Rect screenRect;
GDHandle junk;
Boolean hasMB;
long exPixels, exCount, space;
i = GetPrefLong(PREF_NW_DEV);
if (i)
{
utl_GetIndGD(i,&junk,&screenRect,&hasMB);
if (hasMB) screenRect.top += GetMBarHeight();
}
else
{
GetQDGlobalsScreenBitsBounds(&screenRect);
screenRect.top += GetMBarHeight();
}
ScreenRect = screenRect;
/*
* convenient place to check this
*/
if (PrefIsSet(PREF_TB_FKEYS))
FKeys = True;
else
FKeys = False;
if (!max) max = 1;
/*
* anchored in UL corner
*/
if (!IsWindowVisible(WinWP)) MoveWindow(WinWP,screenRect.left+1,screenRect.top,False);
/*
* make sure we have enough selectors
*/
if (!BD)
{
button = (void*)NuHandleClear(max*sizeof(ButtonData));
BD = (void*)button;
}
else if ((i=HandleCount(BD))<max)
{
SetHandleBig((Handle)BD,max*sizeof(ButtonData));
if (!MemError())
{
LDRef(BD);
WriteZero(*BD+i,(max-i)*sizeof(ButtonData));
UL(BD);
}
}
/*
* make sure we have enough controls
*/
for (i=0;i<max;i++)
{
if (!(*BD)[i].cntl)
{
button = GetNewControl(TB_CNTL,WinWP);
if (button)
{
SetControlReference(button,i+1);
TBSetButtonType(button);
}
(*BD)[i].cntl = button;
}
}
/*
* Search control?
*/
if (!PrefIsSet(PREF_NO_TB_SEARCH))
{
if (!SearchUserPane)
{
StackHandle stack;
// make 'em
button = GetNewControl(TB_SEARCH_USER_CNTL,WinWP);
SearchUserPane = button;
button = GetNewControl(TB_SEARCH_GO_CNTL,WinWP);
SearchGo = button;
button = GetNewControl(TB_SEARCH_POPUP,WinWP);
SearchPopup = button;
button = TBNewSearchEdit(WinWP);
SearchEdit = button;
StackInit(sizeof(Str255),&stack);
if (!(SearchPopup && SearchGo && SearchEdit && stack))
{
// if we didn't get'em, kill 'em
ZapControl(SearchPopup);
ZapControl(SearchEdit);
ZapControl(SearchGo);
ZapControl(SearchUserPane);
ZapHandle(stack);
}
else
{
short id = SEARCH_WEB_ICON;
IconAlignmentType align = kAlignAbsoluteCenter;
// Panes and alignment and other rote crap
EmbedControl(SearchGo,SearchUserPane);
SetControlData(SearchGo,0,kControlIconResourceIDTag,sizeof(id),(void*)&id);
SetControlData(SearchGo,0,kControlIconAlignmentTag,sizeof(align),(void*)&align);
EmbedControl(SearchPopup,SearchUserPane);
TBSearchEmpty();
SearchStack = stack;
}
}
}
else if (SearchUserPane)
{
ZapControl(SearchUserPane);
TipCntl = nil;
}
/*
* figure cell sizes based on variation code
*/
GetRString(s,ToolbarSizesStrn+VarCode);
spot = s+1;
StringToNum(PToken(s,token,&spot,","),&h);
StringToNum(PToken(s,token,&spot,","),&v);
exCount = GetRLong(TOOLBAR_EXTRA_COUNT); if (!exCount) exCount = 1000;
exPixels = GetRLong(TOOLBAR_EXTRA_PIXELS);
space = GetRLong(TOOLBAR_SEP_PIXELS);
Hi = v;
Wi = h;
ExPixels = exPixels;
ExCount = exCount;
Space = space;
/*
* place them
*/
N = max;
TBPlaceControls(&screenRect, &totalWi, &totalHi);
if (!PrefIsSet(PREF_NO_TB_BALL) && !Vertical && (VarCode==tbvBig||VarCode==tbvSmall))
{
Tip.bottom = totalHi-1;
}
else Tip.bottom = 0;
Tip.top = Tip.bottom-10;
SizeWindow(WinWP,totalWi,totalHi,False);
GetPortBounds(GetWindowPort(WinWP),&Win->contR);
InvalContent(Win);
}
/**********************************************************************
*
**********************************************************************/
void GetButtonAlignment(ToolbarVEnum varCode, ControlButtonTextAlignment *alignment, ControlButtonTextPlacement *placement, short *textOffset, ControlButtonGraphicAlignment *gAlignment, Point *gOffset)
{
*textOffset = 0;
gOffset->h = gOffset->v = 0;
switch(varCode)
{
case tbvBigName: // big icons & names
*placement = kControlBevelButtonPlaceBelowGraphic;
*alignment = kControlBevelButtonAlignTextCenter;
*gAlignment = kControlBevelButtonAlignTop;
gOffset->v = 2;
break;
case tbvBig: // big icons
*placement = kControlBevelButtonPlaceToRightOfGraphic;
*alignment = kControlBevelButtonAlignTextFlushRight;
*gAlignment = kControlBevelButtonAlignCenter;
*textOffset = 500;
gOffset->v = 2;
break;
case tbvSmallName: // small icons & names
*placement = kControlBevelButtonPlaceToRightOfGraphic;
*alignment = kControlBevelButtonAlignTextFlushLeft;
*gAlignment = kControlBevelButtonAlignLeft;
gOffset->h = 2;
break;
case tbvSmall: // small icons only
*placement = kControlBevelButtonPlaceToRightOfGraphic;
*alignment = kControlBevelButtonAlignTextFlushRight;
*gAlignment = kControlBevelButtonAlignCenter;
*textOffset = 500;
break;
case tbvName: // text only
*placement = kControlBevelButtonPlaceBelowGraphic;
*alignment = kControlBevelButtonAlignTextCenter;
*gAlignment = kControlBevelButtonAlignTop;
break;
}
}
/**********************************************************************
*
**********************************************************************/
void TBPlaceControls(Rect *screenRect,short *windowWide, short *windowHi)
{
short i;
ControlHandle button;
ControlButtonTextPlacement placement;
ControlButtonTextAlignment alignment;
ControlButtonGraphicAlignment gAlignment;
short textOffset = 0;
Point gOffset = {0,0};
short h, v;
short wi, hi;
short vFactor = Vertical ? 1 : 0;
short hFactor = 1-vFactor;
short maxH = 0;
short maxV = 0;
short extraCount = 0;
short hWrap = RectWi(*screenRect)-GetRLong(TB_H_DESK_MARGIN);
short vWrap = RectHi(*screenRect)-GetRLong(TB_V_DESK_MARGIN);
short nextSlots;
short fKeyHi = 0;
short fKeyWi = 0;
short fKeyWiSave;
short tipHi = 0;
Rect r;
short searchPaneHi = 0;
short searchPaneWi = 0;
short wraps = 0;
// allow room for search button
if (SearchUserPane)
{
searchPaneWi = ControlWi(SearchUserPane);
searchPaneHi = ControlHi(SearchUserPane);
hWrap -= ExPixels + searchPaneWi;
vWrap -= ExPixels + searchPaneHi;
}
// allow room for fkey labels
if (FKeys && PrefIsSet(PREF_SHOW_FKEYS))
{
fKeyWi += vFactor*GetRLong(TB_FKEY_LABEL_WIDE); // yes, vFactor
fKeyHi += hFactor*10; // yes, hFactor
}
if (!PrefIsSet(PREF_NO_TB_BALL) && !Vertical && (VarCode==tbvBig||VarCode==tbvSmall))
tipHi = 12;
fKeyHi = MAX(fKeyHi,tipHi);
fKeyWiSave = fKeyWi;
// setup alignment stuff
GetButtonAlignment (VarCode, &alignment, &placement, &textOffset, &gAlignment, &gOffset);
h = v = ExPixels;
for (i=0;i<N;i++)
{
if (i>14)
{
fKeyHi = tipHi;
fKeyWi = 0;
}
button=(*BD)[i].cntl;
SetControlData(button,0,kControlBevelButtonTextAlignTag,sizeof(alignment),(void*)&alignment);
SetControlData(button,0,kControlBevelButtonTextPlaceTag,sizeof(placement),(void*)&placement);
SetControlData(button,0,kControlBevelButtonTextOffsetTag,sizeof(textOffset),(void*)&textOffset);
SetControlData(button,0,kControlBevelButtonGraphicAlignTag,sizeof(gAlignment),(void*)&gAlignment);
SetControlData(button,0,kControlBevelButtonGraphicOffsetTag,sizeof(gOffset),(void*)&gOffset);
wi = Wi*(1 + hFactor*(*BD)[i].slots);
hi = Hi*(1 + vFactor*(*BD)[i].slots);
MoveMyCntl(button,h,v,wi,hi);
maxH = MAX(maxH,h+wi+fKeyWi);
maxV = MAX(maxV,v+hi+fKeyHi);
extraCount++;
v += vFactor*(hi + Space);
if (!(extraCount%ExCount)) v += vFactor*ExPixels;
h += hFactor*(wi + Space);
if (!(extraCount%ExCount)) h += hFactor*ExPixels;
if (i<N-1)
{
nextSlots = i<N-1 ? (*BD)[i+1].slots : 0;
if (v+vFactor*(1+nextSlots)*Hi>vWrap)
{
v = ExPixels;
h = maxH+ExPixels;
extraCount = 0;
wraps++;
}
else if (h+hFactor*(1+nextSlots)*Wi>hWrap)
{
h = ExPixels;
v = maxV+ExPixels;
extraCount = 0;
wraps++;
}
}
}
// basic sizing
if (windowWide)
{
*windowWide = maxH+ExPixels;
if (!Vertical && SearchUserPane) *windowWide += ControlWi(SearchUserPane)+ExPixels;
}
if (windowHi)
{
*windowHi = maxV+ExPixels;
if (Vertical && SearchUserPane) *windowHi += ControlHi(SearchUserPane)+ExPixels;
}
// The search button
if (SearchUserPane)
{
// If the search button is forcing the window higher or wider, make sure the buttons
// grow to where they need to be
if (Vertical)
{
if (fKeyWiSave+Wi < searchPaneWi && !wraps)
{
// we're going to have to make the buttons wider to fill in the space
Wi = searchPaneWi-fKeyWiSave;
for (i=0;i<N;i++)
SizeControl((*BD)[i].cntl,Wi,Hi);
}
}
hi = ControlHi(SearchUserPane);
if (Vertical)
{
if (*windowWide) *windowWide = MAX(*windowWide,ControlWi(SearchUserPane)+2*ExPixels);
MoveMyCntl(SearchUserPane,ExPixels,maxV+ExPixels,0,hi);
}
else
{
if (*windowHi) *windowHi = MAX(*windowHi,ControlHi(SearchUserPane)+2*ExPixels);
MoveMyCntl(SearchUserPane,maxH+ExPixels,ExPixels+(Hi-hi)/2,0,hi);
}
// Now, move the embedded controls to the right places
GetControlBounds(SearchUserPane,&r);
MoveMyCntl(SearchPopup,r.left+1,r.top+(RectHi(r)-ControlHi(SearchPopup))/2,0,0);
MoveMyCntl(SearchGo,r.right-ControlWi(SearchGo),r.top+(RectHi(r)-ControlHi(SearchGo))/2,0,0);
MoveMyCntl(SearchEdit,r.left+MAX_APPEAR_RIM+ControlWi(SearchPopup)+1,r.top+(RectHi(r)-ControlHi(SearchGo))/2,
ControlWi(SearchUserPane)-2-2*MAX_APPEAR_RIM-ControlWi(SearchPopup)-ControlWi(SearchGo),
RectHi(r)-2*MAX_APPEAR_RIM);
GetControlBounds(SearchEdit,&r);
PeteDidResize(SearchPTE,&r);
}
}
/************************************************************************
* AssignCmdKey - (re)assign command keys
************************************************************************/
void AssignCmdKey(short modifiers)
{
}
/************************************************************************
* ChangeCmdKeys - go through the cmd key string and change cmd keys
************************************************************************/
void ChangeCmdKeys(void)
{
Str255 s;
UPtr spot;
Str31 token;
long num;
EventRecord event;
MenuHandle mh;
short newMods;
Str31 menuStr;
Str31 itemStr;
short menu;
short item;
short i;
if (*GetRString(s,CmdKeyStrn+1))
{
Zero(event);
event.what = keyDown;
EnableMenuItems(true);
for (i=1;;i++)
{
// grab the string
GetRString(s,CmdKeyStrn+i);
if (!*s) break;
spot = s+1;
// first word is modifiers
PToken(s,token,&spot," ");
StringToNum(token,&num);
event.modifiers = num;
// next word is message
PToken(s,token,&spot," ");
StringToNum(token,&num);
event.message = num;
// next word are new modifiers
PToken(s,token,&spot," ");
StringToNum(token,&num);
newMods = num;
// next the menu name
PToken(s,menuStr,&spot,":");
menu = FindMenuByName(menuStr);
// and the item name
PToken(s,itemStr,&spot,"\377");
if (menu) item = FindItemByName(GetMHandle(menu),itemStr);
if (menu && item && event.message)
{
// is it assigned now?
if ((num=MyMenuKeyLo(&event,false))&0xffff0000)
if (mh=GetMHandle((num>>16)&0xffff))
SetItemCmd(mh,num&0xffff,0);
// and assign
mh = GetMHandle(menu);
SetItemCmd(mh,item,UnadornMessage(&event));
SetMenuItemModifiers(mh,item,
(event.modifiers&cmdKey ? 0:kMenuNoCommandModifier)|
(event.modifiers&optionKey ? kMenuOptionModifier:0)|
(event.modifiers&shiftKey ? kMenuShiftModifier:0)|
(event.modifiers&controlKey ? kMenuControlModifier:0));
}
}
EnableMenuItems(false);
HiliteMenu(0);
}
}
/************************************************************************
* TBNewSearchEdit - create the search button & edit region
************************************************************************/
ControlHandle TBNewSearchEdit(WindowPtr winWP)
{
MyWindowPtr win=GetWindowMyWindowPtr(winWP);
GrafPtr oldPort;
OSErr err;
PETEDocInitInfo pi;
PETEHandle pte;
ControlHandle cntl = nil;
DECLARE_UPP(PetePaneDraw,ControlUserPaneDraw);
GetPort(&oldPort);
SetPort_(GetMyWindowCGrafPtr(win));
DefaultPII(win,False,0,&pi);
SetRect(&pi.inRect,0,0,20,20);
pi.docWidth = 80;
if (!(err=PeteCreate(win,&pte,peClearAllReturns|peNoStyledPaste,&pi)))
{
PETEMarkDocDirty(PETE,pte,False);
(*PeteExtra(pte))->frame = true;
PeteFontAndSize(pte,GetPortTextFont(GetQDGlobalsThePort()),GetPortTextSize(GetQDGlobalsThePort()));
(*PeteExtra(pte))->infinitelyWide = True;
(*PeteExtra(pte))->dragPreProcess = TBDragPreProcess;
(*PeteExtra(pte))->dragPostProcess = TBDragPostProcess;
SearchPTE = pte;
if (cntl=NewControl(winWP,&pi.inRect,"",True,0,0,0,kControlUserPaneProc,(uLong)pte))
{
INIT_UPP(PetePaneDraw,ControlUserPaneDraw);
SetControlData(cntl,0,kControlUserPaneDrawProcTag,sizeof(PetePaneDrawUPP),(void*)&PetePaneDrawUPP);
}
}
CleanPII(&pi);
if (err) WarnUser(PETE_ERR,err);
SetPort_(oldPort);
return(cntl);
}
/************************************************************************
* DeletingButton - process deleting ad button
************************************************************************/
void DeletingButton(BDPtr pBD)
{
if (pBD->kind == tbkAd)
{
AdId adId;
adId.ad = pBD->select;
adId.server = pBD->modifiers;
AdDeleteButton(adId);
}
}
void MessageDragPopup (ControlHandle button, Boolean vertical)
{
CGrafPtr oldPort;
Rect buttonRect;
Point offsetPt;
GetControlBounds(button,&buttonRect);
// Put the button rectangle into global coordinates
offsetPt.h = offsetPt.v = 0;
LocalToGlobal (&offsetPt);
OffsetRect (&buttonRect, offsetPt.h, offsetPt.v);
GetPort (&oldPort);
if (OpenToolbarPopup (&buttonRect, VarCode, 2, vertical)) {
AddMenuToToolbarPopup (0, MESSAGE_MENU, MESSAGE_FORWARD_ITEM,(*BD)[GetControlReference(button)-1].title);
AddMenuToToolbarPopup (1, MESSAGE_MENU, MESSAGE_REDISTRIBUTE_ITEM, (*BD)[GetControlReference(button)-1].title);
}
SetPort (oldPort);
}
/************************************************************************
* ConfiguringToolbar - do indicated menu item if configuring the toolbar
************************************************************************/
Boolean ConfiguringToolbarMenuItem(short menuId,short item)
{
if (gTBMenu.doingButton)
{
gTBMenu.menuId = menuId;
gTBMenu.item = item;
return true;
}
return false;
}
/************************************************************************
* TBSearchStart - start a search from the mini-dialog
************************************************************************/
void TBSearchStart(PStr searchMe)
{
Str255 searchFor;
if (!searchMe)
{
searchMe = searchFor;
if (Win->pte)
{
PeteSString(searchFor,SearchPTE);
if (IsAllLWSP(searchFor)) *searchFor = 0;
}
else *searchFor = 0;
}
// Add to recent searches
if (0>StackStringFind(searchMe,SearchStack))
{
if ((*SearchStack)->elCount>=GetRLong(RECENT_SEARCH_LIMIT))
StackPop(nil,SearchStack);
StackQueue(searchMe,SearchStack);
}
// Now go do it
if (SearchItem>1)
{
short findItem = FIND_SEARCH_ITEM;
MyWindowPtr win = nil;
switch (SearchItem)
{
case 2: findItem=FIND_SEARCH_ITEM; break;
case 3: findItem=FIND_SEARCH_ALL_ITEM; break;
case 4: findItem=FIND_SEARCH_BOX_ITEM; break;
case 5: findItem=FIND_SEARCH_FOLDER_ITEM; break;
default: ASSERT(0);
}
win = SearchOpen(findItem);
if (win)
{
SearchNewFindStringLo(searchMe,true);
StartSearch(win);
}
}
else
DoWebFindStr(searchMe);
TBSearchFocus(false);
}
/************************************************************************
* TBSearchEmpty - empty the search field and put in fake text
************************************************************************/
void TBSearchEmpty(void)
{
Str255 s;
PETETextStyle ps;
switch (SearchItem)
{
case 0:
case 1:
ComposeRString(s,SEARCH_NOTHING_FMT,SEARCH_FOR_WEB);
break;
case 2:
ComposeRString(s,SEARCH_NOTHING_FMT,SEARCH_FOR_EMAIL);
break;
case 3:
case 4:
case 5:
MyGetItem(GetMHandle(FIND_HIER_MENU),FIND_SEARCH_ALL_ITEM-3+SearchItem,s);
break;
default:
ASSERT(0);
*s = 0;
break;
}
PeteSetString(s,SearchPTE);
GetRColor(&ps.tsColor,FAKE_CONTENT_COLOR);
PETESetTextStyle(PETE,SearchPTE,0,0xffff,&ps,peColorValid);
}
/************************************************************************
* TBSearchPopup - let the user choose to make us money or be productive
************************************************************************/
void TBSearchPopup(Point pt)
{
MenuHandle mh = NewMenu(CONTEXT_MENU,"");
Str255 s;
long sel;
short mnu, itm;
// Fill the menu with recent searches
if ((*SearchStack)->elCount)
{
for (itm=0;itm<(*SearchStack)->elCount;itm++)
{
StackItem(s,itm,SearchStack);
MyAppendMenu(mh,s);
}
AppendMenu(mh,"\p-");
}
if (!SearchItem) SearchItem = 1;
// The search-where items
AppendMenu(mh,ComposeRString(s,SEARCH_NOTHING_FMT,SEARCH_FOR_WEB));
AppendMenu(mh,ComposeRString(s,SEARCH_NOTHING_FMT,SEARCH_FOR_EMAIL));
CopyMenuItem(GetMHandle(FIND_HIER_MENU),FIND_SEARCH_ALL_ITEM,mh,REAL_BIG);
CopyMenuItem(GetMHandle(FIND_HIER_MENU),FIND_SEARCH_BOX_ITEM,mh,REAL_BIG);
CopyMenuItem(GetMHandle(FIND_HIER_MENU),FIND_SEARCH_FOLDER_ITEM,mh,REAL_BIG);
SetItemMark(mh,CountMenuItems(mh)-SearchItem+5,diamondChar);
LocalToGlobal(&pt);
sel = AFPopUpMenuSelect(mh,pt.v,pt.h,-1);
mnu = (sel>>16)&0xffff;
itm = sel&0xffff;
// Did the user choose anything valid?
if (mnu&&itm)
{
// focus in the search window
TBSearchFocus(true);
if ((*SearchStack)->elCount && itm<=(*SearchStack)->elCount)
{
// recent item
StackItem(s,itm-1,SearchStack);
PeteSetString(s,SearchPTE);
}
else // search where?
{
SearchItem = itm - CountMenuItems(mh) + 5;
if (*PeteString(s,SearchPTE))
TBSearchStart(s);
}
}
}
/************************************************************************
* TBSearchFocus - focus or unfocus on the search field
************************************************************************/
void TBSearchFocus(Boolean focus)
{
if (SearchPTE)
{
if (focus)
{
if (!Win->pte)
{
PeteSetTextPtr(SearchPTE,nil,0);
PetePlain(SearchPTE,0,0xffff,peAllValid);
PetePlain(SearchPTE,kPETECurrentStyle,kPETECurrentStyle,peAllValid);
PeteFocus(Win,SearchPTE,true);
PeteActiveLock(SearchPTE);
}
}
else if (Win->pte)
{
PeteFocus(Win,nil,true);
PeteActiveLock(nil);
TBSearchEmpty();
}
}
}
/************************************************************************
* TBDragPreProcess - clear out fake text on drag
************************************************************************/
void TBDragPreProcess(PETEHandle pte,DragTrackingMessage message,DragReference drag)
{
if (message==kDragTrackingEnterWindow)
TBSearchFocus(true);
}
/************************************************************************
* TBDragPostProcess - launch search after drop
************************************************************************/
void TBDragPostProcess(PETEHandle pte,DragTrackingMessage message,DragReference drag)
{
if (message==kDragTrackingLeaveWindow && !PeteLen(SearchPTE))
TBSearchFocus(false);
else if (message==0x0fff)
{
Str255 s;
PeteString(s,SearchPTE);
if (!IsAllLWSP(s)) TBSearchStart(s);
TBSearchEmpty();
}
}