/* 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;i0 && 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, ¬es)) { 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;iname); 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;iWin->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 (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;ikind) { 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,§)); } 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;bmodifiers,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>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 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>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;icntl); } } // Install ad buttons LDRef(hTBAds); for(i=0;ikind = 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;ikind == 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 && controlRefpte, 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))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;i14) { 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 (ivWrap) { 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>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(); } }