1 line
150 KiB
C
Executable File
1 line
150 KiB
C
Executable File
/* Copyright (c) 2017, Computer History Museum
|
||
All rights reserved.
|
||
Redistribution and use in source and binary forms, with or without modification, are permitted (subject to
|
||
the limitations in the disclaimer below) provided that the following conditions are met:
|
||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
|
||
disclaimer in the documentation and/or other materials provided with the distribution.
|
||
* Neither the name of Computer History Museum nor the names of its contributors may be used to endorse or promote products
|
||
derived from this software without specific prior written permission.
|
||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
|
||
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||
DAMAGE. */
|
||
|
||
#include "filtwin.h"
|
||
/************************************************************************
|
||
* Filters window - Copyright (C) 1994 QUALCOMM Incorporated
|
||
************************************************************************/
|
||
#define FILE_NUM 67
|
||
#ifdef TWO
|
||
#pragma segment FilterWin
|
||
|
||
#define MIN_ACTION_WI (35*Win->hPitch)
|
||
#define MIN_MATCH_HI (13*Win->vPitch)
|
||
#define MAX_MATCH_HI (15*Win->vPitch)
|
||
#define MIN_ACTION_HI (GROW_SIZE + 3*INSET + 5*MIN_ACT1_HI)
|
||
#define MIN_ACT1_HI (24)
|
||
#define MAX_ACT1_HI (3*Win->vPitch)
|
||
#define MAX_MATCHPOP_WI (25*Win->hPitch)
|
||
#define BUTTON_REASONABLE (24*Win->hPitch)
|
||
#define POP_V_ADJUST (-3)
|
||
#define POP_H_ADJUST INSET
|
||
|
||
#define FILT_DRAG_DATA_TYPE 'Eufl'
|
||
|
||
/************************************************************************
|
||
* Filter globals
|
||
************************************************************************/
|
||
typedef enum
|
||
{
|
||
flNewButton=0,
|
||
flRemoveButton,
|
||
flIncoming,
|
||
flOutgoing,
|
||
flManual,
|
||
flMatchOnePop,
|
||
flMatchTwoPop,
|
||
flConjunction,
|
||
flAct1,
|
||
flAct2,
|
||
flAct3,
|
||
flAct4,
|
||
flAct5,
|
||
flAccel1,
|
||
flAccel2,
|
||
flNickFilePop1,
|
||
flNickFilePop2,
|
||
flActionGroup,
|
||
flMatchGroup,
|
||
flLimit
|
||
} FilterControlEnum;
|
||
#define fl1stLimit flAct1
|
||
#define fl2ndLimit flActionGroup
|
||
|
||
typedef enum
|
||
{
|
||
flrVBar,
|
||
flrAccel1,
|
||
flrAccel2,
|
||
flrMatch,
|
||
flrAction,
|
||
flrList,
|
||
flrMatch1,
|
||
flrMatch2,
|
||
flrAct1,
|
||
flrAct2,
|
||
flrAct3,
|
||
flrAct4,
|
||
flrAct5,
|
||
flrDate,
|
||
flrVal1,
|
||
flrVal2,
|
||
flrLimit
|
||
} FilterRectEnum;
|
||
|
||
typedef struct
|
||
{
|
||
PETEHandle headerPTE;
|
||
PETEHandle valuePTE;
|
||
Point labelPoint;
|
||
} MatchBlock, *MBlockPtr, **MBlockHandle;
|
||
|
||
|
||
typedef struct
|
||
{
|
||
ControlHandle controls[flLimit];
|
||
Rect rects[flrLimit];
|
||
short actSpace;
|
||
short actHi;
|
||
MatchBlock blocks[2];
|
||
short selected;
|
||
MyWindowPtr win;
|
||
ListHandle lHand;
|
||
Boolean multiple;
|
||
Boolean hasTwo;
|
||
Boolean currentDirty;
|
||
RgnHandle actRgn;
|
||
MenuHandle actionMenu;
|
||
DragReference oldDrag;
|
||
Boolean dragInteresting;
|
||
Boolean dragFromMe;
|
||
} FilterGlobalRec;
|
||
|
||
FilterGlobalRec **FLG;
|
||
|
||
#define DragInteresting (*FLG)->dragInteresting
|
||
#define DragFromMe (*FLG)->dragFromMe
|
||
#define OldDrag (*FLG)->oldDrag
|
||
#define Controls (*FLG)->controls
|
||
#define Rects (*FLG)->rects
|
||
#define Blocks (*FLG)->blocks
|
||
#define ActSpace (*FLG)->actSpace
|
||
#define ActHi (*FLG)->actHi
|
||
#define Selected (*FLG)->selected
|
||
#define Win (*FLG)->win
|
||
#define LHand (*FLG)->lHand
|
||
#define Points (*FLG)->points
|
||
#define Multiple (*FLG)->multiple
|
||
#define CurrentDirty (*FLG)->currentDirty
|
||
#define CurrentLabel (*FLG)->currentLabel
|
||
|
||
#define RemoveButton Controls[flRemoveButton]
|
||
#define NewButton Controls[flNewButton]
|
||
#define MatchGroup Controls[flMatchGroup]
|
||
#define ActionGroup Controls[flActionGroup]
|
||
#define Block0 (*FLG)->blocks[0]
|
||
#define Block1 (*FLG)->blocks[1]
|
||
#define HasTwo (*FLG)->hasTwo
|
||
#define ActRgn (*FLG)->actRgn
|
||
#define ActionMenu (*FLG)->actionMenu
|
||
#define STEList Win->steList
|
||
|
||
/**********************************************************************
|
||
* Prototypes
|
||
**********************************************************************/
|
||
void FilterHelp(MyWindowPtr win,Point mouse);
|
||
OSErr FiltDragHandler(MyWindowPtr win,DragTrackingMessage which,DragReference drag);
|
||
void FilterClick(MyWindowPtr win, EventRecord *event);
|
||
short FilterListWidth(short total);
|
||
short FilterMatchHeight(short total);
|
||
void FilterDidResize(MyWindowPtr win, Rect *oldContR);
|
||
short MatchBlockHeight(short total);
|
||
void FiltersSetGreys(void);
|
||
Boolean FiltersClose(MyWindowPtr win);
|
||
OSErr FillFilters(short startingFrom);
|
||
void FiltersUpdate(MyWindowPtr win);
|
||
void SetFASpacings(short total);
|
||
void FAPopup(Rect *r);
|
||
void FAPopupValueFit(Rect *r,ControlHandle popup);
|
||
void AccelPopUp(PETEHandle pte,ControlHandle verbCntl,short top,short left);
|
||
void ActOnFilterSelect(void);
|
||
void DisplaySelectedFilter(void);
|
||
void InvalMatch2(void);
|
||
void FActionPopUp(Point pt,ControlHandle cntl);
|
||
void AdjustActionMenu (MenuHandle theMenu);
|
||
void NewAction(short n,FActionHandle fa,FilterKeywordEnum action);
|
||
void FASingleRect(Rect *inRect, Rect *r,short hi);
|
||
void FilterButton(MyWindowPtr win,ControlHandle button,long modifiers,short part);
|
||
void FilterSwap(short i, short j);
|
||
void RemoveFilter(short which);
|
||
void AddFilter(short n);
|
||
Boolean FilterActionButton(ControlHandle button,short modifiers);
|
||
void FilterSelect(short which);
|
||
void FilterTextChanged(MyWindowPtr win, TEHandle teh, short oldNl, short newNl, Boolean scroll);
|
||
OSErr FiltSetAndShowNickPop(FilterControlEnum pop,PStr value,Rect *r);
|
||
void InvalAct(short i);
|
||
short ActOf(FActionHandle fa);
|
||
Boolean FilterKey(MyWindowPtr win, EventRecord *event);
|
||
void FilterActivate(MyWindowPtr win);
|
||
Boolean FilterMenu(MyWindowPtr win, int menu, int item, short modifiers);
|
||
Boolean FilterApp1(MyWindowPtr win,EventRecord *event);
|
||
Boolean AppearInFilter(PStr what,short which,Boolean caseSens);
|
||
Boolean AppearInTerm(PStr what,MTPtr term);
|
||
void FAMultRect(Rect *inRect, Rect *r,short *spacing,short hi,short n);
|
||
Boolean AppearInActions(PStr what,FActionHandle fa);
|
||
Boolean AppearInAction(PStr what,FActionHandle fa);
|
||
void FiltDragDivider(Point where);
|
||
void FilterCursor(Point mouse);
|
||
OSErr PrintFilters(Boolean selected,Boolean now);
|
||
void FiltRedoList(short startSel,short nSel);
|
||
OSErr FiltDrop(short stice,DragReference drag);
|
||
OSErr FiltDropFile(short stice,DragReference drag);
|
||
OSErr MoveSelectedFilters(short stice);
|
||
#ifdef DEBUG
|
||
#ifdef GRIDLINES
|
||
void ControlGridlines(ControlHandle cntl);
|
||
#endif
|
||
#endif
|
||
FActionProc FAflkNone, FAflkPrint, FAflkStop, FAflkCopy, FAflkSubject, FAflkLabel,
|
||
FAflkSound, FAflkOpenMessage, FAflkOpenMailbox, FAflkPriority, FAflkForward,
|
||
FAflkRedirect, FAflkReply, FAflkNotifyApp, FAflkNotifyUser, FAflkServerOpts,
|
||
FAflkTransfer, FAflkAttachments, FAflkTranslit, FAflkStatus, FAflkPersonality,FAflkJunk,
|
||
//#ifdef SPEECH_ENABLED
|
||
FAflkSpeak,
|
||
//#endif
|
||
FAflkAddHistory,
|
||
FAflkMoveAttach;
|
||
OSErr PrintAFilter(short i, Rect *uRect, short *v, short *page,PMPrintContext printContext);
|
||
short FiltPrintLines(short which,Rect *uRect);
|
||
void FiltPrintTerm(MTPtr term);
|
||
void FAPopActRect(Rect *inRect, Rect *r);
|
||
OSErr FiltDoDrag(EventRecord *event);
|
||
void FiltClickHook(short cell,ListHandle lHand);
|
||
void RemoveSelectedFilters(void);
|
||
void RemoveFilterLo(short which);
|
||
void DrawFilterDate(void);
|
||
#ifdef GX_PRINTING
|
||
OSErr GXPrintFilters(Boolean selected, Boolean now);
|
||
OSErr GXPrintAFilter(CGrafPtr GXPortPtr, short i, Rect *uRect, gxRectangle *GXuRect, short *v, short *page, long firstPage, long numPages);
|
||
short FilterToPrintFirst(long firstPage, Rect *uRect);
|
||
#endif //GX_PRINTING
|
||
short SelectFiltersBasedOnWindow(WindowPtr winWP);
|
||
Boolean FilterFind(MyWindowPtr win,PStr what);
|
||
pascal OSErr FilterChanged(PETEHandle pte,long start,long stop);
|
||
pascal OSErr FiltDragSend(FlavorType flavor, void *dragSendRefCon, ItemReference theItemRef, DragReference drag);
|
||
void FiltDragFilename(PStr name);
|
||
void FiltEnableVerb(ControlHandle popUpCntl,PStr head);
|
||
void FiltEnableVerbAll(void);
|
||
Boolean FilterScrollWheel(MyWindowPtr win,Point pt,short h,short v);
|
||
|
||
/**********************************************************************
|
||
* FilterChanged - set the dirty bit on the window when an edit region changes
|
||
**********************************************************************/
|
||
pascal OSErr FilterChanged(PETEHandle pte,long start,long stop)
|
||
{
|
||
#pragma unused(pte,start,stop)
|
||
CurrentDirty = True;
|
||
return noErr;
|
||
}
|
||
|
||
/************************************************************************
|
||
* OpenFiltersWindow - open the window
|
||
************************************************************************/
|
||
OSErr OpenFiltersWindow(void)
|
||
{
|
||
WindowPtr winWP=nil;
|
||
short err = noErr;
|
||
void *grumble;
|
||
MyWindowPtr win=nil;
|
||
Rect r;
|
||
Point cSize;
|
||
Rect bounds;
|
||
short i;
|
||
Str255 not;
|
||
DECLARE_UPP(FiltListDef,ListDef);
|
||
|
||
INIT_UPP(FiltListDef,ListDef);
|
||
CycleBalls();
|
||
|
||
NotifyHelpers(0,eFilterWin,nil);
|
||
|
||
if (PrefIsSet(PREF_MA)) return(noErr);
|
||
|
||
/*
|
||
* open already?
|
||
*/
|
||
if (SelectOpenWazoo(FILT_WIN))
|
||
;
|
||
else if (FLG)
|
||
UserSelectWindow(GetMyWindowWindowPtr(Win));
|
||
else
|
||
{
|
||
|
||
/*
|
||
* allocate space
|
||
*/
|
||
if (!(FLG = NewZH(FilterGlobalRec))) {WarnUser(MEM_ERR,err=MemError()); goto fail;}
|
||
|
||
|
||
/*
|
||
* make the window
|
||
*/
|
||
if (!(win=GetNewMyWindow(FILT_WIND,nil,nil,BehindModal,False,False,FILT_WIN)))
|
||
{
|
||
WarnUser(MEM_ERR,err=MemError());
|
||
goto fail;
|
||
}
|
||
Win = win;
|
||
winWP = GetMyWindowWindowPtr(win);
|
||
|
||
ConfigFontSetup(Win);
|
||
//MySetThemeWindowBackground(win,kThemeListViewBackgroundBrush,False);
|
||
|
||
/*
|
||
* regenerate the list of filters
|
||
*/
|
||
if (err=RegenerateFilters()) goto fail;
|
||
|
||
/*
|
||
* and all the controls
|
||
*/
|
||
for (i=0;i<fl1stLimit;i++)
|
||
{
|
||
if (!(grumble=GetNewControlSmall_(i+FILT_CNTL_BASE,winWP)))
|
||
{WarnUser(MEM_ERR,err=MemError()); goto fail;}
|
||
Controls[i] = grumble;
|
||
}
|
||
ButtonFit(RemoveButton);
|
||
ButtonFit(NewButton);
|
||
|
||
for (i=fl1stLimit;i<fl2ndLimit;i++)
|
||
{
|
||
if (!(grumble=GetNewControlSmall_(i-fl1stLimit+FILT_CNTL_2ND_BASE,winWP)))
|
||
{WarnUser(MEM_ERR,err=MemError()); goto fail;}
|
||
Controls[i] = grumble;
|
||
}
|
||
|
||
//
|
||
// group controls
|
||
//
|
||
if (!(grumble = GetNewControlSmall_(FILTER_MATCH_GROUP_CNTL,winWP)))
|
||
{WarnUser(MEM_ERR,err=MemError()); goto fail;}
|
||
ActionGroup = grumble;
|
||
if (!(grumble = GetNewControlSmall_(FILTER_ACTION_GROUP_CNTL,winWP)))
|
||
{WarnUser(MEM_ERR,err=MemError()); goto fail;}
|
||
MatchGroup = grumble;
|
||
|
||
|
||
/*
|
||
* make the fixed STE's
|
||
*/
|
||
SetRect(&r,0,0,20,20);
|
||
Zero(not);
|
||
not['\015'] = 1;
|
||
|
||
/* header 1 */
|
||
if (err = PeteCreate(Win,&grumble,0,nil)) {WarnUser(MEM_ERR,err); goto fail;}
|
||
PeteFontAndSize(grumble,GetPortTextFont(GetQDGlobalsThePort()),GetPortTextSize(GetQDGlobalsThePort()));
|
||
(*PeteExtra(grumble))->frame = True;
|
||
(*PeteExtra(grumble))->infinitelyWide = True;
|
||
Block0.headerPTE = grumble;
|
||
PETESetCallback(PETE,Block0.headerPTE,(void*)FilterChanged,peDocChanged);
|
||
BMD(not,(*PeteExtra(Block0.headerPTE))->not,sizeof(not));
|
||
|
||
/* value 1 */
|
||
if (err = PeteCreate(Win,&grumble,0,nil)) {WarnUser(MEM_ERR,err); goto fail;}
|
||
PeteFontAndSize(grumble,GetPortTextFont(GetQDGlobalsThePort()),GetPortTextSize(GetQDGlobalsThePort()));
|
||
(*PeteExtra(grumble))->frame = True;
|
||
(*PeteExtra(grumble))->infinitelyWide = True;
|
||
Block0.valuePTE = grumble;
|
||
PETESetCallback(PETE,Block0.valuePTE,(void*)FilterChanged,peDocChanged);
|
||
|
||
/* header 2 */
|
||
if (err = PeteCreate(Win,&grumble,0,nil)) {WarnUser(MEM_ERR,err); goto fail;}
|
||
(*PeteExtra(grumble))->frame = True;
|
||
(*PeteExtra(grumble))->infinitelyWide = True;
|
||
PeteFontAndSize(grumble,GetPortTextFont(GetQDGlobalsThePort()),GetPortTextSize(GetQDGlobalsThePort()));
|
||
Block1.headerPTE = grumble;
|
||
PETESetCallback(PETE,Block1.headerPTE,(void*)FilterChanged,peDocChanged);
|
||
|
||
/* value 2 */
|
||
if (err = PeteCreate(Win,&grumble,0,nil)) {WarnUser(MEM_ERR,err); goto fail;}
|
||
PeteFontAndSize(grumble,GetPortTextFont(GetQDGlobalsThePort()),GetPortTextSize(GetQDGlobalsThePort()));
|
||
(*PeteExtra(grumble))->frame = True;
|
||
(*PeteExtra(grumble))->infinitelyWide = True;
|
||
Block1.valuePTE = grumble;
|
||
PETESetCallback(PETE,Block1.valuePTE,(void*)FilterChanged,peDocChanged);
|
||
|
||
|
||
/*
|
||
* list handle
|
||
*/
|
||
SetRect(&bounds,0,0,1,0);
|
||
cSize.h = cSize.v = 1;
|
||
#ifdef FANCY_FILT_LDEF
|
||
grumble = (void *)CreateNewList(FiltListDefUPP,FILT_LDEF,&r,&bounds,cSize,winWP,True,False,False,True);
|
||
#else
|
||
grumble = (void *)LNew(&r,&bounds,cSize,nil,winWP,True,False,False,True);
|
||
#endif
|
||
if (!grumble) {WarnUser(MEM_ERR,err=MemError()); goto fail;}
|
||
LHand = (ListHandle)grumble;
|
||
(*LHand)->indent.h = INSET;
|
||
//(*LHand)->selFlags = lOnlyOne;
|
||
|
||
/*
|
||
* install handlers
|
||
*/
|
||
Win->help = FilterHelp;
|
||
Win->cursor = FilterCursor;
|
||
Win->activate = FilterActivate;
|
||
Win->app1 = FilterApp1;
|
||
Win->menu = FilterMenu;
|
||
Win->key = FilterKey;
|
||
Win->textChanged = FilterTextChanged;
|
||
Win->button = FilterButton;
|
||
Win->click = FilterClick;
|
||
Win->close = FiltersClose;
|
||
Win->position = PositionPrefsTitle;
|
||
Win->update = FiltersUpdate;
|
||
Win->didResize = FilterDidResize;
|
||
Win->dontControl = True;
|
||
Win->drag = FiltDragHandler;
|
||
Win->find = FilterFind;
|
||
Win->scrollWheel = FilterScrollWheel;
|
||
Win->userSave = true;
|
||
FiltersSetGreys();
|
||
grumble = (Handle)NewRgn();
|
||
if (!grumble) {err=WarnUser(MEM_ERR,MemError()); goto fail;}
|
||
ActRgn = (RgnHandle)grumble;
|
||
|
||
grumble = (Handle)GetMenu(FLA_HI_MENU);
|
||
if (!grumble) {err=WarnUser(MEM_ERR,MemError()); goto fail;}
|
||
ActionMenu = (MenuHandle)grumble;
|
||
AdjustActionMenu (ActionMenu);
|
||
InsertMenu(ActionMenu,-1);
|
||
|
||
/*
|
||
* fill the list
|
||
*/
|
||
if (err = FillFilters(0)) goto fail;
|
||
|
||
MyWindowDidResize(Win,&Win->contR);
|
||
ShowMyWindow(winWP);
|
||
}
|
||
|
||
if (MainEvent.modifiers & shiftKey)
|
||
{
|
||
for (winWP = GetNextWindow (winWP); winWP && !IsWindowVisible (winWP); winWP = GetNextWindow (winWP));
|
||
if (winWP) SelectFiltersBasedOnWindow(winWP);
|
||
}
|
||
|
||
//WinGreyBG(Win);
|
||
|
||
return(noErr);
|
||
|
||
fail:
|
||
FiltersClose(win);
|
||
if (winWP) CloseMyWindow(winWP);
|
||
return(err);
|
||
}
|
||
|
||
|
||
#pragma segment FilterWin
|
||
|
||
/************************************************************************
|
||
* SelectFiltersBasedOnWindow - select the filters that match a window
|
||
************************************************************************/
|
||
short SelectFiltersBasedOnWindow(WindowPtr winWP)
|
||
{
|
||
MyWindowPtr win = GetWindowMyWindowPtr(winWP);
|
||
short count = 0;
|
||
TOCHandle tocH = nil;
|
||
short sumNum;
|
||
Point c;
|
||
|
||
if (winWP)
|
||
{
|
||
switch (GetWindowKind(winWP))
|
||
{
|
||
case MESS_WIN:
|
||
case COMP_WIN:
|
||
tocH = (*Win2MessH(win))->tocH;
|
||
sumNum = (*Win2MessH(win))->sumNum;
|
||
break;
|
||
|
||
case MBOX_WIN:
|
||
case CBOX_WIN:
|
||
tocH = (TOCHandle) GetWindowPrivateData (winWP);
|
||
sumNum = FirstMsgSelected(tocH);
|
||
if (sumNum<0) tocH = nil;
|
||
break;
|
||
}
|
||
if (tocH)
|
||
{
|
||
c.h = 0;
|
||
for (c.v=0;c.v<NFilters;c.v++)
|
||
{
|
||
if (FilterMatchHi(c.v,tocH,sumNum))
|
||
{
|
||
count++;
|
||
LSetSelect(true,c,LHand);
|
||
}
|
||
else
|
||
LSetSelect(false,c,LHand);
|
||
}
|
||
ActOnFilterSelect();
|
||
}
|
||
}
|
||
#ifdef IMAP
|
||
IMAPStopFiltering(true); // FilterMatchHi may have started IMAP filtering
|
||
#endif
|
||
return(count);
|
||
}
|
||
|
||
/************************************************************************
|
||
* FilterCursor - set the cursor properly
|
||
************************************************************************/
|
||
void FilterCursor(Point mouse)
|
||
{
|
||
Rect r;
|
||
short cursor = arrowCursor;
|
||
short i;
|
||
FActionHandle fa;
|
||
|
||
r = Rects[flrList]; r.right -= GROW_SIZE;
|
||
if (PtInRect(mouse,&r))
|
||
cursor = plusCursor;
|
||
else if (PtInSlopRect(mouse,Rects[flrVBar],1))
|
||
cursor = DIVIDER_CURS;
|
||
else if (Selected && !Multiple)
|
||
{
|
||
if (PeteCursorList(Win->pteList,mouse))
|
||
return;
|
||
else
|
||
for (i=0,fa=FR[Selected-1].actions;fa;fa=(*fa)->next,i++)
|
||
{
|
||
r = Rects[flrAct1+i];
|
||
if (PtInSlopRect(mouse,Rects[flrAct1+i],2))
|
||
{
|
||
((*(FActionProc*)FATable((*fa)->action)))(faeCursor,fa,(Rect*)&mouse,&cursor);
|
||
break;
|
||
}
|
||
}
|
||
|
||
}
|
||
SetMyCursor(cursor);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FilterFind - find in the filters window
|
||
**********************************************************************/
|
||
Boolean FilterFind(MyWindowPtr win,PStr what)
|
||
{
|
||
WindowPtr WinWP = GetMyWindowWindowPtr (Win);
|
||
CGrafPtr winPort = GetMyWindowCGrafPtr (win);
|
||
Boolean found = False;
|
||
short spot;
|
||
short stop;
|
||
Boolean wrapped;
|
||
|
||
SelectWindow_(WinWP);
|
||
SetPort_(GetWindowPort(WinWP));
|
||
LActivate(True,LHand);
|
||
|
||
wrapped = False;
|
||
spot = -1;
|
||
stop = 0;
|
||
if (Selected) spot = stop = Selected-1;
|
||
|
||
// Don't let any drawing occur during find
|
||
SetEmptyClipRgn(winPort);
|
||
win->noUpdates = true;
|
||
do
|
||
{
|
||
MiniEvents(); if (CommandPeriod || EjectBuckaroo) break;
|
||
spot++;
|
||
if (spot>=NFilters) {spot=0;wrapped = True;}
|
||
FilterSelect(spot);
|
||
if (spot==stop && wrapped) break;
|
||
found = AppearInFilter(what,spot,PrefIsSet(PREF_SENSITIVE));
|
||
}
|
||
while (!found);
|
||
win->noUpdates = false;
|
||
InfiniteClip(winPort); // Restore clipping region
|
||
InvalContent(win);
|
||
|
||
return found;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FilterScrollWheel - handle scroll wheel events for filter list
|
||
**********************************************************************/
|
||
Boolean FilterScrollWheel(MyWindowPtr win,Point pt,short h,short v)
|
||
{
|
||
Rect rList;
|
||
|
||
GetListViewBounds (LHand, &rList);
|
||
if (PtInRect(pt,&rList))
|
||
{
|
||
LScroll(0,-v,LHand);
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* MatchInFilter - does a string appear in a filter?
|
||
**********************************************************************/
|
||
Boolean AppearInFilter(PStr what,short which,Boolean caseSens)
|
||
{
|
||
#pragma unused(caseSens)
|
||
Boolean found;
|
||
Str255 scratch;
|
||
|
||
LDRef(Filters);
|
||
|
||
found = nil!=PFindSub(what,FR[which].name);
|
||
found = found || AppearInTerm(what,&FR[which].terms[0]);
|
||
found = found || FR[which].conjunction!=cjIgnore && AppearInTerm(what,&FR[which].terms[1]);
|
||
found = found || PFindSub(what,GetRString(scratch,CONJ_STRN+FR[which].conjunction));
|
||
found = found || AppearInActions(what,FR[which].actions);
|
||
|
||
UL(Filters);
|
||
return(found);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* AppearInActions - does a string appear in any of the actions?
|
||
**********************************************************************/
|
||
Boolean AppearInActions(PStr what,FActionHandle fa)
|
||
{
|
||
for (;fa;fa = (*fa)->next) if (AppearInAction(what,fa)) return(True);
|
||
return(False);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* AppearInAction - does a string appear in an action?
|
||
**********************************************************************/
|
||
Boolean AppearInAction(PStr what,FActionHandle fa)
|
||
{
|
||
Str255 scratch;
|
||
|
||
GetMenuItemText(ActionMenu,(*fa)->action,scratch);
|
||
|
||
if (PFindSub(what,scratch)) return(True);
|
||
return(CallAction(faeFind,fa,nil,what));
|
||
}
|
||
|
||
/**********************************************************************
|
||
* AppearInTerm - does a string appear in a term?
|
||
**********************************************************************/
|
||
Boolean AppearInTerm(PStr what,MTPtr term)
|
||
{
|
||
Str255 verb;
|
||
|
||
return (
|
||
PFindSub(what,term->header) ||
|
||
PFindSub(what,term->value) ||
|
||
PFindSub(what,GetRString(verb,VERB_STRN+term->verb)) ||
|
||
0
|
||
);
|
||
}
|
||
|
||
/************************************************************************
|
||
* FilterKey - handle keystrokes in the filter window
|
||
************************************************************************/
|
||
Boolean FilterKey(MyWindowPtr win, EventRecord *event)
|
||
{
|
||
#pragma unused(win)
|
||
short key = event->message&0xff;
|
||
|
||
if (event->modifiers & cmdKey) {return(False);} /* no command keys! */
|
||
|
||
switch(key)
|
||
{
|
||
case upArrowChar:
|
||
FilterSelect(MAX(0,Selected-2));
|
||
return(True);
|
||
case downArrowChar:
|
||
FilterSelect(MIN(Selected,NFilters-1));
|
||
return(True);
|
||
}
|
||
|
||
if (!Win->pte) return(False);
|
||
|
||
if (key=='\t' || key=='\015')
|
||
{
|
||
if (event->modifiers&shiftKey) PeteFocusPrevious(Win);
|
||
else PeteFocusNext(Win);
|
||
PeteSelectAll(Win,Win->pte);
|
||
FiltEnableVerbAll();
|
||
}
|
||
else if (key==enterChar)
|
||
{
|
||
PeteSelectAll(Win,Win->pte);
|
||
SaveCurrentFilter();
|
||
FiltEnableVerbAll();
|
||
}
|
||
else
|
||
{
|
||
return(False);
|
||
}
|
||
return(True);
|
||
}
|
||
|
||
/************************************************************************
|
||
* FilterApp1 - handle App1 event for filter
|
||
************************************************************************/
|
||
Boolean FilterApp1(MyWindowPtr win,EventRecord *event)
|
||
{
|
||
#pragma unused(win)
|
||
return(ListApp1(event,LHand));
|
||
}
|
||
|
||
/************************************************************************
|
||
* FilterActivate - handle activation and deactivation
|
||
************************************************************************/
|
||
void FilterActivate(MyWindowPtr win)
|
||
{
|
||
#pragma unused(win)
|
||
LActivate(Win->isActive,LHand);
|
||
if (!Win->isActive) SaveCurrentFilter();
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FiltersUpdate - update the filters window
|
||
**********************************************************************/
|
||
void FiltersUpdate(MyWindowPtr win)
|
||
{
|
||
CGrafPtr WinPort = GetMyWindowCGrafPtr (Win);
|
||
Rect r;
|
||
Str63 s;
|
||
short i;
|
||
FActionHandle fa;
|
||
short wi;
|
||
|
||
//RaisedWindowRect(win);
|
||
|
||
ConfigFontSetup(win);
|
||
|
||
r = Rects[flrList];
|
||
InsetRect(&r,1,1);
|
||
DrawThemeListBoxFrame(&r,kThemeStateActive);
|
||
|
||
for (i=flrMatch1;i<=flrAct5;i++)
|
||
{
|
||
r = Rects[i];
|
||
DrawThemeSecondaryGroup(&r,kThemeStateActive);
|
||
}
|
||
|
||
TextMode(srcOr);
|
||
|
||
GetRString(s,HEADER_LABEL);
|
||
|
||
if (!Selected || Multiple)
|
||
TextMode(grayishTextOr);
|
||
|
||
MoveTo(Block0.labelPoint.h,Block0.labelPoint.v);
|
||
DrawString(s);
|
||
|
||
if (!HasTwo)
|
||
TextMode(grayishTextOr);
|
||
MoveTo(Block1.labelPoint.h,Block1.labelPoint.v); DrawString(s);
|
||
|
||
TextMode(srcOr);
|
||
TextFace(0);
|
||
DrawFilterDate();
|
||
|
||
r = Rects[flrVBar]; DrawDivider(&r,True);
|
||
|
||
LUpdate(MyGetPortVisibleRegion(WinPort),LHand);
|
||
|
||
wi = ControlWi(Controls[flMatchOnePop]);
|
||
|
||
if (Selected && !Multiple)
|
||
{
|
||
for (i=0,fa=FR[Selected-1].actions;fa && i<MAX_ACTIONS;i++,fa=(*fa)->next)
|
||
{
|
||
r = Rects[flrAct1+i];
|
||
(*(FActionProc*)FATable((*fa)->action))(faeDraw,fa,&r,nil);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
* DrawFilterDate - draw the last use date of a filter
|
||
**********************************************************************/
|
||
void DrawFilterDate(void)
|
||
{
|
||
Str255 string;
|
||
Str63 date;
|
||
Rect r;
|
||
long secs;
|
||
|
||
r = Rects[flrDate];
|
||
EraseRect(&r);
|
||
if (Selected && !Multiple)
|
||
{
|
||
if (secs = FilterLastMatchHi(Selected-1))
|
||
{
|
||
DateString(secs+ZoneSecs(),shortDate,date,nil);
|
||
ComposeRString(string,FILT_DATE_LABEL,date);
|
||
MoveTo(r.right-StringWidth(string),r.bottom);
|
||
DrawString(string);
|
||
}
|
||
}
|
||
}
|
||
|
||
/************************************************************************
|
||
* FiltersMenu - handle our paltry menu item
|
||
************************************************************************/
|
||
Boolean FilterMenu(MyWindowPtr win, int menu, int item, short modifiers)
|
||
{
|
||
switch (menu)
|
||
{
|
||
case FILE_MENU:
|
||
switch(item)
|
||
{
|
||
case FILE_SAVE_ITEM:
|
||
if (win->isDirty) SaveFilters();
|
||
return(True);
|
||
break;
|
||
case FILE_PRINT_ITEM:
|
||
case FILE_PRINT_ONE_ITEM:
|
||
#ifdef GX_PRINTING
|
||
if (gGXIsPresent)
|
||
GXPrintFilters((modifiers&shiftKey)!=0, item==FILE_PRINT_ONE_ITEM);
|
||
else
|
||
#endif //GX_PRINTING
|
||
PrintFilters((modifiers&shiftKey)!=0, item==FILE_PRINT_ONE_ITEM);
|
||
return(True);
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
return(False);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* ActOf - get the number of an action
|
||
**********************************************************************/
|
||
short ActOf(FActionHandle action)
|
||
{
|
||
short i;
|
||
FActionHandle fa;
|
||
|
||
for (i=0,fa=FR[Selected-1].actions;fa;fa=(*fa)->next,i++)
|
||
if (fa==action) break;
|
||
return(i);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FAPopup - find the popup for a given FAction rectangle
|
||
**********************************************************************/
|
||
void FAPopup(Rect *r)
|
||
{
|
||
short v = r->top;
|
||
short h = r->left;
|
||
short diff;
|
||
|
||
GetControlBounds(Controls[flMatchOnePop],r);
|
||
OffsetRect(r,h+INSET-r->left,v+INSET-r->top-1);
|
||
|
||
// how much space is there?
|
||
diff = ActHi-RectHi(*r);
|
||
|
||
if (r->top>v+diff/2) // if space is tight, center
|
||
OffsetRect(r,0,v+diff/2-r->top);
|
||
}
|
||
|
||
/************************************************************************
|
||
* FAPopupValueFit - fit a popup control for a value in a filter action
|
||
************************************************************************/
|
||
void FAPopupValueFit(Rect *r,ControlHandle popup)
|
||
{
|
||
Rect controlR;
|
||
short over;
|
||
|
||
// figure out how big it wants to be
|
||
ButtonFit(popup);
|
||
|
||
// figure out how big we think it should be
|
||
FAPopActRect(r,&controlR);
|
||
|
||
// if it's too tall, move it up a bit
|
||
over = controlR.top + ControlHi(popup) - r->bottom;
|
||
if (over>0) OffsetRect(&controlR,0,-over-2);
|
||
|
||
// move the control into place
|
||
MoveMyCntl(popup,controlR.left,controlR.top,MIN(ControlWi(popup),RectWi(controlR)),0);
|
||
}
|
||
|
||
/************************************************************************
|
||
* FillFilters - fill the list box
|
||
************************************************************************/
|
||
OSErr FillFilters(short startingFrom)
|
||
{
|
||
Str255 name;
|
||
short n = NFilters;
|
||
Point c;
|
||
|
||
c.h = 0;
|
||
|
||
LSetDrawingMode(False,LHand);
|
||
LAddRow(n-startingFrom,n,LHand);
|
||
|
||
for (c.v=startingFrom;c.v<n;c.v++)
|
||
{
|
||
PCopy(name,FR[c.v].name);
|
||
LSetCell(name+1,*name,c,LHand);
|
||
}
|
||
LSetDrawingMode(True,LHand);
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FilterDidResize - resize the filters window
|
||
**********************************************************************/
|
||
void FilterDidResize(MyWindowPtr win, Rect *oldContR)
|
||
{
|
||
#pragma unused(oldContR)
|
||
short mblHeight;
|
||
short x, y;
|
||
Rect r,r2,hiddenRect;
|
||
Str255 s;
|
||
Point cSize;
|
||
Rect listR, matchR, actionR, dateR;
|
||
short wi;
|
||
short i;
|
||
short lineH;
|
||
short popupValue;
|
||
Rect rCntl;
|
||
|
||
ConfigFontSetup(Win);
|
||
|
||
lineH = Win->vPitch+2;
|
||
SetWinMinSize(Win,120+55*Win->hPitch,MIN_MATCH_HI+MIN_ACTION_HI+2*INSET+Win->vPitch);
|
||
|
||
/* Size the buttons early on */
|
||
ButtonFit(NewButton);
|
||
ButtonFit(RemoveButton);
|
||
|
||
/*
|
||
* begin by figuring out the big rectangles
|
||
*/
|
||
listR = win->contR;
|
||
InsetRect(&listR,GROW_SIZE,INSET); /* leave a decent margin */
|
||
matchR = actionR = listR;
|
||
|
||
/* list rectangle needs room for a row of buttons along the bottom */
|
||
listR.bottom -= (2*INSET+ControlHi(NewButton));
|
||
/* list rectangle width */
|
||
listR.right = listR.left + FilterListWidth(RectWi(listR));
|
||
|
||
/* match & action offset from list */
|
||
matchR.left = actionR.left = listR.right + GROW_SIZE;
|
||
/* bit of room off the top */
|
||
matchR.top += Win->vPitch/2+4;
|
||
/* figure out relative heights of the two areas */
|
||
matchR.bottom = matchR.top + FilterMatchHeight(RectHi(matchR));
|
||
actionR.top = matchR.bottom + Win->vPitch + 2 + 4;
|
||
/* leave room near grow box if possible */
|
||
if (actionR.bottom-actionR.top>MIN_ACTION_HI+(GROW_SIZE-INSET))
|
||
actionR.bottom -= GROW_SIZE-INSET;
|
||
|
||
Rects[flrMatch] = matchR;
|
||
Rects[flrAction] = actionR;
|
||
Rects[flrList] = listR;
|
||
|
||
r = actionR; r.top -= GROW_SIZE;
|
||
MySetCntlRect(ActionGroup,&r);
|
||
r = matchR; r.top -= GROW_SIZE;
|
||
MySetCntlRect(MatchGroup,&r);
|
||
|
||
/*
|
||
* new and remove buttons along the bottom
|
||
*/
|
||
MoveMyCntl(NewButton,listR.left,listR.bottom+INSET,0,0);
|
||
MoveMyCntl(RemoveButton,listR.right-ControlWi(RemoveButton),listR.bottom+INSET,0,0);
|
||
|
||
/*
|
||
* set up the rectangle for the vertical separator bar
|
||
*/
|
||
SET_RECT(&Rects[flrVBar],listR.right+INSET,win->contR.top+INSET,listR.right+INSET+2,actionR.bottom);
|
||
|
||
/*
|
||
* the match rectangles
|
||
*/
|
||
mblHeight = MatchBlockHeight(RectHi(matchR));
|
||
SET_RECT(&Rects[flrMatch1],matchR.left+GROW_SIZE,matchR.top+INSET+(3*GROW_SIZE)/2,
|
||
matchR.right-GROW_SIZE,matchR.top+INSET+mblHeight);
|
||
Rects[flrMatch2] = Rects[flrMatch1];
|
||
OFFSET_RECT(&Rects[flrMatch2],0,matchR.bottom - INSET - Rects[flrMatch1].bottom);
|
||
|
||
dateR = actionR;
|
||
dateR.bottom = dateR.top-4;
|
||
dateR.top = dateR.bottom - (SmallSysFontSize()*12)/10;
|
||
dateR.right = Rects[flrMatch1].right;
|
||
dateR.left = (dateR.left+dateR.right)/2;
|
||
Rects[flrDate] = dateR;
|
||
|
||
/*
|
||
* place match controls
|
||
*/
|
||
x = (3*RectWi(Rects[flrMatch1]))/8;
|
||
x = MIN(x,MAX_MATCHPOP_WI);
|
||
x += Rects[flrMatch1].left;
|
||
y = RectHi(Rects[flrMatch1])/2 + Rects[flrMatch1].top;
|
||
|
||
MoveMyCntl(Controls[flMatchOnePop],Rects[flrMatch1].left+INSET,y+MAX_APPEAR_RIM,
|
||
x-Rects[flrMatch1].left-INSET-1,
|
||
lineH+2*TE_VMARGIN);
|
||
GetControlBounds(Controls[flMatchOnePop],&rCntl);
|
||
OFFSET_RECT(&rCntl,0,
|
||
Rects[flrMatch2].bottom-Rects[flrMatch1].bottom);
|
||
SetControlBounds(Controls[flMatchTwoPop],&rCntl);
|
||
|
||
SetControlBounds(Controls[flConjunction],&rCntl);
|
||
MoveControl(Controls[flConjunction],x-RectWi(rCntl)/2,
|
||
(Rects[flrMatch2].top+Rects[flrMatch1].bottom-RectHi(rCntl))/2);
|
||
|
||
/*
|
||
* Place match STE's
|
||
*/
|
||
|
||
SetRect(&hiddenRect,-100,-100,-100,-100);
|
||
|
||
/* value 1 */
|
||
GetControlBounds(Controls[flMatchOnePop],&r);
|
||
r.left = r.right+MIN_APPEAR_SPACE;
|
||
r.right = Rects[flrMatch1].right-INSET;
|
||
r.top += ((r.bottom-r.top)-ONE_LINE_HI(Win))/2;
|
||
r.bottom = r.top+ONE_LINE_HI(Win);
|
||
Rects[flrVal1] = r;
|
||
|
||
popupValue = GetControlValue(Controls[flMatchOnePop]);
|
||
|
||
if (popupValue == mbmAppears || popupValue == mbmNotAppears ||
|
||
popupValue == mbmIntersectsFile || popupValue == mbmNotIntersectsFile)
|
||
{
|
||
PeteDidResize(Block0.valuePTE,&hiddenRect);
|
||
if (popupValue == mbmIntersectsFile || popupValue == mbmNotIntersectsFile)
|
||
FiltSetAndShowNickPop(flNickFilePop1,nil,&r);
|
||
else
|
||
HideControl(Controls[flNickFilePop1]);
|
||
}
|
||
else
|
||
{
|
||
HideControl(Controls[flNickFilePop1]);
|
||
PeteDidResize(Block0.valuePTE,&r);
|
||
}
|
||
|
||
/* value 2 */
|
||
|
||
popupValue = GetControlValue(Controls[flMatchTwoPop]);
|
||
|
||
OffsetRect(&r,0,Rects[flrMatch2].bottom-Rects[flrMatch1].bottom);
|
||
if (popupValue == mbmAppears || popupValue == mbmNotAppears ||
|
||
popupValue == mbmIntersectsFile || popupValue == mbmNotIntersectsFile)
|
||
{
|
||
PeteDidResize(Block1.valuePTE,&hiddenRect);
|
||
if (popupValue == mbmIntersectsFile || popupValue == mbmNotIntersectsFile)
|
||
FiltSetAndShowNickPop(flNickFilePop2,nil,&r);
|
||
else
|
||
HideControl(Controls[flNickFilePop1]);
|
||
}
|
||
else
|
||
{
|
||
HideControl(Controls[flNickFilePop2]);
|
||
PeteDidResize(Block1.valuePTE,&r);
|
||
}
|
||
Rects[flrVal2] = r;
|
||
|
||
/* header 2 */
|
||
OffsetRect(&r,0,y-Rects[flrMatch1].bottom+3);
|
||
r.right = r.left + (2*(r.right-r.left))/3;
|
||
PeteDidResize(Block1.headerPTE,&r);
|
||
Block1.labelPoint.h = x-StringWidth(GetRString(s,HEADER_LABEL))-2;
|
||
Block1.labelPoint.v = r.top+SmallSysFontSize()+TE_VMARGIN;
|
||
|
||
/* header 1 */
|
||
OffsetRect(&r,0,Rects[flrMatch1].bottom-Rects[flrMatch2].bottom);
|
||
PeteDidResize(Block0.headerPTE,&r);
|
||
Block0.labelPoint = Block1.labelPoint;
|
||
Block0.labelPoint.v += Rects[flrMatch1].bottom-Rects[flrMatch2].bottom;
|
||
|
||
/* accel 1 */
|
||
r.left = r.right+4;
|
||
r.right = r.left+GROW_SIZE;
|
||
r.bottom = r.top+GROW_SIZE;
|
||
InsetRect(&r,0,4);
|
||
Rects[flrAccel1] = r;
|
||
MySetCntlRect(Controls[flAccel1],&r);
|
||
//ShowControl(Controls[flAccel1]);
|
||
|
||
/* accel 2 */
|
||
OffsetRect(&r,0,Rects[flrMatch2].bottom-Rects[flrMatch1].bottom);
|
||
Rects[flrAccel2] = r;
|
||
MySetCntlRect(Controls[flAccel2],&r);
|
||
//ShowControl(Controls[flAccel2]);
|
||
|
||
/*
|
||
* incoming, outgoing, and manual buttons
|
||
*/
|
||
x = Rects[flrMatch1].left;
|
||
wi = (Rects[flrMatch1].right-x-2*INSET)/3;
|
||
y = matchR.top+INSET;
|
||
MoveMyCntl(Controls[flIncoming],x,y,wi,lineH);
|
||
MoveMyCntl(Controls[flOutgoing],x+wi+INSET,y,wi,lineH);
|
||
MoveMyCntl(Controls[flManual],x+2*(wi+INSET),y,wi,lineH);
|
||
|
||
/*
|
||
* list itself
|
||
*/
|
||
r = Rects[flrList];
|
||
r.right -= GROW_SIZE;
|
||
InsetRect(&r,1,1);
|
||
cSize.h = r.right-r.left;
|
||
cSize.v = lineH;
|
||
r.bottom = r.top + (RectHi(r)/lineH)*lineH;
|
||
ResizeList(LHand,&r,cSize);
|
||
r.right += GROW_SIZE;
|
||
InsetRect(&r,-1,-1);
|
||
Rects[flrList] = r;
|
||
|
||
|
||
/*
|
||
* action rectangles
|
||
*/
|
||
r = Rects[flrMatch1];
|
||
SetFASpacings(Rects[flrAction].bottom-Rects[flrAction].top);
|
||
r.top = Rects[flrAction].top + ActSpace;
|
||
r.bottom = r.top + ActHi;
|
||
for (i=flrAct1;i<flrAct1+MAX_ACTIONS;i++)
|
||
{
|
||
Rects[i] = r2 = r;
|
||
OffsetRect(&r,0,ActSpace+ActHi);
|
||
|
||
// FAPopup(&r2);
|
||
{
|
||
short v = r2.top;
|
||
short h = r2.left;
|
||
short diff;
|
||
|
||
GetControlBounds(Controls[flAct1+i-flrAct1],&rCntl);
|
||
r2.top = rCntl.top;
|
||
r2.bottom = rCntl.bottom;
|
||
GetControlBounds(Controls[flMatchOnePop],&rCntl);
|
||
r2.left = rCntl.left;
|
||
r2.right = rCntl.right;
|
||
OffsetRect (&r2,h+INSET-r2.left,v+INSET-r2.top-1);
|
||
|
||
// how much space is there?
|
||
diff = ActHi-RectHi(r2);
|
||
|
||
if (r2.top>v+diff/2) // if space is tight, center
|
||
OffsetRect(&r2,0,v+diff/2-r2.top);
|
||
}
|
||
|
||
MySetCntlRect(Controls[flAct1+i-flrAct1],&r2);
|
||
}
|
||
|
||
if (ActRgn)
|
||
{
|
||
/* big box */
|
||
r = Rects[flrAct1];
|
||
InsetRect(&r,1,1);
|
||
RectRgn(ActRgn,&r);
|
||
|
||
/* outside of little box */
|
||
r = Rects[flrAct1];
|
||
FAPopup(&r);
|
||
InsetRect(&r,-1,-1);
|
||
r.bottom += 1;
|
||
RgnMinusRect(ActRgn,&r);
|
||
|
||
/* inside of little box */
|
||
InsetRect(&r,2,3);
|
||
r.top -= 1;
|
||
RgnPlusRect(ActRgn,&r);
|
||
}
|
||
|
||
ForAllActionsDo(faeResize,nil);
|
||
|
||
/*
|
||
* wipe it
|
||
*/
|
||
for (i=0;i<flLimit;i++) if (Controls[i]) SetControlVisibility(Controls[i],true,false);
|
||
InvalContent(win);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* SetFASpacings - set the spacings for filter actions
|
||
**********************************************************************/
|
||
void SetFASpacings(short total)
|
||
{
|
||
short hi;
|
||
short space;
|
||
|
||
/*
|
||
* this code looks weird. this code is weird. ha ha! joke's on you.
|
||
*/
|
||
space = 2*INSET/3;
|
||
hi = (total-(MAX_ACTIONS+1)*space)/MAX_ACTIONS;
|
||
hi = MIN(hi,MAX_ACT1_HI);
|
||
hi = MAX(hi,MIN_ACT1_HI);
|
||
space = (total-MAX_ACTIONS*hi)/(MAX_ACTIONS+1);
|
||
space = MIN(space,(4*INSET)/3);
|
||
hi = (total-(MAX_ACTIONS+1)*space)/MAX_ACTIONS;
|
||
|
||
ActSpace = space;
|
||
ActHi = hi;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FilterListWidth - figure out the width of the filter list box
|
||
**********************************************************************/
|
||
short FilterListWidth(short total)
|
||
{
|
||
short width = GetPrefLong(PREF_F_LIST_WIDE);
|
||
if (width==0) width = (GetRLong(FILTER_LIST_PERCENT)*total)/100;
|
||
if (total-width<MIN_ACTION_WI) width = total-MIN_ACTION_WI;
|
||
return(width);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FilterMatchHeight - find height of the match region
|
||
**********************************************************************/
|
||
short FilterMatchHeight(short total)
|
||
{
|
||
short extra;
|
||
short hi;
|
||
extra = total - MIN_MATCH_HI - MIN_ACTION_HI - GROW_SIZE;
|
||
hi = MIN_MATCH_HI + (2*extra)/5;
|
||
hi = MIN(hi,MAX_MATCH_HI);
|
||
return(hi);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* MatchBlockHeight - return the height of a single match block
|
||
**********************************************************************/
|
||
short MatchBlockHeight(short total)
|
||
{
|
||
short extra = total-MIN_MATCH_HI;
|
||
extra = MAX(extra,0);
|
||
return((MIN_MATCH_HI-2*INSET-(3*GROW_SIZE)/2)/2 + 2*extra/5);
|
||
}
|
||
|
||
/************************************************************************
|
||
* FiltersSetGreys - set the greys for controls
|
||
************************************************************************/
|
||
void FiltersSetGreys(void)
|
||
{
|
||
FilterControlEnum fl;
|
||
|
||
if (!Selected) // Grey all controls except new button
|
||
for(fl=0;fl<flLimit;fl++) SetGreyControl(Controls[fl],fl!=flNewButton);
|
||
else if (Multiple)
|
||
{
|
||
// Grey controls from the incoming button to the end of the list
|
||
for(fl=0;fl<flIncoming;fl++) SetGreyControl(Controls[fl],False);
|
||
for(fl=flIncoming;fl<flLimit;fl++) SetGreyControl(Controls[fl],True);
|
||
}
|
||
else
|
||
{
|
||
if (HasTwo)
|
||
for (fl=0;fl<flLimit;fl++) SetGreyControl(Controls[fl],False);
|
||
else
|
||
for (fl=0;fl<flLimit;fl++) SetGreyControl(Controls[fl],fl==flMatchTwoPop);
|
||
}
|
||
}
|
||
|
||
#pragma segment Main
|
||
/************************************************************************
|
||
* FiltersClose - close the window
|
||
************************************************************************/
|
||
Boolean FiltersClose(MyWindowPtr win)
|
||
{
|
||
#pragma unused(win)
|
||
if (FLG && *FLG)
|
||
{
|
||
int which=WANNA_SAVE_SAVE;
|
||
|
||
if (!GrowZoning)
|
||
{
|
||
SaveCurrentFilter();
|
||
if (Win && Win->isDirty)
|
||
{
|
||
which = WannaSave(Win);
|
||
if (which==CANCEL_ITEM || which == WANNA_SAVE_SAVE && SaveFilters()) return(False);
|
||
}
|
||
|
||
if (which==WANNA_SAVE_DISCARD)
|
||
{
|
||
FiltersRefCount = 0;
|
||
ZapFilters();
|
||
}
|
||
}
|
||
|
||
if (ActionMenu)
|
||
{
|
||
DeleteMenu(FLA_MENU);
|
||
ReleaseResource_(ActionMenu);
|
||
}
|
||
|
||
LDRef(FLG);
|
||
if (LHand) LDispose(LHand);
|
||
FiltersDecRef();
|
||
if (ActRgn) DisposeRgn(ActRgn);
|
||
ZapHandle(FLG);
|
||
}
|
||
return(True);
|
||
}
|
||
|
||
|
||
/**********************************************************************
|
||
* FilterWindowClean - set the clean of the fitler window
|
||
**********************************************************************/
|
||
void FilterWindowClean(Boolean clean)
|
||
{
|
||
if (FLG && Win) Win->isDirty = !clean;
|
||
}
|
||
|
||
#pragma segment FilterWin
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
Boolean FiltWinOpen(void)
|
||
{
|
||
return(FLG && Win);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FilterIsSelected - is a filter selected?
|
||
**********************************************************************/
|
||
Boolean FilterIsSelected(short which)
|
||
{
|
||
return FLG && Cell1Selected(which+1,LHand);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
void FiltClickHook(short cell,ListHandle lHand)
|
||
{
|
||
Point c;
|
||
short oldCell;
|
||
|
||
if (cell && cell<=(*lHand)->dataBounds.bottom)
|
||
{
|
||
if (MainEvent.modifiers&cmdKey)
|
||
{
|
||
c.h = 0;
|
||
c.v = cell-1;
|
||
LSetSelect(!Cell1Selected(cell,lHand),c,lHand);
|
||
ActOnFilterSelect();
|
||
}
|
||
else if (!Cell1Selected(cell,lHand))
|
||
{
|
||
if (MainEvent.modifiers&shiftKey)
|
||
{
|
||
oldCell = Next1Selected(0,lHand);
|
||
if (oldCell && oldCell<cell)
|
||
oldCell--; // Next1Selected is 1-based
|
||
else if (oldCell>cell)
|
||
{
|
||
c.v = cell-1;
|
||
cell = oldCell-1;
|
||
oldCell = c.v;
|
||
}
|
||
else oldCell = --cell;
|
||
|
||
c.h = 0;
|
||
for (c.v=oldCell;c.v<cell;c.v++) LSetSelect(True,c,lHand);
|
||
ActOnFilterSelect();
|
||
}
|
||
else
|
||
FilterSelect(cell-1);
|
||
}
|
||
}
|
||
else
|
||
FilterSelect(-1);
|
||
}
|
||
|
||
/************************************************************************
|
||
* FilterClick - handle a click in the filter window
|
||
************************************************************************/
|
||
void FilterClick(MyWindowPtr win, EventRecord *event)
|
||
{
|
||
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
||
Point pt = event->where;
|
||
Rect r;
|
||
PETEHandle pte = nil;
|
||
FActionHandle fa;
|
||
short i;
|
||
Boolean drag;
|
||
ControlHandle cntl;
|
||
long controlId = -1;
|
||
|
||
GlobalToLocal(&pt);
|
||
|
||
r = Rects[flrAction];
|
||
if (PtInRect(pt,&r))
|
||
{
|
||
ForAllActionsDo(faeMouseGoingDown,nil);
|
||
}
|
||
r = Rects[flrList];
|
||
if (PtInRect(pt,&r))
|
||
{
|
||
LClickWDrag(pt,event->modifiers,LHand,&drag,FiltClickHook);
|
||
if (drag) FiltDoDrag(event);
|
||
ActOnFilterSelect();
|
||
}
|
||
else if ((r = Rects[flrVBar]),PtInSloppyRect(pt,&r,1))
|
||
{
|
||
FiltDragDivider(pt);
|
||
}
|
||
else if (FindControl(pt,winWP,&cntl) && (GetControlReference(cntl)&0xffffff00)=='act\0')
|
||
{
|
||
FActionPopUp(pt,cntl);
|
||
controlId = GetControlReference(cntl);
|
||
}
|
||
else if (HandleControl(pt,win))
|
||
;
|
||
else if (Selected && !Multiple)
|
||
{
|
||
if ((r=Rects[flrAccel1]),PtInRect(pt,&r))
|
||
{
|
||
AccelPopUp(Block0.headerPTE,Controls[flMatchOnePop],r.top,r.left);
|
||
controlId = AUDITCONTROLID(GetWindowKind(winWP),flAccel1);
|
||
}
|
||
else if (HasTwo && ((r=Rects[flrAccel2]),PtInRect(pt,&r)))
|
||
{
|
||
AccelPopUp(Block1.headerPTE,Controls[flMatchTwoPop],r.top,r.left);
|
||
controlId = AUDITCONTROLID(GetWindowKind(winWP),flAccel2);
|
||
}
|
||
else if (PtInPETE(pt,Block0.headerPTE)) pte = Block0.headerPTE;
|
||
else if (PtInPETE(pt,Block0.valuePTE)) pte = Block0.valuePTE;
|
||
else if (HasTwo && PtInPETE(pt,Block1.headerPTE)) pte = Block1.headerPTE;
|
||
else if (HasTwo && PtInPETE(pt,Block1.valuePTE)) pte = Block1.valuePTE;
|
||
else
|
||
for (i=0,fa=FR[Selected-1].actions;fa;fa=(*fa)->next,i++)
|
||
{
|
||
r = Rects[flrAct1+i];
|
||
if (PtInRect(pt,&r))
|
||
{
|
||
((*(FActionProc*)FATable((*fa)->action)))(faeClick,fa,(Rect*)&pt,event);
|
||
break;
|
||
}
|
||
}
|
||
if (pte) PeteEditWFocus(Win,pte,peeEvent,(void*)event,nil);
|
||
}
|
||
|
||
FiltEnableVerbAll();
|
||
|
||
if (controlId >= 0)
|
||
AuditHit((event->modifiers&shiftKey)!=0, (event->modifiers&controlKey)!=0, (event->modifiers&optionKey)!=0, (event->modifiers&cmdKey)!=0, false, GetWindowKind(winWP), controlId, event->what);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FiltDoDrag - drag some filters
|
||
**********************************************************************/
|
||
OSErr FiltDoDrag(EventRecord *event)
|
||
{
|
||
Point p = event->where;
|
||
short theCell;
|
||
short n = NFilters;
|
||
DragReference drag;
|
||
OSErr err = noErr;
|
||
Handle data;
|
||
RgnHandle rgn;
|
||
PromiseHFSFlavor promise;
|
||
FSSpec spec; // we may write here
|
||
DECLARE_UPP(FiltDragSend,DragSendData);
|
||
|
||
INIT_UPP(FiltDragSend,DragSendData);
|
||
|
||
GlobalToLocal(&p);
|
||
theCell = InWhich1Cell(p,LHand);
|
||
|
||
if (theCell>n)
|
||
LClick(p,event->modifiers,LHand);
|
||
else
|
||
{
|
||
if (!Cell1Selected(theCell,LHand))
|
||
FilterSelect(theCell-1);
|
||
if (!(err=MyNewDrag(Win,&drag)))
|
||
{
|
||
if (!(data=NuHTempBetter(0)))
|
||
err = MemError();
|
||
else if (!(rgn=MyLDragRgn(LHand)))
|
||
err = MemError();
|
||
else
|
||
{
|
||
for (theCell=0;theCell=Next1Selected(theCell,LHand);)
|
||
if (err=PtrPlusHand(&theCell,data,sizeof(theCell))) break;
|
||
|
||
// Setup the promiseHFS
|
||
Zero(promise);
|
||
promise.fileType = FILTER_FTYPE;
|
||
promise.fileCreator = CREATOR;
|
||
promise.promisedFlavor = SPEC_FLAVOR;
|
||
Zero(spec);
|
||
|
||
if (!(err=FinderDragVoodoo(drag))) // bad finder. bad.
|
||
if (!err)
|
||
{
|
||
// add the cell data for internal drags
|
||
err = AddDragItemFlavor(drag,1,FILT_DRAG_DATA_TYPE,
|
||
LDRef(data),GetHandleSize(data),
|
||
flavorSenderOnly|flavorNotSaved);
|
||
ZapHandle(data);
|
||
if (!err)
|
||
// add the promiseHFS
|
||
if (!(err=AddDragItemFlavor(drag,1,flavorTypePromiseHFS,&promise,sizeof(promise),0)))
|
||
// add an flavor to hold the spec we're supposed to write to
|
||
if (!(err=AddDragItemFlavor(drag,1,SPEC_FLAVOR,nil,0,0)))
|
||
// now the proc that really does the work if somebody takes us up on our promise
|
||
if (!(err=SetDragSendProc(drag,FiltDragSendUPP,(void*)&spec)))
|
||
{
|
||
// finally actually track the drag
|
||
if (!(err=MyTrackDrag(drag,event,rgn)))
|
||
{
|
||
if (*spec.name)
|
||
{
|
||
// We need to write selected filters to this file
|
||
err = SaveFiltersLo(&spec,false,false);
|
||
}
|
||
}
|
||
}
|
||
DisposeRgn(rgn);
|
||
}
|
||
}
|
||
MyDisposeDrag(drag);
|
||
}
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FiltDragSend - drag data proc for filters
|
||
**********************************************************************/
|
||
pascal OSErr FiltDragSend(FlavorType flavor, void *dragSendRefCon, ItemReference theItemRef, DragReference drag)
|
||
{
|
||
AEDesc dropLocation;
|
||
OSErr err=cantGetFlavorErr;
|
||
FSSpecPtr spec = (FSSpecPtr)dragSendRefCon;
|
||
|
||
/*
|
||
* return the filename
|
||
*/
|
||
if (flavor==SPEC_FLAVOR)
|
||
{
|
||
NullADList(&dropLocation,nil);
|
||
if (!(err=GetDropLocation(drag,&dropLocation)))
|
||
if (!(err=GetDropLocationDirectory(&dropLocation,&spec->vRefNum,&spec->parID)))
|
||
{
|
||
FiltDragFilename(spec->name);
|
||
UniqueSpec(spec,31);
|
||
FSpCreateResFile(spec,CREATOR,FILTER_FTYPE,smSystemScript);
|
||
WhackFinder(spec);
|
||
if (!(err = ResError()))
|
||
err = MySetDragItemFlavorData(drag,1,SPEC_FLAVOR,spec,sizeof(FSSpec));
|
||
}
|
||
DisposeADList(&dropLocation,nil);
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FiltDragFilename - setup a filename for the target of a filter drag
|
||
**********************************************************************/
|
||
void FiltDragFilename(PStr name)
|
||
{
|
||
#ifdef TO_DO
|
||
#pragma warning Need to write better naming function for filter drags
|
||
#endif
|
||
GetRString(name,FILTERS_NAME);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FiltDragHandler - drag handler for filters window
|
||
**********************************************************************/
|
||
OSErr FiltDragHandler(MyWindowPtr win,DragTrackingMessage which,DragReference drag)
|
||
{
|
||
OSErr err=noErr;
|
||
Point mouse;
|
||
Rect r;
|
||
short stice;
|
||
static short flags;
|
||
|
||
if (drag!=OldDrag)
|
||
{
|
||
Boolean interesting, me, draggingFile;
|
||
interesting = DragIsInteresting(drag,FILT_DRAG_DATA_TYPE,nil);
|
||
if (!interesting) draggingFile = interesting = DragIsInterestingFileType(drag,nil,FILTER_FTYPE,nil);
|
||
else draggingFile = false;
|
||
flags = ldtInterstice;
|
||
if (draggingFile) flags |= ldtIgnoreSelection;
|
||
me = DragSource==win;
|
||
DragInteresting = interesting;
|
||
OldDrag = drag;
|
||
DragFromMe = me;
|
||
}
|
||
|
||
if (!DragInteresting) return(Selected ? dragNotAcceptedErr:1);
|
||
|
||
if (which==0xfff) HideDragHilite(drag);
|
||
|
||
SetPort(GetMyWindowCGrafPtr(Win));
|
||
GetDragMouse(drag,&mouse,nil);
|
||
GlobalToLocal(&mouse);
|
||
|
||
switch (which)
|
||
{
|
||
case 0xfff:
|
||
case kDragTrackingInWindow:
|
||
if (DragInteresting)
|
||
{
|
||
r = Rects[flrList];
|
||
r.right -= GROW_SIZE;
|
||
InsetRect(&r,0,-GROW_SIZE);
|
||
if (PtInRect(mouse,&r))
|
||
{
|
||
stice = MyLDragTracker(drag,mouse,flags,LHand);
|
||
if (stice==-1) err = dragNotAcceptedErr;
|
||
else if (which==0xfff)
|
||
{
|
||
HideDragHilite(drag);
|
||
if (DragInteresting) err = FiltDrop(stice,drag);
|
||
else err == dragNotAcceptedErr;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case kDragTrackingLeaveWindow:
|
||
HideDragHilite(drag);
|
||
break;
|
||
}
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FiltDrop - handle a drop onto filters
|
||
**********************************************************************/
|
||
OSErr FiltDrop(short stice,DragReference drag)
|
||
{
|
||
short n = NFilters;
|
||
short **data;
|
||
FRHandle fr = nil;
|
||
OSErr err;
|
||
|
||
ASSERT(MyCountDragItems(drag)==1);
|
||
|
||
SaveCurrentFilter();
|
||
|
||
if (!(err=MyGetDragItemData(drag,1,FILT_DRAG_DATA_TYPE,(Handle*)&data)))
|
||
{
|
||
ZapHandle(data);
|
||
err = MoveSelectedFilters(stice);
|
||
}
|
||
else
|
||
err = FiltDropFile(stice,drag);
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
OSErr FiltDropFile(short stice,DragReference drag)
|
||
{
|
||
short item;
|
||
OSErr err=noErr;
|
||
HFSFlavor **data;
|
||
FSSpec spec;
|
||
short n = MyCountDragItems(drag);
|
||
short oldN = NFilters;
|
||
|
||
// Add the filters to the filter structure
|
||
for (item=1;item<=n && !err;item++) // loop through each item
|
||
{
|
||
if (!(err=MyGetDragItemData(drag,item,flavorTypeHFS,(void*)&data)))
|
||
{
|
||
spec = (*data)->fileSpec;
|
||
ZapHandle(data);
|
||
err = ReadFilters(Filters,spec.vRefNum,spec.parID,spec.name);
|
||
}
|
||
}
|
||
|
||
// Add the filters to the list in the window
|
||
n = NFilters - oldN;
|
||
if (n>0)
|
||
{
|
||
FillFilters(oldN);
|
||
FiltRedoList(oldN,n);
|
||
MoveSelectedFilters(stice);
|
||
}
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FiltSetAndShowNickPop - populate the nickname file popup and move it into place
|
||
**********************************************************************/
|
||
OSErr FiltSetAndShowNickPop(FilterControlEnum pop,PStr value,Rect *r)
|
||
{
|
||
// if we're passed with a string, set the contents
|
||
// of the menu and its value
|
||
if (value)
|
||
{
|
||
MenuHandle mh;
|
||
short ab;
|
||
Str63 name;
|
||
short val = 1;
|
||
|
||
if (mh = GetControlPopupMenuHandle(Controls[pop]))
|
||
{
|
||
TrashMenu(mh,1);
|
||
// The address book menu will consist of only the following:
|
||
// Eudora Nicknames
|
||
// Regular Address Books
|
||
// History List
|
||
// <09>Any<6E>
|
||
GetRString(name,ANY_ALIAS_FILE);
|
||
MyAppendMenu(mh,name);
|
||
for (ab = 0; ab < NAliases; ++ab)
|
||
if (IsEudoraAddressBook (ab) || IsRegularAddressBook (ab) || IsHistoryAddressBook (ab))
|
||
{
|
||
PCopy(name,(*Aliases)[ab].spec.name);
|
||
MyAppendMenu (mh,name);
|
||
if (StringSame(name,value)) val = CountMenuItems(mh);
|
||
}
|
||
|
||
SetControlMaximum (Controls[pop], CountMenuItems (mh));
|
||
SetControlMinimum (Controls[pop], 1);
|
||
SetControlValue (Controls[pop], val);
|
||
}
|
||
}
|
||
|
||
MySetCntlRect(Controls[pop],r);
|
||
ShowControl(Controls[pop]);
|
||
return noErr;
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
OSErr MoveSelectedFilters(short stice)
|
||
{
|
||
short fNum;
|
||
short nSelected=0;
|
||
FRHandle fr=nil;
|
||
short i;
|
||
short spot;
|
||
short goodSpot;
|
||
short n = NFilters;
|
||
|
||
for (fNum=0;fNum<n;fNum++)
|
||
if (Cell1Selected(fNum+1,LHand))
|
||
{
|
||
FR[fNum].kill = true;
|
||
nSelected++;
|
||
}
|
||
|
||
if (fr=NuHTempBetter(sizeof(FilterRecord)*nSelected))
|
||
{
|
||
/*
|
||
* copy out the filters in question
|
||
*/
|
||
i=0;
|
||
for (fNum=0;fNum<n;fNum++)
|
||
if (FR[fNum].kill)
|
||
{
|
||
(*fr)[i] = FR[fNum];
|
||
(*fr)[i].kill = false;
|
||
i++;
|
||
}
|
||
|
||
/*
|
||
* where will the new spot be?
|
||
*/
|
||
spot = 0;
|
||
for (fNum=0;fNum<stice;fNum++) if (!FR[fNum].kill) spot++;
|
||
|
||
/*
|
||
* move the ones that belong before
|
||
*/
|
||
for (fNum=goodSpot=0;goodSpot<spot && fNum<n;fNum++)
|
||
{
|
||
if (FR[fNum].kill) continue; //will be overwritten
|
||
if (fNum!=goodSpot) FR[goodSpot]=FR[fNum]; //filter ok, copy into place
|
||
goodSpot++; //found another good one
|
||
}
|
||
|
||
/*
|
||
* move the ones that belong after
|
||
*/
|
||
for (goodSpot=fNum=n-1;goodSpot>=spot+nSelected;fNum--)
|
||
{
|
||
if (FR[fNum].kill) continue; //will be overwritten
|
||
if (fNum!=goodSpot) FR[goodSpot] = FR[fNum]; //filter ok, copy into place
|
||
goodSpot--; //found another good one
|
||
}
|
||
|
||
/*
|
||
* now, move them into place
|
||
*/
|
||
BMD(*fr,&FR[spot],nSelected*sizeof(FilterRecord));
|
||
ZapHandle(fr);
|
||
|
||
/*
|
||
* cleanup
|
||
*/
|
||
if (nSelected==1 && Selected && !Multiple) Selected = spot+1;
|
||
FiltRedoList(spot,nSelected);
|
||
|
||
return noErr;
|
||
}
|
||
return MemError();
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
void FiltRedoList(short startSel,short nSel)
|
||
{
|
||
Point c;
|
||
short n = NFilters;
|
||
Str255 title;
|
||
|
||
c.h = 0;
|
||
|
||
/*
|
||
* retitle every cell
|
||
*/
|
||
for (c.v=0;c.v<n;c.v++)
|
||
{
|
||
PCopy(title,FR[c.v].name);
|
||
LSetCell(title+1,*title,c,LHand);
|
||
LSetSelect(False,c,LHand);
|
||
}
|
||
|
||
/*
|
||
* select the newly selected ones
|
||
*/
|
||
for (c.v=startSel;c.v<startSel+nSel;c.v++)
|
||
LSetSelect(True,c,LHand);
|
||
|
||
/*
|
||
* neaten
|
||
*/
|
||
ActOnFilterSelect();
|
||
|
||
/*
|
||
* redraw them on update
|
||
*/
|
||
Win->isDirty = True;
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
void FiltDragDivider(Point pt)
|
||
{
|
||
Rect div, bounds;
|
||
Point newPt;
|
||
|
||
div = Rects[flrVBar];
|
||
bounds = Win->contR;
|
||
bounds.right = RectWi(Win->contR)-MIN_ACTION_WI;
|
||
bounds.left = (GetRLong(FILT_LIST_MIN)*Win->minSize.h)/100;
|
||
|
||
newPt = DragDivider(pt,&div,&bounds,Win);
|
||
|
||
/*
|
||
* resize?
|
||
*/
|
||
if (newPt.h)
|
||
{
|
||
SetPrefLong(PREF_F_LIST_WIDE,newPt.h-GROW_SIZE-INSET);
|
||
MyWindowDidResize(Win,nil);
|
||
}
|
||
}
|
||
|
||
/************************************************************************
|
||
* FilterButton - handle hits on the buttons.
|
||
************************************************************************/
|
||
void FilterButton(MyWindowPtr win,ControlHandle button,long modifiers,short part)
|
||
{
|
||
#pragma unused(modifiers,part)
|
||
FilterControlEnum which;
|
||
Rect r,hiddenRect;
|
||
short popupValue;
|
||
Boolean wasFilterActionButton = false;
|
||
|
||
SetRect(&hiddenRect,-100,-100,-100,ONE_LINE_HI(Win)-100);
|
||
|
||
for (which=flNewButton;which<flLimit;which++)
|
||
if (button==Controls[which]) break;
|
||
|
||
switch(which)
|
||
{
|
||
case flRemoveButton:
|
||
RemoveSelectedFilters();
|
||
break;
|
||
|
||
case flNewButton:
|
||
AddFilter(Selected?Selected:NFilters);
|
||
break;
|
||
|
||
case flIncoming:
|
||
case flOutgoing:
|
||
case flManual:
|
||
MySetCtlValue(Controls[which],!GetControlValue(Controls[which]));
|
||
Win->isDirty = CurrentDirty = True;
|
||
break;
|
||
|
||
case flMatchOnePop:
|
||
Win->isDirty = CurrentDirty = True;
|
||
/* value 1 */
|
||
r = Rects[flrVal1];
|
||
|
||
popupValue = GetControlValue(Controls[flMatchOnePop]);
|
||
|
||
if (popupValue == mbmAppears || popupValue == mbmNotAppears ||
|
||
popupValue == mbmIntersectsFile || popupValue == mbmNotIntersectsFile)
|
||
{
|
||
PeteDidResize(Block0.valuePTE,&hiddenRect);
|
||
if (popupValue == mbmIntersectsFile || popupValue == mbmNotIntersectsFile)
|
||
FiltSetAndShowNickPop(flNickFilePop1,"",&r);
|
||
else
|
||
HideControl(Controls[flNickFilePop1]);
|
||
}
|
||
else
|
||
{
|
||
HideControl(Controls[flNickFilePop1]);
|
||
PeteDidResize(Block0.valuePTE,&r);
|
||
}
|
||
InsetRect(&r,-3,-3);
|
||
InvalWindowRect(GetMyWindowWindowPtr(win),&r);
|
||
break;
|
||
|
||
case flMatchTwoPop:
|
||
Win->isDirty = CurrentDirty = True;
|
||
/* value 2 */
|
||
popupValue = GetControlValue(Controls[flMatchTwoPop]);
|
||
r = Rects[flrVal2];
|
||
|
||
if (popupValue == mbmAppears || popupValue == mbmNotAppears ||
|
||
popupValue == mbmIntersectsFile || popupValue == mbmNotIntersectsFile)
|
||
{
|
||
PeteDidResize(Block1.valuePTE,&hiddenRect);
|
||
if (popupValue == mbmIntersectsFile || popupValue == mbmNotIntersectsFile)
|
||
FiltSetAndShowNickPop(flNickFilePop2,"",&r);
|
||
else
|
||
HideControl(Controls[flNickFilePop2]);
|
||
}
|
||
else
|
||
{
|
||
HideControl(Controls[flNickFilePop2]);
|
||
PeteDidResize(Block1.valuePTE,&r);
|
||
}
|
||
InsetRect(&r,-3,-3);
|
||
InvalWindowRect(GetMyWindowWindowPtr(win),&r);
|
||
|
||
break;
|
||
|
||
case flNickFilePop1:
|
||
case flNickFilePop2:
|
||
Win->isDirty = CurrentDirty = True;
|
||
break;
|
||
|
||
case flConjunction:
|
||
if (HasTwo != (GetControlValue(Controls[flConjunction])!=cjIgnore))
|
||
{
|
||
InvalMatch2();
|
||
HasTwo = !HasTwo;
|
||
FiltersSetGreys();
|
||
if (!HasTwo && (Win->pte==Block1.headerPTE || Win->pte==Block1.valuePTE))
|
||
{
|
||
PeteFocus(Win,Block0.headerPTE,True);
|
||
PeteSelectAll(Win,Win->pte);
|
||
Win->hasSelection = MyWinHasSelection(Win);
|
||
}
|
||
}
|
||
Win->isDirty = CurrentDirty = True;
|
||
break;
|
||
|
||
default:
|
||
if (FilterActionButton(button,modifiers))
|
||
Win->isDirty = CurrentDirty = True;
|
||
wasFilterActionButton = true;
|
||
break;
|
||
}
|
||
|
||
// Audit the non-filter action button controls.
|
||
if (!wasFilterActionButton)
|
||
AuditHit((modifiers&shiftKey)!=0, (modifiers&controlKey)!=0, (modifiers&optionKey)!=0, (modifiers&cmdKey)!=0, false, GetWindowKind (GetMyWindowWindowPtr (win)), AUDITCONTROLID(GetWindowKind (GetMyWindowWindowPtr (win)),which), mouseDown);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* RemoveSelectedFilters - remove the current set of filters
|
||
**********************************************************************/
|
||
void RemoveSelectedFilters(void)
|
||
{
|
||
short cell;
|
||
short selectMe=0;
|
||
Rect r;
|
||
|
||
cell=1;
|
||
while (cell=Next1Selected(cell-1,LHand))
|
||
{
|
||
RemoveFilterLo(cell-1);
|
||
if (!selectMe) selectMe = cell;
|
||
}
|
||
if (NFilters)
|
||
FilterSelect(selectMe-1);
|
||
else
|
||
{
|
||
FilterSelect(0);
|
||
DisplaySelectedFilter();
|
||
FiltersSetGreys();
|
||
r = Win->contR;
|
||
InvalWindowRect(GetMyWindowWindowPtr(Win),&r);
|
||
}
|
||
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FilterActionButton - is the given click in one of an action's buttons?
|
||
**********************************************************************/
|
||
Boolean FilterActionButton(ControlHandle button,short modifiers)
|
||
{
|
||
Boolean retVal = False;
|
||
FActionHandle fa;
|
||
short i;
|
||
Point pt;
|
||
Rect r;
|
||
|
||
GetControlBounds(button,&r);
|
||
pt.h = (r.left+r.right)/2;
|
||
pt.v = (r.top+r.bottom)/2;
|
||
|
||
if (Selected && !Multiple)
|
||
{
|
||
for (i=0,fa=FR[Selected-1].actions;fa && i<MAX_ACTIONS;fa=(*fa)->next,i++)
|
||
{
|
||
r = Rects[flrAct1+i];
|
||
if (PtInRect(pt,&r))
|
||
{
|
||
(*(FActionProc*)FATable((*fa)->action))(faeButton,fa,(void*)&modifiers,button);
|
||
return(True);
|
||
}
|
||
}
|
||
}
|
||
return retVal;
|
||
}
|
||
|
||
/************************************************************************
|
||
* FilterSwap - swap two filters
|
||
************************************************************************/
|
||
void FilterSwap(short i, short j)
|
||
{
|
||
FilterRecord fi,fj;
|
||
Point pi, pj;
|
||
Boolean iSelect, jSelect;
|
||
|
||
/*
|
||
* make local copies
|
||
*/
|
||
pi.h = pj.h = 0;
|
||
pi.v = i;
|
||
pj.v = j;
|
||
fi = FR[i];
|
||
fj = FR[j];
|
||
iSelect = LGetSelect(False,&pi,LHand);
|
||
jSelect = LGetSelect(False,&pj,LHand);
|
||
|
||
/*
|
||
* swap data in the handle
|
||
*/
|
||
FR[j] = fi;
|
||
FR[i] = fj;
|
||
|
||
/*
|
||
* swap data in the list
|
||
*/
|
||
LSetCell(fj.name+1,*fj.name,pi,LHand);
|
||
LSetSelect(jSelect,pi,LHand);
|
||
LSetCell(fi.name+1,*fi.name,pj,LHand);
|
||
LSetSelect(iSelect,pj,LHand);
|
||
Win->isDirty = True;
|
||
}
|
||
|
||
/************************************************************************
|
||
* FilterTextChanged - the te routines did something to our text
|
||
************************************************************************/
|
||
void FilterTextChanged(MyWindowPtr win, TEHandle teh, short oldNl, short newNl, Boolean scroll)
|
||
{
|
||
CurrentDirty = True;
|
||
}
|
||
|
||
/************************************************************************
|
||
* RemoveFilter - get rid of a filter
|
||
************************************************************************/
|
||
void RemoveFilter(short which)
|
||
{
|
||
short n = NFilters;
|
||
|
||
RemoveFilterLo(which);
|
||
if (FLG && *FLG && Win)
|
||
{
|
||
if (which==Selected-1)
|
||
{
|
||
Selected = 0;
|
||
if (NFilters)
|
||
FilterSelect(which);
|
||
else
|
||
{
|
||
DisplaySelectedFilter();
|
||
FiltersSetGreys();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void RemoveFilterLo(short which)
|
||
{
|
||
short n = NFilters;
|
||
|
||
if (FLG && *FLG && Win && which==Selected-1 && !Multiple)
|
||
ForAllActionsDo(faeClose,nil);
|
||
|
||
Selected = Multiple = 0;
|
||
|
||
if (which<--n)
|
||
BMD(&FR[which+1],&FR[which],(n-which)*sizeof(FilterRecord));
|
||
SetHandleBig_(Filters,n*sizeof(FilterRecord));
|
||
|
||
if (FLG && *FLG && Win)
|
||
{
|
||
LDelRow(1,which,LHand);
|
||
Win->isDirty = CurrentDirty = True;
|
||
}
|
||
}
|
||
|
||
/************************************************************************
|
||
* AddFilter - add a filter. n is filter should be
|
||
************************************************************************/
|
||
void AddFilter(short n)
|
||
{
|
||
Point c;
|
||
FilterRecord fr;
|
||
short i;
|
||
FActionHandle fa;
|
||
|
||
FRInit(&fr);
|
||
fr.incoming = True;
|
||
fr.fu.id = FilterNewId();
|
||
GetRString(fr.name,UNTITLED);
|
||
|
||
SetHandleBig_(Filters,(NFilters+1)*sizeof(fr));
|
||
if (MemError()) {WarnUser(MEM_ERR,MemError()); return;}
|
||
|
||
for (i=MAX_ACTIONS;i;i--)
|
||
{
|
||
fa = NewZH(FAction);
|
||
if (!fa) {WarnUser(MEM_ERR,MemError()); break;}
|
||
(*fa)->action = flkNone;
|
||
LL_Push(fr.actions,fa);
|
||
}
|
||
|
||
if (i) SetHandleBig_(Filters,NFilters*sizeof(fr));
|
||
|
||
if (n<NFilters-1) BMD(FR+n,FR+n+1,(NFilters-n-1)*sizeof(fr));
|
||
FR[n] = fr;
|
||
|
||
FilterNoteMatch(n,GMTDateTime());
|
||
|
||
if (FLG && *FLG && Win)
|
||
{
|
||
PushGWorld();
|
||
SetPort_(GetMyWindowCGrafPtr(Win));
|
||
LAddRow(1,n,LHand);
|
||
c.h = 0; c.v = n;
|
||
LSetCell(fr.name+1,*fr.name,c,LHand);
|
||
FilterSelect(n);
|
||
Win->isDirty = CurrentDirty = True;
|
||
PopGWorld();
|
||
}
|
||
}
|
||
|
||
/************************************************************************
|
||
* FilterSelect - select a given cell
|
||
************************************************************************/
|
||
void FilterSelect(short which)
|
||
{
|
||
if (which>0) which = MIN(which,NFilters-1);
|
||
SaveCurrentFilter();
|
||
SelectSingleCell(which,LHand);
|
||
LAutoScroll(LHand);
|
||
ActOnFilterSelect();
|
||
}
|
||
|
||
/************************************************************************
|
||
* ActOnFilterSelect - we have selected a filter; do something about it
|
||
************************************************************************/
|
||
void ActOnFilterSelect(void)
|
||
{
|
||
short which, next;
|
||
Rect r;
|
||
short i;
|
||
FActionHandle fa;
|
||
|
||
which = Next1Selected(0,LHand);
|
||
next = Next1Selected(which,LHand);
|
||
|
||
if (Multiple && next) return; /* still a multiple selection */
|
||
if (which==Selected && !next) return; /* same single selection */
|
||
SaveCurrentFilter();
|
||
|
||
if (Multiple)
|
||
for (i=0;i<MAX_ACTIONS;i++) InvalAct(i);
|
||
else if (Selected)
|
||
for (i=0,fa=FR[Selected-1].actions;fa && i<MAX_ACTIONS;i++,fa=(*fa)->next)
|
||
if ((*fa)->action!=flkNone) InvalAct(i);
|
||
|
||
ForAllActionsDo(faeClose,nil);
|
||
|
||
if ((Multiple==0)!=(next==0) || (Selected==0)!=(which==0))
|
||
{
|
||
r = Win->contR;
|
||
r.left = Rects[flrVBar].right+1;
|
||
InvalWindowRect(GetMyWindowWindowPtr(Win),&r);
|
||
}
|
||
else if (which && Selected && (FR[which-1].conjunction==cjIgnore)!=HasTwo)
|
||
InvalMatch2();
|
||
|
||
r = Rects[flrDate];
|
||
InvalWindowRect(GetMyWindowWindowPtr(Win),&r);
|
||
Selected = which;
|
||
Multiple = next;
|
||
|
||
if (Multiple)
|
||
for (i=0;i<MAX_ACTIONS;i++) InvalAct(i);
|
||
else if (Selected)
|
||
for (i=0,fa=FR[Selected-1].actions;fa && i<MAX_ACTIONS;i++,fa=(*fa)->next)
|
||
if ((*fa)->action!=flkNone) InvalAct(i);
|
||
|
||
if (!Selected || Multiple)
|
||
for (i=0;i<MAX_ACTIONS;i++) HideControl(Controls[flAct1+i]);
|
||
|
||
DisplaySelectedFilter();
|
||
FiltersSetGreys();
|
||
CurrentDirty = False;
|
||
if (Selected && !Multiple) LAutoScroll(LHand);
|
||
}
|
||
|
||
/************************************************************************
|
||
* InvalMatch2 - invalidate the second match rectangle
|
||
************************************************************************/
|
||
void InvalMatch2(void)
|
||
{
|
||
Rect r = Rects[flrMatch2];
|
||
InsetRect(&r,1,1);
|
||
InvalWindowRect(GetMyWindowWindowPtr(Win),&r);
|
||
}
|
||
|
||
/************************************************************************
|
||
* FActionPopUp - pop up a menu for choosing a faction
|
||
************************************************************************/
|
||
void FActionPopUp(Point pt,ControlHandle cntl)
|
||
{
|
||
short item;
|
||
Str63 s;
|
||
FActionHandle other;
|
||
FActionHandle fa;
|
||
short i;
|
||
short n = (GetControlReference(cntl)&0xff) - '0';
|
||
Boolean enable;
|
||
|
||
/*
|
||
* find the action
|
||
*/
|
||
for (i=n,fa=FR[Selected-1].actions;i;i--) fa=(*fa)->next;
|
||
|
||
/*
|
||
* enable the items
|
||
*/
|
||
CheckNone(ActionMenu);
|
||
item = GetControlValue(cntl);
|
||
for (i=CountMenuItems(ActionMenu);i;i--)
|
||
{
|
||
GetMenuItemText(ActionMenu,i,s);
|
||
if (*s>1)
|
||
{
|
||
//Enhanced Filters - disable and mark the Pro-only filter feature set (already done at this point)
|
||
if (enable = (HasFeature (featureEudoraPro) || !FAProOnly (i)))
|
||
if (!FAMultiple(i) && i!=(*fa)->action)
|
||
{
|
||
for (other=FR[Selected-1].actions;other;other=(*other)->next)
|
||
if (other!=fa && (*other)->action==i)
|
||
{
|
||
DisableItem (ActionMenu,i);
|
||
goto loop;
|
||
}
|
||
}
|
||
EnableIf (ActionMenu, i, enable);
|
||
if (item==i) SetItemMark (ActionMenu, item, diamondChar);
|
||
}
|
||
loop:;
|
||
}
|
||
|
||
if (TrackControl(cntl,pt,nil))
|
||
{
|
||
short newItem;
|
||
|
||
newItem = GetControlValue(cntl);
|
||
|
||
if (newItem != item)
|
||
NewAction(n,fa,newItem);
|
||
}
|
||
}
|
||
|
||
/************************************************************************
|
||
* AdjustActionMenu - enable/disable items in the action menu
|
||
************************************************************************/
|
||
void AdjustActionMenu (MenuHandle theMenu)
|
||
|
||
{
|
||
// Disable any non-pro features (lamer than it should be...)
|
||
SetMenuItemBasedOnFeature (theMenu, flkLabel, featureFilterLabel, true);
|
||
SetMenuItemBasedOnFeature (theMenu, flkPersonality, featureFilterPersonality, true);
|
||
SetMenuItemBasedOnFeature (theMenu, flkSound, featureFilterSound, true);
|
||
SetMenuItemBasedOnFeature (theMenu, flkSpeak, featureFilterSpeak, SpeechAvailable ());
|
||
SetMenuItemBasedOnFeature (theMenu, flkOpenMessage, featureFilterOpen, true);
|
||
SetMenuItemBasedOnFeature (theMenu, flkPrint, featureFilterPrint, true);
|
||
SetMenuItemBasedOnFeature (theMenu, flkAddHistory, featureFilterAddHistory, true);
|
||
SetMenuItemBasedOnFeature (theMenu, flkForward, featureFilterForward, true);
|
||
SetMenuItemBasedOnFeature (theMenu, flkRedirect, featureFilterRedirect, true);
|
||
SetMenuItemBasedOnFeature (theMenu, flkReply, featureFilterReply, true);
|
||
SetMenuItemBasedOnFeature (theMenu, flkServerOpts, featureFilterServerOptions, true);
|
||
SetMenuItemBasedOnFeature (theMenu, flkJunk, featureJunk, true);
|
||
}
|
||
|
||
/************************************************************************
|
||
* AccelPopUp - pop up a menu for choosing a header quickly
|
||
************************************************************************/
|
||
void AccelPopUp(PETEHandle pte,ControlHandle verbCntl,short top,short left)
|
||
{
|
||
MenuHandle mh;
|
||
Str255 value;
|
||
short item;
|
||
long sel;
|
||
Point pt;
|
||
|
||
pt.h = left; pt.v = top; LocalToGlobal(&pt);
|
||
|
||
if (mh=GetMenu(HEAD_ACCEL_MENU))
|
||
{
|
||
if (PersCount()>1) MyAppendMenu(mh,GetRString(value,FiltMetaLocalStrn+fmlPersonality));
|
||
|
||
GetRString(value,FiltMetaLocalStrn+fmlJunk);
|
||
if (*value && (item=FindItemByName(mh,value)))
|
||
SetMenuItemBasedOnFeature(mh,item,featureJunk,true);
|
||
|
||
item = 0;
|
||
|
||
PeteSString(value,pte);
|
||
if (*value && !(item=FindItemByName(mh,value)))
|
||
{
|
||
AppendMenu(mh,"\p-");
|
||
DisableItem(mh,CountMenuItems(mh));
|
||
MyAppendMenu(mh,value);
|
||
item = CountMenuItems(mh);
|
||
}
|
||
|
||
InsertMenu(mh,-1);
|
||
sel = AFPopUpMenuSelect(mh,pt.v,pt.h,item);
|
||
if (sel&0xffff && sel&0xff && (sel&0xff)!=item)
|
||
{
|
||
MyGetItem(mh,sel&0xff,value);
|
||
PeteSetTextPtr(pte,value+1,*value);
|
||
Win->isDirty = CurrentDirty = True;
|
||
FiltEnableVerb(verbCntl,value);
|
||
}
|
||
DeleteMenu(HEAD_ACCEL_MENU);
|
||
ReleaseResource_(mh);
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
* NewAction - change an action
|
||
**********************************************************************/
|
||
void NewAction(short n,FActionHandle fa,FilterKeywordEnum action)
|
||
{
|
||
FActionProc *old, *new;
|
||
Rect r;
|
||
|
||
old = (FActionProc *)FATable((*fa)->action);
|
||
new = (FActionProc *)FATable(action);
|
||
if (old)
|
||
{
|
||
(*old)(faeDispose,fa,nil,nil);
|
||
if ((*fa)->data) ZapHandle((*fa)->data);
|
||
}
|
||
Win->isDirty = CurrentDirty = True;
|
||
(*fa)->action = action;
|
||
r = Rects[flrAct1+n];
|
||
InvalAct(n);
|
||
if (new)
|
||
if (!(*new)(faeRead,fa,nil,nil))
|
||
if (!(*new)(faeInit,fa,&r,nil));
|
||
(*new)(faeNew,fa,&r,nil);
|
||
}
|
||
|
||
/************************************************************************
|
||
* DisplaySelectedFilter - display a filter
|
||
************************************************************************/
|
||
void DisplaySelectedFilter(void)
|
||
{
|
||
FilterRecord fr;
|
||
Rect r,hiddenRect;
|
||
Str255 s;
|
||
short i;
|
||
FActionHandle fa;
|
||
|
||
SetRect(&hiddenRect,-100,-100,-100,ONE_LINE_HI(Win)-100);
|
||
|
||
if (Selected && !Multiple)
|
||
fr = FR[Selected-1];
|
||
else
|
||
FRInit(&fr);
|
||
|
||
MySetCtlValue(Controls[flIncoming],fr.incoming);
|
||
MySetCtlValue(Controls[flOutgoing],fr.outgoing);
|
||
MySetCtlValue(Controls[flManual],fr.manual);
|
||
#ifdef NEVER
|
||
CurrentLabel = fr.label;
|
||
DrawLabel();
|
||
DrawFilterDate();
|
||
#endif
|
||
MySetCtlValue(Controls[flConjunction],fr.conjunction);
|
||
MySetCtlValue(Controls[flMatchOnePop],fr.terms[0].verb);
|
||
MySetCtlValue(Controls[flMatchTwoPop],fr.terms[1].verb);
|
||
|
||
/* value 1 */
|
||
r = Rects[flrVal1];
|
||
|
||
FiltEnableVerb(Controls[flMatchOnePop],fr.terms[0].header);
|
||
|
||
if (fr.terms[0].verb == mbmAppears || fr.terms[0].verb == mbmNotAppears ||
|
||
fr.terms[0].verb == mbmIntersectsFile || fr.terms[0].verb == mbmNotIntersectsFile)
|
||
{
|
||
PeteDidResize(Block0.valuePTE,&hiddenRect);
|
||
if (fr.terms[0].verb == mbmIntersectsFile || fr.terms[0].verb == mbmNotIntersectsFile)
|
||
FiltSetAndShowNickPop(flNickFilePop1,fr.terms[0].value,&r);
|
||
else
|
||
HideControl(Controls[flNickFilePop1]);
|
||
}
|
||
else
|
||
{
|
||
HideControl(Controls[flNickFilePop1]);
|
||
PeteDidResize(Block0.valuePTE,&r);
|
||
}
|
||
|
||
/* value 2 */
|
||
|
||
r = Rects[flrVal2];
|
||
|
||
FiltEnableVerb(Controls[flMatchTwoPop],fr.terms[1].header);
|
||
|
||
if (fr.terms[1].verb == mbmAppears || fr.terms[1].verb == mbmNotAppears ||
|
||
fr.terms[1].verb == mbmIntersectsFile || fr.terms[1].verb == mbmNotIntersectsFile)
|
||
{
|
||
PeteDidResize(Block1.valuePTE,&hiddenRect);
|
||
if (fr.terms[1].verb == mbmIntersectsFile || fr.terms[1].verb == mbmNotIntersectsFile)
|
||
FiltSetAndShowNickPop(flNickFilePop2,fr.terms[1].value,&r);
|
||
else
|
||
HideControl(Controls[flNickFilePop1]);
|
||
}
|
||
else
|
||
{
|
||
HideControl(Controls[flNickFilePop2]);
|
||
PeteDidResize(Block1.valuePTE,&r);
|
||
}
|
||
|
||
PeteSetString(Transmogrify(s,FiltMetaLocalStrn,fr.terms[0].header,FiltMetaEnglishStrn),Block0.headerPTE);
|
||
PeteSetString(fr.terms[0].value,Block0.valuePTE);
|
||
PeteSetString(Transmogrify(s,FiltMetaLocalStrn,fr.terms[1].header,FiltMetaEnglishStrn),Block1.headerPTE);
|
||
PeteSetString(fr.terms[1].value,Block1.valuePTE);
|
||
if (HasTwo != (fr.conjunction!=cjIgnore))
|
||
{
|
||
HasTwo = !HasTwo;
|
||
InvalMatch2();
|
||
}
|
||
|
||
ForAllActionsDo(faeInit,nil);
|
||
|
||
if (Selected && !Multiple)
|
||
{
|
||
PeteFocus(Win,Block0.headerPTE,True);
|
||
PeteSelectAll(Win,Win->pte);
|
||
for (i=0,fa=FR[Selected-1].actions;i<MAX_ACTIONS;i++,fa=(*fa)->next)
|
||
{
|
||
SetControlValue(Controls[flAct1+i],fa?(*fa)->action:flkNone);
|
||
ShowControl(Controls[flAct1+i]);
|
||
}
|
||
}
|
||
else PeteFocus(Win,nil,True);
|
||
|
||
PeteCleanList(Win->pteList);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FiltEnableVerbAll - enable all the verb popups in the filters window
|
||
**********************************************************************/
|
||
void FiltEnableVerbAll(void)
|
||
{
|
||
Str63 s;
|
||
PeteSString(s,Block0.headerPTE);
|
||
FiltEnableVerb(Controls[flMatchOnePop],s);
|
||
PeteSString(s,Block1.headerPTE);
|
||
FiltEnableVerb(Controls[flMatchTwoPop],s);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FiltEnableVerb - enable one of the verb popups
|
||
**********************************************************************/
|
||
void FiltEnableVerb(ControlHandle popUpCntl,PStr head)
|
||
{
|
||
Boolean junkScore = EqualStrRes(head,FiltMetaEnglishStrn+fmeJunk) || EqualStrRes(head,FiltMetaLocalStrn+fmlJunk);
|
||
short i;
|
||
MenuHandle mh = PopUpMenuH(popUpCntl);
|
||
|
||
// enable only a few things if we're searching on junk score
|
||
for (i=mbmContains;i<mbmLimit;i++)
|
||
EnableIf(mh,i,((i==mbmJunkLess||i==mbmJunkMore)==junkScore)||i==mbmIs||i==mbmIsnt);
|
||
|
||
// make sure what is selected isn't dimmed
|
||
if (!IsMenuItemEnabled(mh,GetControlValue(popUpCntl)))
|
||
SetControlValue(popUpCntl,junkScore?mbmJunkMore:mbmContains);
|
||
}
|
||
|
||
|
||
/**********************************************************************
|
||
* InvalAct - invalidate an action
|
||
**********************************************************************/
|
||
void InvalAct(short i)
|
||
{
|
||
Rect rRgn;
|
||
|
||
GetRegionBounds(ActRgn,&rRgn);
|
||
OffsetRgn(ActRgn,0,Rects[flrAct1+i].bottom-rRgn.bottom-1);
|
||
InvalWindowRgn(GetMyWindowWindowPtr(Win),ActRgn);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* ForAllActionsDo - do something for the current actions
|
||
**********************************************************************/
|
||
short ForAllActionsDo(FACallEnum callType,void *dataPtr)
|
||
{
|
||
short i;
|
||
FActionHandle fa;
|
||
Rect r;
|
||
OSErr err, anyErr;
|
||
|
||
err = anyErr = noErr;
|
||
|
||
if (Selected && !Multiple)
|
||
{
|
||
for (i=0,fa=FR[Selected-1].actions;fa && i<MAX_ACTIONS;i++,fa=(*fa)->next)
|
||
{
|
||
r = Rects[flrAct1+i];
|
||
err = (*(FActionProc*)FATable((*fa)->action))(callType,fa,&r,dataPtr);
|
||
if (err) anyErr = err;
|
||
}
|
||
}
|
||
return(anyErr);
|
||
}
|
||
|
||
|
||
|
||
/************************************************************************
|
||
* SaveCurrentFilter - save the current filter
|
||
************************************************************************/
|
||
void SaveCurrentFilter(void)
|
||
{
|
||
Str31 scratch;
|
||
Str255 name;
|
||
Str31 head;
|
||
Boolean dirty = FLG && Win && PeteIsDirtyList(Win->pteList);
|
||
|
||
if (FLG) CurrentDirty = dirty || CurrentDirty;
|
||
|
||
if (FLG && Selected && !Multiple && CurrentDirty)
|
||
{
|
||
FilterRecord fr;
|
||
FilterUse fu = FR[Selected-1].fu;
|
||
Str31 idStr;
|
||
|
||
FRInit(&fr);
|
||
fr.fu = fu;
|
||
fr.actions = FR[Selected-1].actions;
|
||
|
||
fr.incoming = GetControlValue(Controls[flIncoming]);
|
||
fr.outgoing = GetControlValue(Controls[flOutgoing]);
|
||
fr.manual = GetControlValue(Controls[flManual]);
|
||
fr.conjunction = GetControlValue(Controls[flConjunction]);
|
||
fr.terms[0].verb = GetControlValue(Controls[flMatchOnePop]);
|
||
PeteSString(fr.terms[0].header,Block0.headerPTE);
|
||
if (fr.terms[0].verb==mbmIntersectsFile || fr.terms[0].verb==mbmNotIntersectsFile)
|
||
MyGetItem(PopUpMenuH (Controls[flNickFilePop1]),GetControlValue(Controls[flNickFilePop1]),fr.terms[0].value);
|
||
else if (fr.terms[0].verb==mbmAppears || fr.terms[0].verb==mbmNotAppears)
|
||
*fr.terms[0].value = 0;
|
||
else
|
||
PeteSString(fr.terms[0].value,Block0.valuePTE);
|
||
|
||
if (HasTwo)
|
||
{
|
||
fr.terms[1].verb = GetControlValue(Controls[flMatchTwoPop]);
|
||
PeteSString(fr.terms[1].header,Block1.headerPTE);
|
||
if (fr.terms[1].verb==mbmIntersectsFile || fr.terms[1].verb==mbmNotIntersectsFile)
|
||
MyGetItem(PopUpMenuH (Controls[flNickFilePop2]),GetControlValue(Controls[flNickFilePop2]),fr.terms[1].value);
|
||
else if (fr.terms[1].verb==mbmAppears || fr.terms[1].verb==mbmNotAppears)
|
||
*fr.terms[1].value = 0;
|
||
else
|
||
PeteSString(fr.terms[1].value,Block1.valuePTE);
|
||
}
|
||
TrimWhite(fr.terms[0].header);
|
||
TrimWhite(fr.terms[1].header);
|
||
TrimInitialWhite(fr.terms[0].header);
|
||
TrimInitialWhite(fr.terms[1].header);
|
||
|
||
/*
|
||
* build the name BEFORE transmogrification
|
||
*/
|
||
if (*fr.terms[0].header || *fr.terms[0].value)
|
||
{
|
||
NumToString(fr.fu.id,idStr);
|
||
PSCopy(head,fr.terms[0].header);
|
||
if (head[*head]==':') --*head;
|
||
utl_PlugParams(GetRString(scratch,FILTER_NAME),name,
|
||
head,fr.terms[0].value,idStr,nil);
|
||
PSCopy(fr.name,name);
|
||
}
|
||
else GetRString(fr.name,UNTITLED);
|
||
|
||
Transmogrify(fr.terms[0].header,FiltMetaEnglishStrn,fr.terms[0].header,FiltMetaLocalStrn);
|
||
Transmogrify(fr.terms[1].header,FiltMetaEnglishStrn,fr.terms[1].header,FiltMetaLocalStrn);
|
||
|
||
/*
|
||
* save the actions
|
||
*/
|
||
ForAllActionsDo(faeSave,nil);
|
||
|
||
/*
|
||
* study it
|
||
*/
|
||
StudyFilter(&fr);
|
||
|
||
/*
|
||
* save it
|
||
*/
|
||
LDRef(Filters);
|
||
{
|
||
Point c;
|
||
c.h = 0; c.v = Selected-1;
|
||
FR[Selected-1] = fr;
|
||
Win->isDirty = True;
|
||
LSetCell(fr.name+1,*fr.name,c,LHand);
|
||
}
|
||
UL(Filters);
|
||
CurrentDirty = False;
|
||
PeteCleanList(Win->pteList);
|
||
}
|
||
}
|
||
|
||
#pragma segment Print
|
||
/**********************************************************************
|
||
* PrintFilters - print the filter list
|
||
**********************************************************************/
|
||
OSErr PrintFilters(Boolean selected,Boolean now)
|
||
{
|
||
OSErr err;
|
||
PMPrintContext printContext;
|
||
Rect uRect;
|
||
short page = 0;
|
||
short n = NFilters;
|
||
short i;
|
||
short v;
|
||
|
||
PushGWorld();
|
||
|
||
if (!(err = PrintPreamble(&printContext,&uRect,now)))
|
||
{
|
||
for (i=0;i<NFilters && !err;i++)
|
||
err = PrintAFilter(i,&uRect,&v,&page,printContext);
|
||
|
||
/*
|
||
* finish final page
|
||
*/
|
||
if (page)
|
||
{
|
||
PrintBottomHeader(page,&uRect);
|
||
PMEndPage(printContext);
|
||
}
|
||
|
||
PrintCleanup(printContext,err);
|
||
}
|
||
PopGWorld();
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* PrintAFilter - print a single filter
|
||
**********************************************************************/
|
||
OSErr PrintAFilter(short which, Rect *uRect, short *v, short *page, PMPrintContext printContext)
|
||
{
|
||
Str255 scratch, string;
|
||
OSErr err = noErr;
|
||
short h = uRect->left + (GetRLong(NICK_PRINT_NICK_PER)*RectWi(*uRect))/100;
|
||
FActionHandle fa;
|
||
Point penLoc;
|
||
|
||
FilterRecord fr = FR[which];
|
||
|
||
/*
|
||
* need new page?
|
||
*/
|
||
if (*page==0 || *v+FiltPrintLines(which,uRect)*Win->vPitch>uRect->bottom-GetRLong(PRINT_H_MAR))
|
||
{
|
||
GetWTitle(GetMyWindowWindowPtr(Win),scratch);
|
||
if (*page!=0)
|
||
{
|
||
PrintBottomHeader(*page,uRect);
|
||
PMEndPage(printContext);
|
||
}
|
||
PMBeginPage(printContext,nil);
|
||
*v = uRect->top+GetRLong(PRINT_H_MAR);
|
||
PrintMessageHeader(scratch,++*page,GetRLong(PRINT_H_MAR),*v,uRect->left,uRect->right);
|
||
}
|
||
|
||
/*
|
||
* print the name & types
|
||
*/
|
||
*v += Win->vPitch;
|
||
MoveTo(uRect->left,*v);
|
||
BoldString(fr.name);
|
||
if (GetPortPenLocation(GetQDGlobalsThePort(),&penLoc)->h<h-10) MoveTo(h,*v);
|
||
else Move(10,0);
|
||
|
||
*scratch = 0;
|
||
if (fr.incoming) GetRString(scratch,FiltKindPrintStrn+fkpIn);
|
||
if (fr.outgoing)
|
||
{
|
||
if (*scratch) PSCat(scratch,"\p, ");
|
||
PCatR(scratch,FiltKindPrintStrn+fkpOut);
|
||
}
|
||
if (fr.manual)
|
||
{
|
||
if (*scratch) PSCat(scratch,"\p, ");
|
||
PCatR(scratch,FiltKindPrintStrn+fkpMan);
|
||
}
|
||
if (!*scratch) GetRString(scratch,FiltKindPrintStrn+fkpNone);
|
||
ComposeRString(string,PAREN_STRING,scratch);
|
||
DrawString(string);
|
||
*v += Win->vPitch;
|
||
|
||
/*
|
||
* print the terms
|
||
*/
|
||
MoveTo(h,*v);
|
||
FiltPrintTerm(fr.terms);
|
||
if (fr.conjunction!=cjIgnore)
|
||
{
|
||
*v += Win->vPitch;
|
||
MoveTo(h,*v);
|
||
DrawChar(' ');
|
||
BoldRString(FiltConjPrintStrn+fr.conjunction);
|
||
DrawChar(' ');
|
||
FiltPrintTerm(fr.terms+1);
|
||
}
|
||
|
||
MoveTo(h,*v+(Win->vPitch*2)/3);
|
||
Hairline(True); Line(72,0); Hairline(False);
|
||
*v += Win->vPitch;
|
||
|
||
/*
|
||
* print the actions
|
||
*/
|
||
for (fa=fr.actions;fa;fa=(*fa)->next)
|
||
{
|
||
if ((*fa)->action==flkNone) continue;
|
||
*v += Win->vPitch;
|
||
|
||
MoveTo(h,*v);
|
||
GetMenuItemText(ActionMenu,(*fa)->action,scratch);
|
||
BoldString(scratch);
|
||
DrawChar(' ');
|
||
CallAction(faePrint,fa,nil,nil);
|
||
}
|
||
|
||
/*
|
||
* and leave a blank line
|
||
*/
|
||
*v += Win->vPitch;
|
||
|
||
return(err);
|
||
}
|
||
|
||
#ifdef GX_PRINTING
|
||
/**********************************************************************
|
||
* GXPrintFilters - print the filter list, Quickdraw GX version
|
||
**********************************************************************/
|
||
OSErr GXPrintFilters(Boolean selected, Boolean now)
|
||
{
|
||
OSErr err = noErr;
|
||
gxRectangle GXuRect;
|
||
Rect uRect;
|
||
short i = 0, v = 0, page = 0;
|
||
Str255 scratch;
|
||
CGrafPort GXPort;
|
||
long firstPage, numPages;
|
||
GrafPtr oldPort;
|
||
|
||
GetWTitle(GetMyWindowWindowPtr(Win), scratch);
|
||
if ((err = GXPrintPreamble(&GXuRect, scratch, &firstPage, &numPages, now)) == noErr)
|
||
{
|
||
GetPort(&oldPort);
|
||
OpenCPort(&GXPort);
|
||
SetPort((GrafPtr)&GXPort);
|
||
|
||
GXRectToRect(&GXuRect, &uRect);
|
||
for (i = FilterToPrintFirst(firstPage, &uRect); i < NFilters && !err; i++)
|
||
err = GXPrintAFilter(&GXPort, i, &uRect, &GXuRect, &v, &page, firstPage, numPages);
|
||
|
||
//finish final page
|
||
if ((page) && (err==noErr))
|
||
{
|
||
MyGXInstallQDTranslator(&GXPort, &GXuRect, &gGXPrintViewPort, true);
|
||
PrintBottomHeader(page, &uRect);
|
||
MyGXRemoveQDTranslator(&GXPort);
|
||
GXFinishPage(GXPageSetup);
|
||
}
|
||
|
||
#ifdef DEBUG
|
||
{
|
||
GrafPtr test;
|
||
|
||
GetPort(&test);
|
||
ASSERT(test == (GrafPtr)&GXPort);
|
||
}
|
||
#endif //DEBUG
|
||
|
||
CloseCPort(&GXPort);
|
||
SetPort(oldPort);
|
||
|
||
err = GXPrintCleanup();
|
||
}
|
||
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FilterToPrintFirst - return which filter to print first. Return the
|
||
* first filter that shows up on the first page in the page range.
|
||
**********************************************************************/
|
||
short FilterToPrintFirst(long firstPage, Rect *uRect)
|
||
{
|
||
short filtNum = 0;
|
||
short pageNum = 1;
|
||
FActionHandle fa;
|
||
FilterRecord fr;
|
||
short v = 0;
|
||
|
||
while (pageNum < firstPage)
|
||
{
|
||
fr = FR[filtNum];
|
||
|
||
//"draw" the filter
|
||
v += 4*(Win->vPitch);
|
||
if (fr.conjunction!=cjIgnore)
|
||
{
|
||
v += Win->vPitch;
|
||
}
|
||
for (fa=fr.actions;fa;fa=(*fa)->next)
|
||
{
|
||
if ((*fa)->action==flkNone) continue;
|
||
v += Win->vPitch;
|
||
}
|
||
|
||
//we skipped this filter.
|
||
filtNum++;
|
||
|
||
//have we "filled" a page?
|
||
if (v+FiltPrintLines(filtNum,uRect)*Win->vPitch>uRect->bottom-GetRLong(PRINT_H_MAR))
|
||
{
|
||
pageNum++;
|
||
v = uRect->top+GetRLong(PRINT_H_MAR);
|
||
}
|
||
}
|
||
|
||
return (filtNum);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* GXPrintAFilter - print a single filter, GX version. This sets the
|
||
* port to GXPortPtr.
|
||
**********************************************************************/
|
||
OSErr GXPrintAFilter(CGrafPtr GXPortPtr, short which, Rect *uRect, gxRectangle *GXuRect, short *v, short *page, long firstPage, long numPages)
|
||
{
|
||
Str255 scratch, string;
|
||
OSErr err = noErr;
|
||
short h = uRect->left + (GetRLong(NICK_PRINT_NICK_PER)*RectWi(*uRect))/100;
|
||
FActionHandle fa;
|
||
FilterRecord fr = FR[which];
|
||
gxFormat pageFormat = GXGetJobFormat(GXPageSetup, 1);
|
||
Point penLoc;
|
||
|
||
//This will allow cmd-. to stop printing.
|
||
GXIdleJob(GXPageSetup);
|
||
MiniEvents();
|
||
if (CommandPeriod) return(errEndOfDocument);
|
||
|
||
SetPort((GrafPtr)GXPortPtr); //all printing will be done to this port ...
|
||
|
||
/*
|
||
* need new page?
|
||
*/
|
||
if (*page == 0 || *v+FiltPrintLines(which,uRect)*Win->vPitch>uRect->bottom-GetRLong(PRINT_H_MAR))
|
||
{
|
||
GetWTitle(GetMyWindowWindowPtr(Win), scratch);
|
||
//finish current page
|
||
if (*page != 0)
|
||
{
|
||
MyGXInstallQDTranslator(GXPortPtr, GXuRect, &gGXPrintViewPort, true);
|
||
PrintBottomHeader(*page + firstPage - 1, uRect);
|
||
MyGXRemoveQDTranslator(GXPortPtr);
|
||
GXFinishPage(GXPageSetup);
|
||
}
|
||
|
||
//return if the next page is past the last page in the page range
|
||
if ((numPages < INT_MAX) && (*page + firstPage > firstPage + numPages - 1))
|
||
return (errEndOfDocument);
|
||
|
||
//start new page
|
||
GXStartPage(GXPageSetup, (*page)+firstPage, pageFormat, 1, &gGXPrintViewPort);
|
||
err = GXGetJobError(GXPageSetup);
|
||
if (err != noErr) return (err);
|
||
(*page)++;
|
||
*v = uRect->top+GetRLong(PRINT_H_MAR);
|
||
MyGXInstallQDTranslator(GXPortPtr, GXuRect, &gGXPrintViewPort, true);
|
||
PrintMessageHeader(scratch, *page + firstPage - 1, GetRLong(PRINT_H_MAR), *v, uRect->left, uRect->right);
|
||
MyGXRemoveQDTranslator(GXPortPtr);
|
||
}
|
||
|
||
/*
|
||
* print the name & types
|
||
*/
|
||
|
||
MyGXInstallQDTranslator(GXPortPtr, GXuRect, &gGXPrintViewPort, true);
|
||
|
||
*v += Win->vPitch;
|
||
MoveTo(uRect->left,*v);
|
||
BoldString(fr.name);
|
||
if (GetPortPenLocation(GetQDGlobalsThePort(),&penLoc)->h<h-10) MoveTo(h,*v);
|
||
else Move(10,0);
|
||
|
||
*scratch = 0;
|
||
if (fr.incoming) GetRString(scratch,FiltKindPrintStrn+fkpIn);
|
||
if (fr.outgoing)
|
||
{
|
||
if (*scratch) PSCat(scratch,"\p, ");
|
||
PCatR(scratch,FiltKindPrintStrn+fkpOut);
|
||
}
|
||
if (fr.manual)
|
||
{
|
||
if (*scratch) PSCat(scratch,"\p, ");
|
||
PCatR(scratch,FiltKindPrintStrn+fkpMan);
|
||
}
|
||
if (!*scratch) GetRString(scratch,FiltKindPrintStrn+fkpNone);
|
||
ComposeRString(string,PAREN_STRING,scratch);
|
||
DrawString(string);
|
||
*v += Win->vPitch;
|
||
|
||
/*
|
||
* print the terms
|
||
*/
|
||
MoveTo(h,*v);
|
||
FiltPrintTerm(fr.terms);
|
||
if (fr.conjunction!=cjIgnore)
|
||
{
|
||
*v += Win->vPitch;
|
||
MoveTo(h,*v);
|
||
DrawChar(' ');
|
||
BoldRString(FiltConjPrintStrn+fr.conjunction);
|
||
DrawChar(' ');
|
||
FiltPrintTerm(fr.terms+1);
|
||
}
|
||
|
||
MoveTo(h,*v+(Win->vPitch*2)/3);
|
||
Hairline(True); Line(72,0); Hairline(False);
|
||
*v += Win->vPitch;
|
||
|
||
/*
|
||
* print the actions
|
||
*/
|
||
for (fa=fr.actions;fa;fa=(*fa)->next)
|
||
{
|
||
if ((*fa)->action==flkNone) continue;
|
||
*v += Win->vPitch;
|
||
|
||
MoveTo(h,*v);
|
||
GetMenuItemText(ActionMenu,(*fa)->action,scratch);
|
||
BoldString(scratch);
|
||
DrawChar(' ');
|
||
CallAction(faePrint,fa,nil,nil);
|
||
}
|
||
|
||
/*
|
||
* and leave a blank line
|
||
*/
|
||
*v += Win->vPitch;
|
||
|
||
MyGXRemoveQDTranslator(GXPortPtr);
|
||
|
||
return(err);
|
||
}
|
||
#endif //GX_PRINTING
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
void FiltPrintTerm(MTPtr term)
|
||
{
|
||
if (!EqualStrRes(term->header,FILTER_ANY) &&
|
||
!EqualStrRes(term->header,FILTER_ADDRESSEE) &&
|
||
!EqualStrRes(term->header,FILTER_BODY))
|
||
{
|
||
BoldRString(JUST_PLAIN_HEADER);
|
||
DrawChar(' ');
|
||
}
|
||
|
||
DrawString(term->header);
|
||
|
||
DrawChar(' ');
|
||
BoldRString(FiltVerbPrintStrn+term->verb);
|
||
DrawChar(' ');
|
||
|
||
if (term->verb!=mbmAppears && term->verb!=mbmNotAppears)
|
||
DrawString(term->value);
|
||
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FiltPrintLines - how many lines will a filter take?
|
||
**********************************************************************/
|
||
short FiltPrintLines(short which,Rect *uRect)
|
||
{
|
||
short lines = 3; // filter name & condition
|
||
FActionHandle fa;
|
||
Str255 name;
|
||
|
||
PCopy(name,FR[which].name);
|
||
if (FR[which].conjunction!=cjIgnore) lines++;
|
||
|
||
for (fa=FR[which].actions;fa;fa=(*fa)->next) if ((*fa)->action!=flkNone) lines++;
|
||
|
||
return(lines);
|
||
}
|
||
|
||
#pragma segment Balloon
|
||
|
||
typedef enum
|
||
{
|
||
fhFirstTwo=1, /* descriptions of the first four controls; up, down, new, remove */
|
||
fhFilterTypes=3, /* in, out, manual */
|
||
fhList=9, /* list box */
|
||
fhHeader, /* header text boxes */
|
||
fhValue, /* value text boxes */
|
||
fhGreyNoSel, /* something is grey because no selection */
|
||
fhGreyOne, /* something is grey because only one term in use */
|
||
fhMatchType, /* match type help base */
|
||
fhConjunction=fhMatchType+mbmLimit-1, /* help for the conjunction */
|
||
fhDate=fhConjunction+cjLimit-1, /* date rectangle */
|
||
fhNone,
|
||
fhAction,
|
||
} FilterHelpEnum;
|
||
|
||
/************************************************************************
|
||
* FilterHelp - balloon help for the filter window
|
||
************************************************************************/
|
||
void FilterHelp(MyWindowPtr win,Point mouse)
|
||
{
|
||
#pragma unused(win)
|
||
Rect r;
|
||
FilterHelpEnum fh=0;
|
||
FilterHelpEnum greyFH=0;
|
||
short part;
|
||
ControlHandle cntl;
|
||
short cNum;
|
||
Str255 message;
|
||
Str255 grey;
|
||
FActionHandle fa;
|
||
short i;
|
||
short percent = 80;
|
||
|
||
*message = 0;
|
||
greyFH = Selected ? fhGreyOne : fhGreyNoSel;
|
||
|
||
/*
|
||
* help on controls
|
||
*/
|
||
if (part=FindControl(mouse,GetMyWindowWindowPtr(win),&cntl))
|
||
{
|
||
for (cNum=0;cNum<flLimit;cNum++)
|
||
if (Controls[cNum] == cntl)
|
||
{
|
||
GetControlBounds(cntl,&r);
|
||
if (cNum<=flRemoveButton)
|
||
fh = fhFirstTwo+cNum;
|
||
else if (cNum<=flManual)
|
||
fh = fhFilterTypes + 2*(cNum-flIncoming) + (GetControlValue(cntl) ? 0 : 1);
|
||
else switch(cNum)
|
||
{
|
||
case flMatchOnePop:
|
||
case flMatchTwoPop:
|
||
fh = fhMatchType + GetControlValue(cntl) - 1;
|
||
break;
|
||
case flConjunction:
|
||
fh = fhConjunction + GetControlValue(cntl) - 1;
|
||
break;
|
||
}
|
||
if (!ControlIsGrey(cntl)) greyFH = 0;
|
||
break;
|
||
}
|
||
}
|
||
if (!fh)
|
||
{
|
||
greyFH = Selected ? 0 : fhGreyNoSel;
|
||
if (PtInPETE(mouse,Block0.headerPTE)) {PeteRect(Block0.headerPTE,&r); fh = fhHeader; goto display;}
|
||
if (PtInPETE(mouse,Block0.valuePTE)) {PeteRect(Block0.valuePTE,&r); fh = fhValue; goto display;}
|
||
greyFH = Selected ? (HasTwo?0:fhGreyOne) : fhGreyNoSel;
|
||
if (PtInPETE(mouse,Block1.headerPTE)) {PeteRect(Block1.headerPTE,&r); fh = fhHeader+greyFH; goto display;}
|
||
if (PtInPETE(mouse,Block1.valuePTE)) {PeteRect(Block1.valuePTE,&r); fh = fhValue+greyFH; goto display;}
|
||
greyFH = 0;
|
||
r = Rects[flrList]; if (PtInRect(mouse,&r)) {fh = fhList; goto display;}
|
||
r = Rects[flrDate]; if (PtInRect(mouse,&r)) {fh = fhDate; goto display;}
|
||
|
||
if (Selected && !Multiple)
|
||
{
|
||
for (i=0,fa=FR[Selected-1].actions;fa;i++,fa=(*fa)->next)
|
||
{
|
||
r = Rects[flrAct1+i];
|
||
if (PtInRect(mouse,&r))
|
||
{
|
||
if ((*fa)->action==flkNone) fh = fhNone;
|
||
else
|
||
{
|
||
*message = 0;
|
||
CallAction(faeHelp,fa,&r,message);
|
||
fh = fhAction+1;
|
||
if (!*message) {percent=20; GetIndString(message,526,(*fa)->action);}
|
||
//Dprintf("\p1 %d.%d %d.%d <%d> <20>%p<>;g",r.left,r.top,r.right,r.bottom,fh,message);
|
||
}
|
||
goto display;
|
||
}
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
display:
|
||
if (fh==fhList)
|
||
{
|
||
MyBalloon(&r,90,0,0,FILT_LIST_HELP_PICT,nil);
|
||
}
|
||
else if (fh)
|
||
{
|
||
if (!*message)
|
||
{
|
||
GetRString(message,FILT_HELP_STRN+fh);
|
||
if (greyFH)
|
||
{
|
||
GetRString(grey,FILT_HELP_STRN+greyFH);
|
||
PSCat(message,grey);
|
||
}
|
||
}
|
||
//Dprintf("\p2 %d.%d %d.%d <%d> <20>%p<>;g",r.left,r.top,r.right,r.bottom,fh,message);
|
||
MyBalloon(&r,percent,0,0,0,message);
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FAflkNone - no action
|
||
**********************************************************************/
|
||
short FAflkNone(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FAflkStop - stop filtering now
|
||
**********************************************************************/
|
||
short FAflkStop(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
case faeResize:
|
||
case faeDraw:
|
||
case faeClose:
|
||
case faeDispose:
|
||
case faeRead:
|
||
break;
|
||
case faeWrite:
|
||
return(FWriteBool(*(short*)dataPtr,(*action)->action,True));
|
||
case faeButton:
|
||
case faeClick:
|
||
case faeSave:
|
||
break;
|
||
#ifdef FANCY_FILT_LDEF
|
||
case faeListDraw:
|
||
{
|
||
Point old;
|
||
GetPortPenLocation(GetQDGlobalsThePort(),&old);
|
||
r->right -= 10;
|
||
MoveTo(r->right+2,old.v);
|
||
PlotTinyIconAtPenID(ttNone,STOP_ICON);
|
||
MoveTo(old.h,old.v);
|
||
break;
|
||
}
|
||
#endif
|
||
case faeDo:
|
||
return(euFilterStop);
|
||
break;
|
||
}
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FAflkJunk - junk the current message
|
||
**********************************************************************/
|
||
short FAflkJunk(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
OSErr err = noErr;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
TOCHandle junkTOC = NULL;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
case faeResize:
|
||
case faeDraw:
|
||
case faeClose:
|
||
case faeDispose:
|
||
case faeRead:
|
||
break;
|
||
case faeWrite:
|
||
return(FWriteBool(*(short*)dataPtr,(*action)->action,True));
|
||
case faeButton:
|
||
case faeClick:
|
||
case faeSave:
|
||
break;
|
||
#ifdef FANCY_FILT_LDEF
|
||
case faeListDraw:
|
||
{
|
||
Point old;
|
||
GetPortPenLocation(GetQDGlobalsThePort(),&old);
|
||
r->right -= 10;
|
||
MoveTo(r->right+2,old.v);
|
||
PlotTinyIconAtPenID(ttNone,STOP_ICON);
|
||
MoveTo(old.h,old.v);
|
||
break;
|
||
}
|
||
#endif
|
||
case faeDo:
|
||
if (HasFeature (featureJunk))
|
||
{
|
||
// locate proper Junk mailbox
|
||
if ((*fpb->tocH)->imapTOC)
|
||
junkTOC = LocateIMAPJunkToc(fpb->tocH, true,true);
|
||
else
|
||
junkTOC = GetSpecialTOC(JUNK);
|
||
|
||
if (junkTOC)
|
||
{
|
||
UseFeature (featureJunk);
|
||
err = Junk(fpb->tocH,fpb->sumNum,true,false);
|
||
if (!err && ((fpb->tocH)!=junkTOC))
|
||
{
|
||
if (junkTOC)
|
||
{
|
||
fpb->spec = GetMailboxSpec(junkTOC,-1);
|
||
fpb->xferred = True;
|
||
fpb->dontUser = true;
|
||
}
|
||
err = euFilterXfered;
|
||
}
|
||
}
|
||
if (err && err!=euFilterXfered) err = euFilterStop; // continue filtering rest of messages in spite of error
|
||
}
|
||
return(err);
|
||
break;
|
||
}
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FAflkPrint - print one
|
||
**********************************************************************/
|
||
short FAflkPrint(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
case faeResize:
|
||
case faeDraw:
|
||
case faeClose:
|
||
case faeDispose:
|
||
case faeRead:
|
||
break;
|
||
case faeWrite:
|
||
return(FWriteBool(*(short*)dataPtr,(*action)->action,True));
|
||
case faeButton:
|
||
case faeClick:
|
||
case faeSave:
|
||
break;
|
||
case faeDo:
|
||
//Enhanced Filters - the print filter action is not supported in Light
|
||
if (HasFeature (featureFilterPrint)) {
|
||
UseFeature (featureFilterPrint);
|
||
#ifdef IMAP
|
||
// if this is an IMAP message, make sure it's been downloaded.
|
||
if ((*fpb->tocH)->imapTOC)
|
||
{
|
||
Boolean filteringUnderway = IMAPFilteringUnderway();
|
||
|
||
if (filteringUnderway) IMAPStopFiltering(false);
|
||
EnsureMsgDownloaded(fpb->tocH, fpb->sumNum, false);
|
||
if (filteringUnderway) IMAPStartFiltering(fpb->tocH, true);
|
||
}
|
||
#endif
|
||
fpb->print = True;
|
||
}
|
||
break;
|
||
}
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FAFlkTransfer - transfer message to another mailbox
|
||
**********************************************************************/
|
||
typedef struct
|
||
{
|
||
ControlHandle button;
|
||
FSSpec spec;
|
||
Boolean brandNew;
|
||
} FDflkTransfer, *FDflkTransferPtr, **FDflkTransferHandle;
|
||
|
||
short FAflkTransfer(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FDflkTransfer f;
|
||
OSErr err = noErr;
|
||
Str255 s;
|
||
FDflkTransferHandle data = (FDflkTransferHandle)(*action)->data;
|
||
Rect tempR;
|
||
Boolean copy = (*action)->action==flkCopy;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
FSSpec curSpec;
|
||
TOCHandle toTocH;
|
||
|
||
switch (callType)
|
||
{
|
||
/*
|
||
* initialize for the window
|
||
*/
|
||
case faeInit:
|
||
f.button = GetNewControlSmall(FILT_CNTL_BASE+flNewButton,GetMyWindowWindowPtr(Win));
|
||
if (!f.button) { err = ResError(); break; }
|
||
(*data)->button = f.button;
|
||
f.spec = (*data)->spec;
|
||
MailboxSpecAlias(&f.spec,s);
|
||
SetControlTitle(f.button,s);
|
||
EmbedControl(f.button,ActionGroup);
|
||
/* fall-through */
|
||
case faeResize:
|
||
f.button = (*data)->button;
|
||
ButtonFit(f.button);
|
||
FASingleRect(r,&tempR,ControlHi(f.button));
|
||
if (RectWi(tempR)>BUTTON_REASONABLE) tempR.right = tempR.left+BUTTON_REASONABLE;
|
||
MoveMyCntl(f.button,tempR.left,tempR.top,RectWi(tempR),0);
|
||
ShowControl(f.button);
|
||
if ((*data)->brandNew) goto buttonHit;
|
||
break;
|
||
|
||
/*
|
||
* close for window
|
||
*/
|
||
case faeDispose:
|
||
case faeClose:
|
||
if (data)
|
||
{
|
||
if ((*data)->button) DisposeControl((*data)->button);
|
||
(*data)->button = nil;
|
||
}
|
||
break;
|
||
|
||
/*
|
||
* do we care that a mailbox was renamed?
|
||
*/
|
||
case faeMBWillRename:
|
||
curSpec = (*data)->spec;
|
||
if (SameSpec(&curSpec,&((MBRenamePBPtr)dataPtr)->oldSpec)) err = 1;
|
||
break;
|
||
|
||
case faeMBDidRename:
|
||
curSpec = (*data)->spec;
|
||
if (SameSpec(&curSpec,&((MBRenamePBPtr)dataPtr)->oldSpec))
|
||
{
|
||
(*data)->spec = ((MBRenamePBPtr)dataPtr)->newSpec;
|
||
if (FLG && Win && (*data)->button) SetControlTitle((*data)->button,((MBRenamePBPtr)dataPtr)->newSpec.name);
|
||
}
|
||
break;
|
||
|
||
/*
|
||
* read in data
|
||
*/
|
||
case faeRead:
|
||
Zero(f);
|
||
if (dataPtr)
|
||
{
|
||
BoxSpecByName(&f.spec,dataPtr);
|
||
f.brandNew = False;
|
||
}
|
||
else f.brandNew = True;
|
||
data = NewZH(FDflkTransfer);
|
||
if (!data) err = MemError();
|
||
else
|
||
{
|
||
**data = f;
|
||
(*action)->data = (Handle)data;
|
||
}
|
||
break;
|
||
|
||
/*
|
||
* find
|
||
*/
|
||
case faeFind:
|
||
PCopy(s,(*data)->spec.name);
|
||
err = PFindSub(dataPtr,s)!=nil;
|
||
break;
|
||
|
||
#ifdef FANCY_FILT_LDEF
|
||
/*
|
||
* draw the item
|
||
*/
|
||
case faeListDraw:
|
||
{
|
||
Point old;
|
||
GetPortPenLocation(GetQDGlobalsThePort(),&old);
|
||
r->right -= 10;
|
||
MoveTo(r->right+2,old.v);
|
||
PlotTinyIconAtPenID(ttNone,copy?COPY_ICON:TRANSFER_ICON);
|
||
if ((*action)->action==flkTransfer) FAflkStop(callType,action,r,dataPtr);
|
||
MoveTo(old.h,old.v);
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
/*
|
||
* print
|
||
*/
|
||
case faePrint:
|
||
PCopy(s,(*data)->spec.name);
|
||
DrawString(s);
|
||
break;
|
||
|
||
/*
|
||
* write it out
|
||
*/
|
||
case faeWrite:
|
||
f.spec = (*data)->spec;
|
||
if (Box2Path(&f.spec,s)) PCopy(s,(*data)->spec.name);
|
||
if (*s) err = FWriteKey(*(short*)dataPtr,(*action)->action,s);
|
||
break;
|
||
|
||
/*
|
||
* button
|
||
*/
|
||
case faeButton:
|
||
f.button = (ControlHandle)dataPtr;
|
||
if (f.button==(*data)->button)
|
||
{
|
||
buttonHit:
|
||
if ((*data)->brandNew) UpdateMyWindow(GetMyWindowWindowPtr(Win));
|
||
(*data)->brandNew = False;
|
||
if (ChooseMailbox(TRANSFER_MENU,CHOOSE_MBOX_TRANSFER,&f.spec))
|
||
{
|
||
SetControlTitle(f.button,MailboxSpecAlias(&f.spec,s));
|
||
(*data)->spec = f.spec;
|
||
Win->isDirty = CurrentDirty = True;
|
||
}
|
||
return(True);
|
||
}
|
||
break;
|
||
|
||
case faeHelp:
|
||
if (MouseInControl((*data)->button))
|
||
{
|
||
GetControlBounds((*data)->button,r);
|
||
GetIndString(dataPtr,526,((*action)->action==flkTransfer ? flkhTransfer:flkhCopy));
|
||
}
|
||
break;
|
||
|
||
case faeDo:
|
||
if (!(*data)->spec.name) return(0); /* failure */
|
||
f = **data;
|
||
curSpec = GetMailboxSpec(fpb->tocH,-1);
|
||
if (SameSpec(&curSpec,&f.spec)) return(euFilterStop);
|
||
if (!copy && fpb->openMessage)
|
||
(*fpb->tocH)->sums[fpb->sumNum].opts |= OPT_OPEN;
|
||
if (!copy && fpb->print)
|
||
{
|
||
short oldstat = (*fpb->tocH)->sums[fpb->sumNum].state;
|
||
#ifdef IMAP
|
||
// if this is an IMAP message, make sure it's been downloaded before we try to print it
|
||
if ((*fpb->tocH)->imapTOC)
|
||
{
|
||
Boolean filteringUnderway = IMAPFilteringUnderway();
|
||
|
||
if (filteringUnderway) IMAPStopFiltering(false);
|
||
EnsureMsgDownloaded(fpb->tocH, fpb->sumNum, false);
|
||
if (filteringUnderway) IMAPStartFiltering(fpb->tocH, true);
|
||
}
|
||
#endif
|
||
PrintClosedMessage(fpb->tocH,fpb->sumNum,True);
|
||
SetState(fpb->tocH,fpb->sumNum,oldstat);
|
||
}
|
||
|
||
(*fpb->tocH)->sums[fpb->sumNum].flags |= FLAG_SKIPWARN;
|
||
|
||
// if this is a transfer to or from an IMAP mailbox, do the transfer in the foreground.
|
||
toTocH = TOCBySpec(&f.spec);
|
||
|
||
if (((*fpb->tocH)->imapTOC) || (toTocH && (*toTocH)->imapTOC))
|
||
{
|
||
err = IMAPMoveMessageDuringFiltering(fpb->tocH, fpb->sumNum, toTocH, (*action)->action==flkCopy, fpb);
|
||
}
|
||
else
|
||
err = MoveMessageLo(fpb->tocH,fpb->sumNum,&f.spec,(*action)->action==flkCopy,false,true);
|
||
|
||
if (!err)
|
||
{
|
||
if (!copy)
|
||
{
|
||
fpb->xferred = True;
|
||
#ifdef IMAP
|
||
if ((*fpb->tocH)->imapTOC) fpb->xferredFromIMAP = True;
|
||
#endif
|
||
fpb->spec = f.spec;
|
||
err = euFilterXfered;
|
||
}
|
||
else if ((fpb->doReport || PrefIsSet(PREF_REPORT)) && !fpb->dontReport)
|
||
AddSpecToList(&f.spec,fpb->report);
|
||
}
|
||
if (err && err!=euFilterXfered) err = euFilterStop; // continue filtering rest of messages in spite of error
|
||
break;
|
||
}
|
||
|
||
return(err);
|
||
}
|
||
/**********************************************************************
|
||
* FAflkMoveAttach - move attachments
|
||
**********************************************************************/
|
||
typedef struct
|
||
{
|
||
ControlHandle button;
|
||
FSSpec spec;
|
||
Boolean brandNew;
|
||
} FDflkMVA, *FDflkMVAPtr, **FDflkMVAHandle;
|
||
|
||
short FAflkMoveAttach(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FDflkMVA f;
|
||
OSErr err = noErr;
|
||
Str255 s;
|
||
FDflkMVAHandle data = (FDflkMVAHandle)(*action)->data;
|
||
Rect tempR;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
|
||
switch (callType)
|
||
{
|
||
/*
|
||
* initialize for the window
|
||
*/
|
||
case faeInit:
|
||
f.button = GetNewControlSmall(FILT_CNTL_BASE+flNewButton,GetMyWindowWindowPtr(Win));
|
||
if (!f.button) { err = ResError(); break; }
|
||
(*data)->button = f.button;
|
||
f.spec = (*data)->spec;
|
||
if ((*data)->brandNew || GetDirName(nil,f.spec.vRefNum,f.spec.parID,s))
|
||
*s = 0;
|
||
SetControlTitle(f.button,s);
|
||
EmbedControl(f.button,ActionGroup);
|
||
/* fall-through */
|
||
case faeResize:
|
||
f.button = (*data)->button;
|
||
ButtonFit(f.button);
|
||
FASingleRect(r,&tempR,ControlHi(f.button));
|
||
if (RectWi(tempR)>BUTTON_REASONABLE) tempR.right = tempR.left+BUTTON_REASONABLE;
|
||
MoveMyCntl(f.button,tempR.left,tempR.top,RectWi(tempR),0);
|
||
ShowControl(f.button);
|
||
if ((*data)->brandNew) goto buttonHit;
|
||
break;
|
||
|
||
/*
|
||
* close for window
|
||
*/
|
||
case faeDispose:
|
||
case faeClose:
|
||
if (data)
|
||
{
|
||
if ((*data)->button) DisposeControl((*data)->button);
|
||
(*data)->button = nil;
|
||
}
|
||
break;
|
||
|
||
/*
|
||
* do we care that a mailbox was renamed?
|
||
*/
|
||
case faeMBWillRename:
|
||
break;
|
||
|
||
case faeMBDidRename:
|
||
break;
|
||
|
||
/*
|
||
* read in data
|
||
*/
|
||
case faeRead:
|
||
Zero(f);
|
||
f.spec = AttFolderSpec;
|
||
if (dataPtr)
|
||
{
|
||
StringToNum(dataPtr,&f.spec.parID);
|
||
f.brandNew = False;
|
||
if (GetDirName(nil,f.spec.vRefNum,f.spec.parID,s)) f.spec = AttFolderSpec;
|
||
}
|
||
else
|
||
f.brandNew = True;
|
||
data = NewZH(FDflkMVA);
|
||
if (!data) err = MemError();
|
||
else
|
||
{
|
||
**data = f;
|
||
(*action)->data = (Handle)data;
|
||
}
|
||
break;
|
||
|
||
/*
|
||
* find
|
||
*/
|
||
case faeFind:
|
||
PCopy(s,(*data)->spec.name);
|
||
err = PFindSub(dataPtr,s)!=nil;
|
||
break;
|
||
|
||
#ifdef FANCY_FILT_LDEF
|
||
/*
|
||
* draw the item
|
||
*/
|
||
case faeListDraw:
|
||
break;
|
||
#endif
|
||
|
||
/*
|
||
* print
|
||
*/
|
||
case faePrint:
|
||
PCopy(s,(*data)->spec.name);
|
||
DrawString(s);
|
||
break;
|
||
|
||
/*
|
||
* write it out
|
||
*/
|
||
case faeWrite:
|
||
f.spec = (*data)->spec;
|
||
NumToString(f.spec.parID,s);
|
||
if (*s) err = FWriteKey(*(short*)dataPtr,(*action)->action,s);
|
||
break;
|
||
|
||
/*
|
||
* button
|
||
*/
|
||
case faeButton:
|
||
f.button = (ControlHandle)dataPtr;
|
||
if (f.button==(*data)->button)
|
||
{
|
||
buttonHit:
|
||
(*data)->brandNew = False;
|
||
if (GetFolder(s,&f.spec.vRefNum,&f.spec.parID,True,True,True,True))
|
||
{
|
||
if (f.spec.vRefNum!=AttFolderSpec.vRefNum)
|
||
{
|
||
WarnUser(SAME_VOLUME_DUMMY,0);
|
||
goto buttonHit;
|
||
}
|
||
*f.spec.name = 0;
|
||
GetDirName(nil,f.spec.vRefNum,f.spec.parID,s);
|
||
SetControlTitle(f.button,s);
|
||
(*data)->spec = f.spec;
|
||
Win->isDirty = CurrentDirty = True;
|
||
}
|
||
return(True);
|
||
}
|
||
break;
|
||
|
||
case faeHelp:
|
||
if (MouseInControl((*data)->button))
|
||
{
|
||
GetControlBounds((*data)->button,r);
|
||
GetIndString(dataPtr,526,((*action)->action==flkTransfer ? flkhTransfer:flkhCopy));
|
||
}
|
||
break;
|
||
|
||
case faeDo:
|
||
f = **data;
|
||
if ((*fpb->tocH)->sums[fpb->sumNum].flags&FLAG_HAS_ATT)
|
||
#ifdef IMAP
|
||
{
|
||
if ((*fpb->tocH)->imapTOC)
|
||
{
|
||
Boolean filteringUnderway = IMAPFilteringUnderway();
|
||
|
||
// deselect the current message. It may or may not go away, and it will just confuse the filtering process to keep it highlighted.
|
||
(*fpb->tocH)->sums[fpb->sumNum].selected = false;
|
||
InvalSum(fpb->tocH,fpb->sumNum);
|
||
|
||
// Filtering takes place in the foreground. Free up the connection for the upcoming transfer
|
||
if (filteringUnderway) IMAPStopFiltering(false);
|
||
|
||
EnsureMsgDownloaded(fpb->tocH, fpb->sumNum, false);
|
||
if (FetchAllIMAPAttachments(fpb->tocH, fpb->sumNum, true))
|
||
{
|
||
MovingAttachmentsLo(fpb->tocH,fpb->sumNum,True,False,False,false,nil,&f.spec);
|
||
}
|
||
|
||
// go back to filtering
|
||
if (filteringUnderway) IMAPStartFiltering(fpb->tocH, true);
|
||
}
|
||
else
|
||
#endif
|
||
MovingAttachmentsLo(fpb->tocH,fpb->sumNum,True,False,False,false,nil,&f.spec);
|
||
#ifdef IMAP
|
||
}
|
||
#endif
|
||
break;
|
||
}
|
||
|
||
return(err);
|
||
}
|
||
|
||
/************************************************************************
|
||
* SetNewAndOther - enable/disable "New" and/or "Other" mailbox menu items
|
||
************************************************************************/
|
||
static void SetNewAndOther(short menu,short newItem,short firstUserItem,Boolean disableNew,Boolean disableOther)
|
||
{
|
||
MenuHandle mh;
|
||
short menuCount,subID,item;
|
||
|
||
if (mh = GetMHandle(menu))
|
||
{
|
||
EnableIf(mh,newItem,!disableNew);
|
||
EnableIf(mh,newItem+1,!disableOther); // Other item
|
||
menuCount = CountMenuItems(mh);
|
||
for(item=firstUserItem;item<=menuCount;item++)
|
||
if (subID = SubmenuId(mh,item))
|
||
// Do submenu with recursion
|
||
SetNewAndOther(subID,1,3,disableNew,disableOther);
|
||
}
|
||
}
|
||
|
||
/************************************************************************
|
||
* DisableRemoteMailboxes - disable IMAP mailbox menu items
|
||
************************************************************************/
|
||
static void DisableRemoteMailboxes(short menu, Boolean restore)
|
||
{
|
||
MenuHandle mh;
|
||
short c;
|
||
PersHandle p;
|
||
Boolean disable;
|
||
Str255 itemText;
|
||
short vRef;
|
||
long dirId;
|
||
short it;
|
||
|
||
if (mh = GetMHandle(menu))
|
||
{
|
||
// the caller has asked for a local mailbox. Disable IMAP malboxes in this menu.
|
||
for (c = 1; c <= CountMenuItems(mh); c++)
|
||
{
|
||
MyGetItem(mh,c,itemText);
|
||
|
||
disable = false;
|
||
for (p = PersList; p && !disable; p = (*p)->next)
|
||
{
|
||
if (StringSame((*p)->name,itemText) && IsIMAPPers(p))
|
||
{
|
||
// This item has the same name as an IMAP personality
|
||
it = SubmenuId(mh,c);
|
||
if (it)
|
||
{
|
||
MenuID2VD(it,&vRef,&dirId);
|
||
if (IsIMAPVD(vRef, dirId))
|
||
{
|
||
// this item *is* an IMAP personality menu
|
||
disable = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (disable) EnableIf(mh, c, restore);
|
||
}
|
||
}
|
||
}
|
||
|
||
/************************************************************************
|
||
* ChooseMailboxLo - select a mailbox from Mailboxes or Transfer menu
|
||
* Allow disabling of new and other mailboxes
|
||
************************************************************************/
|
||
Boolean ChooseMailboxLo(short menu, PStr msgStr, FSSpecPtr spec, Boolean disableNew, Boolean disableOther, Boolean disableRemote)
|
||
{
|
||
short mId;
|
||
WindowPtr theWindow;
|
||
EventRecord event;
|
||
DialogPtr dgPtr;
|
||
MyWindowPtr dgPtrWin;
|
||
Boolean rslt = False;
|
||
|
||
PushGWorld();
|
||
|
||
/*
|
||
* put up message and disable all but transfer
|
||
*/
|
||
for (mId=APPLE_MENU;mId<MENU_LIMIT;mId++) DisableItem(GetMHandle(mId),0);
|
||
DisableItem(GetMHandle(WINDOW_MENU),0);
|
||
EnableItem(GetMHandle(menu),0);
|
||
DrawMenuBar();
|
||
ParamText(msgStr,"","","");
|
||
|
||
dgPtrWin = GetNewMyDialog (XFER_MENU_DLOG,nil,nil,InFront);
|
||
dgPtr = GetMyWindowDialogPtr (dgPtrWin);
|
||
// dgPtr = GetNewDialog(XFER_MENU_DLOG,nil,InFront);
|
||
// DrawDialog(dgPtr);
|
||
SetMyCursor(arrowCursor); SFWTC = True;
|
||
|
||
if (disableNew || disableOther)
|
||
// Disable "New" and/or "Other" menu items
|
||
SetNewAndOther(menu,MAILBOX_NEW_ITEM,MAILBOX_FIRST_USER_ITEM,disableNew,disableOther);
|
||
|
||
if (disableRemote)
|
||
// The caller has asked for local mailboxes only.
|
||
DisableRemoteMailboxes(menu, false);
|
||
|
||
/*
|
||
* now, let the user choose something:
|
||
*/
|
||
PushModalWindow(GetDialogWindow(dgPtr));
|
||
DirtyHackForChooseMailbox = true;
|
||
for (;;)
|
||
{
|
||
if (WNE(mDownMask|keyDownMask|updateMask,&event,REAL_BIG))
|
||
{
|
||
if (event.what==updateEvt) MiniMainLoop(&event);
|
||
// Check for mouseDown and keyDown events. WNE in OS X
|
||
// is currently return more than what's in the event mask.
|
||
else if (event.what==mouseDown || event.what==keyDown) break;
|
||
}
|
||
}
|
||
PopModalWindow();
|
||
if (event.what==mouseDown)
|
||
{
|
||
if (inMenuBar == FindWindow_(event.where,&theWindow))
|
||
{
|
||
long mSelect = MenuSelect(event.where);
|
||
short mnu, itm;
|
||
|
||
mnu = (mSelect>>16)&0xffff;
|
||
itm = mSelect & 0xffff;
|
||
if (mnu==menu || IsMailboxSubmenu(mnu))
|
||
{
|
||
rslt=GetTransferParams(mnu,itm,spec,nil);
|
||
}
|
||
HiliteMenu(0);
|
||
}
|
||
}
|
||
DisposDialog_(dgPtr);
|
||
EnableMenus(FrontWindow_(),False);
|
||
DirtyHackForChooseMailbox = false;
|
||
|
||
if (disableNew || disableOther)
|
||
// Restore "New" and "Other" mailbox menu items
|
||
SetNewAndOther(menu,MAILBOX_NEW_ITEM,MAILBOX_FIRST_USER_ITEM,false,false);
|
||
|
||
if (disableRemote)
|
||
// The caller has asked for local mailboxes only.
|
||
DisableRemoteMailboxes(menu, true);
|
||
|
||
PopGWorld();
|
||
return(rslt);
|
||
}
|
||
|
||
/************************************************************************
|
||
* ChooseMailbox - select a mailbox from Mailboxes or Transfer menu
|
||
************************************************************************/
|
||
Boolean ChooseMailbox(short menu, short msg, FSSpecPtr spec)
|
||
{
|
||
Str255 msgStr;
|
||
return ChooseMailboxLo(menu,GetRString(msgStr,msg),spec,false,false,false);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FASingleRect - size a single rectangle in an action area
|
||
**********************************************************************/
|
||
void FASingleRect(Rect *inRect, Rect *r,short hi)
|
||
{
|
||
Rect popup = *inRect;
|
||
short lines;
|
||
|
||
FAPopup(&popup);
|
||
lines = (RectHi(*inRect)-3*INSET)/Win->vPitch;
|
||
|
||
if (lines<=1 || hi)
|
||
{
|
||
*r = popup;
|
||
r->left = popup.right+2*INSET;
|
||
r->right = inRect->right - 2*INSET;
|
||
if (hi) r->bottom = r->top+hi;
|
||
}
|
||
else
|
||
{
|
||
hi = Win->vPitch*((RectHi(*inRect)-Win->vPitch-2*INSET)/Win->vPitch) + 2*TE_VMARGIN;
|
||
r->top = popup.bottom + (inRect->bottom-popup.bottom-hi)/2;
|
||
SetRect(r,popup.left+GROW_SIZE,r->top,inRect->right-GROW_SIZE,r->top+hi);
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
void FAPopActRect(Rect *inRect, Rect *r)
|
||
{
|
||
short wi;
|
||
|
||
*r = *inRect;
|
||
FAPopup(r);
|
||
wi = RectWi(*r);
|
||
r->left = r->right + 2*INSET;
|
||
r->right = inRect->right - 2*INSET;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FAMultRect - size multiple rectangles in an action area
|
||
**********************************************************************/
|
||
void FAMultRect(Rect *inRect, Rect *r,short *spacing,short hi,short n)
|
||
{
|
||
Rect overall;
|
||
|
||
FASingleRect(inRect,&overall,0);
|
||
*spacing = (RectHi(overall)>2*Win->vPitch) ? 2*INSET : INSET;
|
||
|
||
if (hi)
|
||
{
|
||
OffsetRect(&overall,0,(RectHi(overall)-hi)/2);
|
||
overall.bottom = overall.top + hi;
|
||
}
|
||
overall.right = overall.left + (RectWi(overall)-(n-1)*(*spacing))/n;
|
||
*r = overall;
|
||
}
|
||
|
||
#pragma segment FiltActions
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
short FAflkCopy(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
return(FAflkTransfer(callType,action,r,dataPtr));
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
short FAflkTranslit(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
return(noErr);
|
||
}
|
||
|
||
typedef struct
|
||
{
|
||
Rect r;
|
||
long status;
|
||
ControlHandle popup;
|
||
} FDflkStatus, **FDflkStatusHandle;
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
short FAflkStatus(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FDflkStatusHandle data;
|
||
FDflkStatus f;
|
||
Str255 s;
|
||
OSErr err = noErr;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
short item;
|
||
Rect controlR;
|
||
|
||
data = (void*)(*action)->data;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
f = **data;
|
||
f.popup = GetNewControlSmall(FILT_STATUS_POP,GetMyWindowWindowPtr(Win));
|
||
if (!f.popup)
|
||
{
|
||
FAflkStatus(faeDispose,action,nil,nil);
|
||
return(MEM_ERR);
|
||
}
|
||
item = Status2Item(f.status);
|
||
|
||
MySetCtlValue(f.popup,item);
|
||
EmbedControl(f.popup,ActionGroup);
|
||
**data = f;
|
||
// fall-through
|
||
|
||
case faeResize:
|
||
f = **data;
|
||
FAPopupValueFit(r,f.popup);
|
||
ShowControl(f.popup);
|
||
break;
|
||
|
||
case faeHelp:
|
||
FAPopActRect(r,&controlR);
|
||
if (MouseInRect(&controlR))
|
||
{
|
||
*r = controlR;
|
||
GetIndString(dataPtr,526,flkhStatus);
|
||
}
|
||
break;
|
||
|
||
case faeDraw:
|
||
f = **data;
|
||
if (f.popup)
|
||
{
|
||
MenuHandle mh = GetMHandle(STATE_HIER_MENU);
|
||
CGrafPtr WinPort = GetMyWindowCGrafPtr (Win);
|
||
EnableItem(mh,0);
|
||
Update1Control(f.popup,MyGetPortVisibleRegion(WinPort));
|
||
#ifdef GRIDLINES
|
||
ControlGridlines(f.popup);
|
||
#endif
|
||
}
|
||
break;
|
||
|
||
case faeRead:
|
||
data = NuHandleClear(sizeof(FDflkStatus)); /* if we can't find a dozen bytes, we're dead */
|
||
if (!data) return(MemError());
|
||
(*action)->data = (void*)data;
|
||
if (dataPtr)
|
||
{
|
||
StringToNum(dataPtr,&f.status);
|
||
(*data)->status = f.status;
|
||
}
|
||
else (*data)->status = UNREAD; // gotta be something
|
||
break;
|
||
|
||
case faePrint:
|
||
MyGetItem(GetMHandle(STATE_HIER_MENU),Status2Item((*data)->status),s);
|
||
DrawString(s);
|
||
break;
|
||
|
||
case faeWrite:
|
||
NumToString((*data)->status,s);
|
||
err = FWriteKey(*(short*)dataPtr,flkStatus,s);
|
||
break;
|
||
|
||
case faeButton:
|
||
f = **data;
|
||
item = GetControlValue(f.popup);
|
||
item = Item2Status(item);
|
||
if (item!=f.status)
|
||
{
|
||
f.status = item;
|
||
Win->isDirty = CurrentDirty = True;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeFind:
|
||
MyGetItem(GetMHandle(STATE_HIER_MENU),(*data)->status,s);
|
||
err = PFindSub(dataPtr,s)!=nil;
|
||
break;
|
||
|
||
case faeClick:
|
||
break;
|
||
|
||
case faeClose:
|
||
case faeDispose:
|
||
if (data)
|
||
{
|
||
f = **data;
|
||
if (f.popup) DisposeControl(f.popup);
|
||
f.popup = nil;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeDo:
|
||
SetState(fpb->tocH,fpb->sumNum,(*data)->status);
|
||
break;
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FAflkSubject - change a subject
|
||
**********************************************************************/
|
||
typedef struct FDflkSubject **FDflkSubjectHandle;
|
||
typedef struct FDflkSubject
|
||
{
|
||
PETEHandle pte;
|
||
Str255 subject;
|
||
} FDflkSubject;
|
||
|
||
short FAflkSubject(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FDflkSubjectHandle data = (FDflkSubjectHandle)(*action)->data;
|
||
FDflkSubject f;
|
||
Rect textR;
|
||
OSErr err = noErr;
|
||
Str255 s;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
SetRect(&textR,0,0,0,0);
|
||
if (err=PeteCreate(Win,&f.pte,0,nil)) return(WarnUser(PETE_ERR,err));
|
||
PeteFontAndSize(f.pte,GetPortTextFont(GetQDGlobalsThePort()),GetPortTextSize(GetQDGlobalsThePort()));
|
||
(*PeteExtra(f.pte))->frame = True;
|
||
(*PeteExtra(f.pte))->infinitelyWide = True;
|
||
PCopy(s,(*data)->subject);
|
||
PeteSetString(s,f.pte);
|
||
(*data)->pte = f.pte;
|
||
PETESetCallback(PETE,f.pte,(void*)FilterChanged,peDocChanged);
|
||
/* fall through */
|
||
case faeResize:
|
||
FASingleRect(r,&textR,ONE_LINE_HI(Win));
|
||
PeteDidResize((*data)->pte,&textR);
|
||
break;
|
||
|
||
case faeNew:
|
||
PeteFocus(Win,(*data)->pte,true);
|
||
break;
|
||
|
||
case faeDraw:
|
||
break;
|
||
|
||
case faeFind:
|
||
err = PeteFindString(dataPtr,0,(*data)->pte)>=0;
|
||
break;
|
||
|
||
case faePrint:
|
||
PCopy(s,(*data)->subject);
|
||
DrawString(s);
|
||
break;
|
||
|
||
case faeCursor:
|
||
if (PtInPETE(*(Point*)r,(*data)->pte))
|
||
*(short*)dataPtr = iBeamCursor;
|
||
else
|
||
*(short*)dataPtr = arrowCursor;
|
||
break;
|
||
|
||
case faeDispose:
|
||
case faeClose:
|
||
if (data)
|
||
{
|
||
PeteDispose(Win,(*data)->pte);
|
||
(*data)->pte = nil;
|
||
}
|
||
break;
|
||
|
||
case faeRead:
|
||
data = NewZH(FDflkSubject);
|
||
if (!data) return(WarnUser(MEM_ERR,MemError()));
|
||
else
|
||
{
|
||
(*action)->data = (void*)data;
|
||
if (dataPtr) PCopy((*data)->subject,(UPtr)dataPtr);
|
||
}
|
||
break;
|
||
|
||
case faeWrite:
|
||
PCopy(s,(*data)->subject);
|
||
if (*s) err = FWriteKey(*(short*)dataPtr,flkSubject,s);
|
||
break;
|
||
|
||
case faeHelp:
|
||
if (MouseInPTE((*data)->pte))
|
||
{
|
||
PeteRect((*data)->pte,r);
|
||
GetIndString(dataPtr,526,flkhSubject);
|
||
}
|
||
break;
|
||
|
||
case faeClick:
|
||
if (PtInPETE(*(Point*)r,(*data)->pte))
|
||
{
|
||
PeteEditWFocus(Win,(*data)->pte,peeEvent,dataPtr,nil);
|
||
err = True; /* actually, not an error, but... */
|
||
}
|
||
break;
|
||
|
||
case faeSave:
|
||
PeteSString(s,(*data)->pte);
|
||
PCopy((*data)->subject,s);
|
||
break;
|
||
|
||
case faeDo:
|
||
PCopy(s,(*data)->subject);
|
||
NonSequitur(s,fpb->tocH,fpb->sumNum);
|
||
break;
|
||
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FAflkLabel - set the label for a message
|
||
**********************************************************************/
|
||
typedef struct FDflkLabel **FDflkLabelHandle;
|
||
typedef struct FDflkLabel
|
||
{
|
||
long color;
|
||
Rect r;
|
||
ControlHandle popup;
|
||
} FDflkLabel;
|
||
|
||
short FAflkLabel(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FDflkLabelHandle data;
|
||
FDflkLabel f;
|
||
RGBColor oldColor,color;
|
||
Str255 s;
|
||
OSErr err = noErr;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
short item;
|
||
|
||
data = (void*)(*action)->data;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
f = **data;
|
||
f.popup = GetNewControlSmall(FILT_LABEL_POP,GetMyWindowWindowPtr(Win));
|
||
if (!f.popup)
|
||
{
|
||
FAflkStatus(faeDispose,action,nil,nil);
|
||
return(MEM_ERR);
|
||
}
|
||
**data = f;
|
||
FAflkLabel(faeMouseGoingDown,action,r,dataPtr);
|
||
MySetCtlValue(f.popup,Label2Menu(f.color));
|
||
EmbedControl(f.popup,ActionGroup);
|
||
// fall-through
|
||
|
||
case faeResize:
|
||
f = **data;
|
||
FAPopupValueFit(r,f.popup);
|
||
ShowControl(f.popup);
|
||
break;
|
||
|
||
case faeClose:
|
||
case faeDispose:
|
||
if (data)
|
||
{
|
||
f = **data;
|
||
if (f.popup) DisposeControl(f.popup);
|
||
f.popup = nil;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeButton:
|
||
f = **data;
|
||
item = GetControlValue(f.popup);
|
||
item = Menu2Label(item);
|
||
if (item!=f.color)
|
||
{
|
||
f.color = item;
|
||
Win->isDirty = CurrentDirty = True;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeMouseGoingDown:
|
||
{
|
||
MenuHandle mh;
|
||
f = **data;
|
||
if (f.popup && (mh = GetControlPopupMenuHandle(f.popup)))
|
||
{
|
||
TrashMenu(mh,3);
|
||
AddFinderItems(mh);
|
||
SetItemMark(mh,1,noMark);
|
||
SetItemMark(mh,GetControlValue(f.popup),diamondChar);
|
||
EnableItem(mh,0);
|
||
SetControlMaximum(f.popup,CountMenuItems(mh));
|
||
}
|
||
break;
|
||
}
|
||
|
||
case faeHelp:
|
||
FAPopActRect(r,&f.r);
|
||
if (MouseInRect(&f.r))
|
||
{
|
||
*r = f.r;
|
||
GetIndString(dataPtr,526,flkhLabel);
|
||
}
|
||
break;
|
||
case faeDraw:
|
||
f = **data;
|
||
if (f.popup)
|
||
{
|
||
CGrafPtr WinPort = GetMyWindowCGrafPtr (Win);
|
||
MenuHandle mh = GetMHandle(LABEL_HIER_MENU);
|
||
EnableItem(mh,0);
|
||
Update1Control(f.popup,MyGetPortVisibleRegion(WinPort));
|
||
#ifdef GRIDLINES
|
||
ControlGridlines(f.popup);
|
||
#endif
|
||
}
|
||
break;
|
||
|
||
case faeRead:
|
||
data = NewZH(FDflkLabel); /* if we can't find a dozen bytes, we're dead */
|
||
if (!data) return(MemError());
|
||
(*action)->data = (void*)data;
|
||
if (dataPtr)
|
||
{
|
||
StringToNum(dataPtr,&f.color);
|
||
(*data)->color = f.color;
|
||
}
|
||
break;
|
||
|
||
case faePrint:
|
||
//No labels in Light, no label menu
|
||
if (HasFeature (featureFilterLabel)) {
|
||
MyGetLabel((*data)->color,&color,s);
|
||
if (ThereIsColor)
|
||
{
|
||
GetForeColor(&oldColor);
|
||
RGBForeColor(&color);
|
||
}
|
||
DrawString(s);
|
||
if (ThereIsColor) RGBForeColor(&oldColor);
|
||
}
|
||
break;
|
||
|
||
case faeWrite:
|
||
NumToString((*data)->color,s);
|
||
err = FWriteKey(*(short*)dataPtr,flkLabel,s);
|
||
break;
|
||
|
||
case faeFind:
|
||
//No labels in Light, no label menu
|
||
if (HasFeature (featureFilterLabel)) {
|
||
MyGetLabel((*data)->color,&color,s);
|
||
err = PFindSub(dataPtr,s)!=nil;
|
||
}
|
||
break;
|
||
|
||
#ifdef FANCY_FILT_LDEF
|
||
case faeListDraw:
|
||
//No labels in Light, no label menu
|
||
if (HasFeature (featureFilterLabel)) {
|
||
MyGetLabel((*data)->color,&color,s);
|
||
if (ThereIsColor && !BlackWhite(&color)) RGBForeColor(DarkenColor(&color,GetRLong(TEXT_DARKER)));
|
||
}
|
||
break;
|
||
#endif
|
||
|
||
case faeDo:
|
||
//No labels in Light, no label menu
|
||
if (HasFeature (featureFilterLabel)) {
|
||
UseFeature (featureFilterLabel);
|
||
SetSumColor(fpb->tocH,fpb->sumNum,(*data)->color);
|
||
}
|
||
break;
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
|
||
/**********************************************************************
|
||
* FAflkPersonality - set the label for a message
|
||
**********************************************************************/
|
||
typedef struct FDflkPers **FDflkPersHandle;
|
||
typedef struct FDflkPers
|
||
{
|
||
long persId;
|
||
Rect r;
|
||
ControlHandle popup;
|
||
} FDflkPers;
|
||
short FAflkPersonality(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
OSErr err = noErr;
|
||
Str255 s;
|
||
FilterPBPtr fpb;
|
||
PersHandle pers;
|
||
uLong persId;
|
||
Rect localR;
|
||
FDflkPersHandle data;
|
||
FDflkPers f;
|
||
short item;
|
||
|
||
if (!HasFeature (featureFilterPersonality))
|
||
return (err);
|
||
|
||
fpb = (FilterPBPtr)dataPtr;
|
||
data = (FDflkPersHandle)(*action)->data;
|
||
|
||
if (data)
|
||
{
|
||
persId = (uLong)(*data)->persId;
|
||
pers = PERS_FORCE(FindPersById(persId));
|
||
f = **data;
|
||
}
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
f = **data;
|
||
f.popup = GetNewControlSmall(FILT_PERS_POP,GetMyWindowWindowPtr(Win));
|
||
if (!f.popup)
|
||
{
|
||
FAflkPersonality(faeDispose,action,nil,nil);
|
||
return(MEM_ERR);
|
||
}
|
||
**data = f;
|
||
FAflkPersonality(faeMouseGoingDown,action,r,dataPtr);
|
||
item = Pers2Index(pers);
|
||
if (item>0) item+=2;
|
||
else item+=1;
|
||
MySetCtlValue(f.popup,item);
|
||
EmbedControl(f.popup,ActionGroup);
|
||
// fall-through
|
||
|
||
case faeResize:
|
||
f = **data;
|
||
FAPopupValueFit(r,f.popup);
|
||
ShowControl(f.popup);
|
||
break;
|
||
|
||
case faeDraw:
|
||
f = **data;
|
||
if (f.popup)
|
||
{
|
||
MenuHandle mh = GetMHandle(PERS_HIER_MENU);
|
||
CGrafPtr WinPort = GetMyWindowCGrafPtr (Win);
|
||
EnableItem(mh,0);
|
||
Update1Control(f.popup,MyGetPortVisibleRegion(WinPort));
|
||
#ifdef GRIDLINES
|
||
ControlGridlines(f.popup);
|
||
#endif
|
||
}
|
||
break;
|
||
|
||
case faeClose:
|
||
case faeDispose:
|
||
if (data)
|
||
{
|
||
f = **data;
|
||
if (f.popup) DisposeControl(f.popup);
|
||
f.popup = nil;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeButton:
|
||
f = **data;
|
||
item = Pers2Index(pers);
|
||
if (item) item += 2;
|
||
else item++;
|
||
if (item!=GetControlValue(f.popup))
|
||
{
|
||
item = GetControlValue(f.popup);
|
||
item--;
|
||
if (item) item--;
|
||
f.persId = (*Index2Pers(item))->persId;
|
||
Win->isDirty = CurrentDirty = True;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeMouseGoingDown:
|
||
{
|
||
MenuHandle mh;
|
||
Str255 string;
|
||
f = **data;
|
||
if (f.popup && (mh = GetControlPopupMenuHandle(f.popup)))
|
||
{
|
||
TrashMenu(mh,3);
|
||
for (pers=(*PersList)->next;pers;pers=(*pers)->next)
|
||
MyAppendMenu(mh,PCopy(string,(*pers)->name));
|
||
SetItemMark(mh,1,noMark);
|
||
SetItemMark(mh,GetControlValue(f.popup),diamondChar);
|
||
EnableItem(mh,0);
|
||
SetControlMaximum(f.popup,CountMenuItems(mh));
|
||
}
|
||
}
|
||
|
||
|
||
case faeHelp:
|
||
FAPopActRect(r,&localR);
|
||
if (MouseInRect(&localR))
|
||
{
|
||
*r = localR;
|
||
GetIndString(dataPtr,526,flkhPersonality);
|
||
}
|
||
break;
|
||
|
||
case faeRead:
|
||
data = NewZH(FDflkPers); /* if we can't find a dozen bytes, we're dead */
|
||
if (!data) return(MemError());
|
||
(*action)->data = (void*)data;
|
||
if (dataPtr && *(UPtr)dataPtr) persId = (*PERS_FORCE(FindPersByName(dataPtr)))->persId;
|
||
else persId = 0;
|
||
(*data)->persId = persId;
|
||
break;
|
||
|
||
case faePrint:
|
||
PSCopy(s,(*pers)->name);
|
||
DrawString(s);
|
||
break;
|
||
|
||
case faeWrite:
|
||
if (pers==PersList) *s = 0;
|
||
else PSCopy(s,(*pers)->name);
|
||
if (*s)
|
||
err = FWriteKey(*(short*)dataPtr,flkPersonality,s);
|
||
else
|
||
err = FWriteBool(*(short*)dataPtr,flkPersonality,True);
|
||
break;
|
||
|
||
case faeFind:
|
||
PSCopy(s,(*pers)->name);
|
||
err = PFindSub(dataPtr,s)!=nil;
|
||
break;
|
||
|
||
case faeDo:
|
||
//Enhanced Filters - the personalities action is not supported in Light
|
||
if (HasFeature (featureMultiplePersonalities)) {
|
||
if (pers != PersList)
|
||
UseFeature (featureFilterPersonality);
|
||
SetPers(fpb->tocH,fpb->sumNum,pers,False);
|
||
}
|
||
break;
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
typedef struct FDflkSound **FDflkSoundHandle;
|
||
typedef struct FDflkSound
|
||
{
|
||
ControlHandle popup;
|
||
Str255 name;
|
||
} FDflkSound;
|
||
short FAflkSound(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FDflkSoundHandle data;
|
||
FDflkSound f;
|
||
Str255 s;
|
||
OSErr err = noErr;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
short item;
|
||
MenuHandle mh;
|
||
|
||
data = (void*)(*action)->data;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
f = **data;
|
||
f.popup = GetNewControlSmall(FILT_SOUND_CNTL,GetMyWindowWindowPtr(Win));
|
||
if (!f.popup)
|
||
{
|
||
FAflkSound(faeDispose,action,nil,nil);
|
||
return(MEM_ERR);
|
||
}
|
||
|
||
mh = (MenuHandle)GetControlPopupMenuHandle(f.popup);
|
||
AddSoundsToMenu(mh);
|
||
SetControlMaximum(f.popup,CountMenuItems(mh));
|
||
item = FindItemByName(mh,f.name);
|
||
if (!item) {
|
||
item = 1;
|
||
GetMenuItemText(mh,item,f.name);
|
||
}
|
||
|
||
MySetCtlValue(f.popup,item);
|
||
EmbedControl(f.popup,ActionGroup);
|
||
**data = f;
|
||
/* fall-through */
|
||
|
||
case faeResize:
|
||
f = **data;
|
||
FAPopupValueFit(r,f.popup);
|
||
ShowControl(f.popup);
|
||
break;
|
||
|
||
|
||
case faeHelp:
|
||
if (MouseInControl((*data)->popup))
|
||
{
|
||
GetControlBounds((*data)->popup,r);
|
||
GetIndString(dataPtr,526,flkhSound);
|
||
}
|
||
break;
|
||
|
||
case faeDraw:
|
||
break;
|
||
|
||
case faeRead:
|
||
data = NewZH(FDflkSound); /* if we can't find a dozen bytes, we're dead */
|
||
if (!data) return(MemError());
|
||
(*action)->data = (void*)data;
|
||
if (dataPtr) PCopy((*data)->name,(UPtr)dataPtr);
|
||
break;
|
||
|
||
case faeWrite:
|
||
PCopy(f.name,(*data)->name);
|
||
if (*f.name) err = FWriteKey(*(short*)dataPtr,flkSound,f.name);
|
||
break;
|
||
|
||
case faeFind:
|
||
PCopy(f.name,(*data)->name);
|
||
err = PFindSub(dataPtr,f.name)!=nil;
|
||
break;
|
||
|
||
case faeButton:
|
||
f = **data;
|
||
item = GetControlValue(f.popup);
|
||
GetMenuItemText((MenuHandle)GetControlPopupMenuHandle(f.popup),item,s);
|
||
if (*s) PlayNamedSound(s);
|
||
if (!StringSame(f.name,s))
|
||
{
|
||
Win->isDirty = CurrentDirty = True;
|
||
PCopy(f.name,s);
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeClose:
|
||
case faeDispose:
|
||
if (data)
|
||
{
|
||
f = **data;
|
||
if (f.popup) DisposeControl(f.popup);
|
||
f.popup = nil;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faePrint:
|
||
f = **data;
|
||
DrawString(f.name);
|
||
break;
|
||
|
||
case faeDo:
|
||
//Enhanced Filters - the sound filter action is not supported in Light
|
||
if (HasFeature (featureFilterSound)) {
|
||
UseFeature (featureFilterSound);
|
||
f = **data;
|
||
if (*f.name) PlayNamedSound(f.name);
|
||
}
|
||
break;
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
typedef struct FDflkOpen **FDflkOpenHandle;
|
||
typedef struct FDflkOpen
|
||
{
|
||
long flags;
|
||
ControlHandle message;
|
||
ControlHandle mailbox;
|
||
} FDflkOpen;
|
||
short FAflkOpenMessage(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FDflkOpenHandle data = (FDflkOpenHandle)(*action)->data;
|
||
FDflkOpen f;
|
||
Rect controlR;
|
||
short spacing;
|
||
short val;
|
||
WindowPtr WinWP;
|
||
ControlHandle button = (ControlHandle)dataPtr;
|
||
Str63 s;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
long flag;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
WinWP = GetMyWindowWindowPtr (Win);
|
||
f.mailbox = GetNewControlSmall(OPEN_BOX_CNTL,WinWP);
|
||
f.message = GetNewControlSmall(OPEN_MESSAGE_CNTL,WinWP);
|
||
if (!f.mailbox || !f.message)
|
||
{
|
||
FAflkOpenMessage(faeDispose,action,nil,nil);
|
||
return(MEM_ERR);
|
||
}
|
||
f.flags = (*data)->flags;
|
||
**data = f;
|
||
MySetCtlValue(f.mailbox,0!=(f.flags&afbOpenMailbox));
|
||
MySetCtlValue(f.message,0!=(f.flags&afbOpenMessage));
|
||
EmbedControl(f.mailbox,ActionGroup);
|
||
EmbedControl(f.message,ActionGroup);
|
||
/* fall-through */
|
||
case faeResize:
|
||
f = **data;
|
||
ButtonFit(f.mailbox);
|
||
ButtonFit(f.message);
|
||
FAMultRect(r,&controlR,&spacing,ControlHi(f.mailbox),2);
|
||
MoveMyCntl(f.mailbox,controlR.left,controlR.top,RectWi(controlR),0);
|
||
OffsetRect(&controlR,RectWi(controlR)+spacing,0);
|
||
MoveMyCntl(f.message,controlR.left,controlR.top,RectWi(controlR),0);
|
||
ShowControl(f.message);
|
||
ShowControl(f.mailbox);
|
||
break;
|
||
|
||
case faeClose:
|
||
case faeDispose:
|
||
if (data)
|
||
{
|
||
f = **data;
|
||
if (f.message) DisposeControl(f.message);
|
||
if (f.mailbox) DisposeControl(f.mailbox);
|
||
f.mailbox = f.message = nil;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeRead:
|
||
data = NewZH(FDflkOpen); /* if we can't find a dozen bytes, we're dead */
|
||
if (!data) return(MemError());
|
||
(*action)->data = (void*)data;
|
||
if (dataPtr) StringToNum(dataPtr,&f.flags);
|
||
else f.flags = 0;
|
||
(*data)->flags = f.flags;
|
||
break;
|
||
|
||
case faePrint:
|
||
if ((*data)->flags&afbOpenMailbox)
|
||
{
|
||
DrawRString(MAILBOX_PRINT);
|
||
if ((*data)->flags&afbOpenMessage)
|
||
{
|
||
DrawRString(AND_PRINT);
|
||
DrawRString(MESSAGE_PRINT);
|
||
}
|
||
}
|
||
else if ((*data)->flags&afbOpenMessage)
|
||
{
|
||
DrawRString(MESSAGE_PRINT);
|
||
}
|
||
break;
|
||
|
||
case faeWrite:
|
||
NumToString((*data)->flags,s);
|
||
return(FWriteKey(*(short*)dataPtr,(*action)->action,s));
|
||
break;
|
||
|
||
case faeButton:
|
||
f = **data;
|
||
val = !GetControlValue(button);
|
||
MySetCtlValue(button,val);
|
||
flag = (button==f.mailbox) ? afbOpenMailbox : afbOpenMessage;
|
||
if (val)
|
||
(*data)->flags |= flag;
|
||
else
|
||
(*data)->flags &= ~flag;
|
||
break;
|
||
|
||
case faeHelp:
|
||
f = **data;
|
||
if (MouseInControl(f.mailbox))
|
||
{
|
||
GetIndString(dataPtr,526,flkhOpenBox);
|
||
GetControlBounds(f.mailbox,r);
|
||
}
|
||
if (MouseInControl(f.message))
|
||
{
|
||
GetIndString(dataPtr,526,flkhOpenMess);
|
||
GetControlBounds(f.message,r);
|
||
}
|
||
break;
|
||
|
||
case faeDo:
|
||
//Enhanced Filters - the open message filter action is not supported in Light
|
||
if (HasFeature (featureFilterOpen)) {
|
||
UseFeature (featureFilterOpen);
|
||
fpb->openMailbox = 0!=((*data)->flags&afbOpenMailbox);
|
||
fpb->openMessage = 0!=((*data)->flags&afbOpenMessage);
|
||
ComposeLogS(LOG_FILT,nil,"\pOpen %d %d",fpb->openMailbox,fpb->openMessage);
|
||
}
|
||
break;
|
||
}
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
typedef struct FDflkPrior **FDflkPriorHandle;
|
||
typedef struct FDflkPrior
|
||
{
|
||
long prior;
|
||
Rect r;
|
||
ControlHandle popup;
|
||
} FDflkPrior;
|
||
|
||
short FAflkPriority(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FDflkPriorHandle data;
|
||
FDflkPrior f;
|
||
Str255 s;
|
||
OSErr err = noErr;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
Rect ir;
|
||
short item;
|
||
Point penLoc;
|
||
|
||
data = (void*)(*action)->data;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
f = **data;
|
||
f.popup = GetNewControlSmall(FILT_PRIORITY_POP,GetMyWindowWindowPtr(Win));
|
||
if (!f.popup)
|
||
{
|
||
FAflkStatus(faeDispose,action,nil,nil);
|
||
return(MEM_ERR);
|
||
}
|
||
item = f.prior ? f.prior : 3;
|
||
|
||
MySetCtlValue(f.popup,item);
|
||
**data = f;
|
||
EmbedControl(f.popup,ActionGroup);
|
||
// fall-through
|
||
|
||
case faeResize:
|
||
f = **data;
|
||
FAPopupValueFit(r,f.popup);
|
||
ShowControl(f.popup);
|
||
break;
|
||
|
||
case faeHelp:
|
||
f.r = (*data)->r;
|
||
if (MouseInRect(&f.r))
|
||
{
|
||
*r = f.r;
|
||
GetIndString(dataPtr,526,flkhPriority);
|
||
}
|
||
break;
|
||
|
||
case faeDraw:
|
||
f = **data;
|
||
if (f.popup)
|
||
{
|
||
MenuHandle mh = GetMHandle(PRIOR_HIER_MENU);
|
||
CGrafPtr WinPort = GetMyWindowCGrafPtr (Win);
|
||
EnableItem(mh,0);
|
||
Update1Control(f.popup,MyGetPortVisibleRegion(WinPort));
|
||
#ifdef GRIDLINES
|
||
ControlGridlines(f.popup);
|
||
#endif
|
||
}
|
||
break;
|
||
|
||
case faeRead:
|
||
data = NewZH(FDflkPrior); /* if we can't find a dozen bytes, we're dead */
|
||
if (!data) return(MemError());
|
||
(*action)->data = (void*)data;
|
||
if (dataPtr)
|
||
{
|
||
StringToNum(dataPtr,&f.prior);
|
||
(*data)->prior = f.prior;
|
||
}
|
||
break;
|
||
|
||
case faeFind:
|
||
GetRString(s,PRIOR_STRN+(*data)->prior);
|
||
err = PFindSub(dataPtr,s)!=nil;
|
||
break;
|
||
|
||
case faeWrite:
|
||
NumToString((*data)->prior,s);
|
||
err = FWriteKey(*(short*)dataPtr,flkPriority,s);
|
||
break;
|
||
|
||
case faeButton:
|
||
f = **data;
|
||
item = GetControlValue(f.popup);
|
||
if (item!=f.prior)
|
||
{
|
||
f.prior = item;
|
||
Win->isDirty = CurrentDirty = True;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeClose:
|
||
case faeDispose:
|
||
if (data)
|
||
{
|
||
f = **data;
|
||
if (f.popup) DisposeControl(f.popup);
|
||
f.popup = nil;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faePrint:
|
||
f = **data;
|
||
GetPortPenLocation(GetQDGlobalsThePort(),&penLoc);
|
||
ir.top = penLoc.v-10;
|
||
ir.left = penLoc.h;
|
||
ir.bottom = ir.top +16;
|
||
ir.right = ir.left+16;
|
||
PlotIconID(&ir,atAbsoluteCenter, ttNone,PRIOR_SICN_BASE+f.prior-1);
|
||
break;
|
||
|
||
case faeDo:
|
||
SetPriority(fpb->tocH,fpb->sumNum,NewPrior((*data)->prior,
|
||
(*fpb->tocH)->sums[fpb->sumNum].priority));
|
||
break;
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
typedef struct FDflkForward **FDflkForwardHandle;
|
||
typedef struct FDflkForward
|
||
{
|
||
PETEHandle pte;
|
||
Str255 addresses;
|
||
} FDflkForward;
|
||
|
||
short FAflkForward(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FDflkForwardHandle data = (FDflkForwardHandle)(*action)->data;
|
||
FDflkForward f;
|
||
Rect textR;
|
||
OSErr err = noErr;
|
||
Str255 s;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
if (err=PeteCreate(Win,&f.pte,0,nil)) return(WarnUser(PETE_ERR,err));
|
||
(*PeteExtra(f.pte))->frame = True;
|
||
(*PeteExtra(f.pte))->infinitelyWide = True;
|
||
PeteFontAndSize(f.pte,GetPortTextFont(GetQDGlobalsThePort()),GetPortTextSize(GetQDGlobalsThePort()));
|
||
PCopy(s,(*data)->addresses);
|
||
PeteSetString(s,f.pte);
|
||
(*data)->pte = f.pte;
|
||
PETESetCallback(PETE,f.pte,(void*)FilterChanged,peDocChanged);
|
||
/* fall through */
|
||
case faeResize:
|
||
FASingleRect(r,&textR,ONE_LINE_HI(Win));
|
||
PeteDidResize((*data)->pte,&textR);
|
||
break;
|
||
|
||
case faeNew:
|
||
PeteFocus(Win,(*data)->pte,true);
|
||
break;
|
||
|
||
case faeDraw:
|
||
break;
|
||
|
||
case faeDispose:
|
||
case faeClose:
|
||
FAflkSubject(callType,action,r,dataPtr);
|
||
break;
|
||
|
||
case faeFind:
|
||
err = PeteFindString(dataPtr,0,(*data)->pte)>=0;
|
||
break;
|
||
|
||
case faeCursor:
|
||
if (PtInPETE(*(Point*)r,(*data)->pte))
|
||
*(short*)dataPtr = iBeamCursor;
|
||
else
|
||
*(short*)dataPtr = arrowCursor;
|
||
break;
|
||
|
||
case faeRead:
|
||
data = NewZH(FDflkForward);
|
||
if (!data) return(WarnUser(MEM_ERR,MemError()));
|
||
else
|
||
{
|
||
(*action)->data = (void*)data;
|
||
if (dataPtr) PCopy((*data)->addresses,(UPtr)dataPtr);
|
||
}
|
||
break;
|
||
|
||
case faeWrite:
|
||
PCopy(s,(*data)->addresses);
|
||
if (*s) err = FWriteKey(*(short*)dataPtr,(*action)->action,s);
|
||
break;
|
||
|
||
case faePrint:
|
||
PCopy(s,(*data)->addresses);
|
||
DrawString(s);
|
||
break;
|
||
|
||
case faeClick:
|
||
if (PtInPETE(*(Point*)r,(*data)->pte))
|
||
{
|
||
PeteEditWFocus(Win,(*data)->pte,peeEvent,dataPtr,nil);
|
||
err = True; /* actually, not an error, but... */
|
||
}
|
||
break;
|
||
break;
|
||
|
||
case faeSave:
|
||
PeteSString(s,(*data)->pte);
|
||
PCopy((*data)->addresses,s);
|
||
break;
|
||
|
||
case faeHelp:
|
||
if (MouseInPTE((*data)->pte))
|
||
{
|
||
PeteRect((*data)->pte,r);
|
||
GetIndString(dataPtr,526,((*action)->action==flkForward?flkhForward:flkhRedirect));
|
||
}
|
||
break;
|
||
|
||
case faeDo:
|
||
//Enhanced Filters - the forward filter action is not supported in Light
|
||
//if ((*fpb->tocH)->which==OUT) return(noErr); /* don't do for out */
|
||
if (HasFeature (featureFilterForward)) {
|
||
if (((*fpb->tocH)->sums[fpb->sumNum].opts&OPT_BULK)&&!PrefIsSet(PREF_BOMBS_AWAY)) return(noErr); /* don't do for bulk mail */
|
||
PCopy(s,(*data)->addresses);
|
||
DoFordirectMessage(fpb->tocH,fpb->sumNum,(*action)->action,s,True);
|
||
UseFeature (featureFilterForward);
|
||
}
|
||
break;
|
||
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
short FAflkRedirect(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
return(FAflkForward(callType,action,r,dataPtr));
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
typedef struct FDflkReply **FDflkReplyHandle;
|
||
typedef struct FDflkReply
|
||
{
|
||
Str31 name;
|
||
Rect r;
|
||
ControlHandle popup;
|
||
} FDflkReply;
|
||
short FAflkReply(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
OSErr err = noErr;
|
||
Str255 s;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
FDflkReplyHandle data = (FDflkReplyHandle)(*action)->data;
|
||
short item;
|
||
MenuHandle mh;
|
||
FDflkReply f;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
f = **data;
|
||
f.popup = GetNewControlSmall(FILT_REPLY_POP,GetMyWindowWindowPtr(Win));
|
||
if (!f.popup)
|
||
{
|
||
FAflkReply(faeDispose,action,nil,nil);
|
||
return(MEM_ERR);
|
||
}
|
||
**data = f;
|
||
FAflkReply(faeMouseGoingDown,action,r,dataPtr);
|
||
mh = GetControlPopupMenuHandle(f.popup);
|
||
item = FindItemByName(mh,f.name);
|
||
if (!item)
|
||
{
|
||
item = 1;
|
||
MyGetItem(mh,item,f.name);
|
||
PCopy((*data)->name,f.name);
|
||
}
|
||
MySetCtlValue(f.popup,item);
|
||
EmbedControl(f.popup,ActionGroup);
|
||
// fall-through
|
||
|
||
case faeResize:
|
||
f = **data;
|
||
FAPopupValueFit(r,f.popup);
|
||
ShowControl(f.popup);
|
||
break;
|
||
|
||
case faeClose:
|
||
case faeDispose:
|
||
if (data)
|
||
{
|
||
f = **data;
|
||
if (f.popup) DisposeControl(f.popup);
|
||
f.popup = nil;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeButton:
|
||
f = **data;
|
||
mh = GetMHandle(REPLY_WITH_HIER_MENU);
|
||
item = FindItemByName(mh,f.name);
|
||
if (item!=GetControlValue(f.popup))
|
||
{
|
||
item = GetControlValue(f.popup);
|
||
MyGetItem(mh,item,f.name);
|
||
Win->isDirty = CurrentDirty = True;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeMouseGoingDown:
|
||
{
|
||
Str255 string;
|
||
f = **data;
|
||
if (f.popup && (mh = GetControlPopupMenuHandle(f.popup)))
|
||
{
|
||
MenuHandle otherMH = GetMHandle(NEW_WITH_HIER_MENU);
|
||
short n;
|
||
|
||
if (otherMH)
|
||
{
|
||
TrashMenu(mh,1);
|
||
n = CountMenuItems(otherMH);
|
||
for (item=1;item<=n;item++)
|
||
{
|
||
MyGetItem(otherMH,item,string);
|
||
MyAppendMenu(mh,string);
|
||
}
|
||
SetItemMark(mh,GetControlValue(f.popup),diamondChar);
|
||
EnableItem(mh,0);
|
||
SetControlMaximum(f.popup,CountMenuItems(mh));
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
case faeFind:
|
||
PCopy(s,(*data)->name);
|
||
err = PFindSub(dataPtr,s)!=nil;
|
||
break;
|
||
|
||
case faeRead:
|
||
data = NewZH(FDflkReply);
|
||
if (!data) return(WarnUser(MEM_ERR,MemError()));
|
||
else
|
||
{
|
||
(*action)->data = (void*)data;
|
||
if (dataPtr) PSCopy((*data)->name,(UPtr)dataPtr);
|
||
}
|
||
break;
|
||
|
||
case faeWrite:
|
||
PCopy(s,(*data)->name);
|
||
if (*s) err = FWriteKey(*(short*)dataPtr,(*action)->action,s);
|
||
break;
|
||
|
||
case faePrint:
|
||
PCopy(s,(*data)->name);
|
||
DrawString(s);
|
||
break;
|
||
|
||
case faeDo:
|
||
//We don't have a reply with menu, so we can't do this action in LIGHT
|
||
if (HasFeature (featureFilterReply)) {
|
||
short i;
|
||
MenuHandle mh = GetMHandle(REPLY_WITH_HIER_MENU);
|
||
|
||
//if ((*fpb->tocH)->which==OUT) return(noErr); /* don't do for out */
|
||
if (((*fpb->tocH)->sums[fpb->sumNum].opts&OPT_BULK)&&!PrefIsSet(PREF_BOMBS_AWAY)) return(noErr); /* don't do for bulk mail */
|
||
PCopy(s,*(*action)->data);
|
||
if (mh && (i=FindItemByName(mh,s)))
|
||
{
|
||
UseFeature (featureFilterReply);
|
||
DoReplyClosed(fpb->tocH,fpb->sumNum,False,False,False,True,i,True,True);
|
||
}
|
||
}
|
||
break;
|
||
|
||
}
|
||
return(err);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
short FAflkNotifyApp(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
typedef struct FDflkNUser **FDflkNUserHandle;
|
||
typedef struct FDflkNUser
|
||
{
|
||
long flags;
|
||
ControlHandle user;
|
||
ControlHandle report;
|
||
} FDflkNUser;
|
||
short FAflkNotifyUser(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FDflkNUserHandle data = (FDflkNUserHandle)(*action)->data;
|
||
FDflkNUser f;
|
||
Rect controlR;
|
||
short spacing;
|
||
short val;
|
||
WindowPtr WinWP;
|
||
ControlHandle button = (ControlHandle)dataPtr;
|
||
Str63 s;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
long flag;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
WinWP = GetMyWindowWindowPtr (Win);
|
||
f.report = GetNewControlSmall(DO_FILTER_CNTL,WinWP);
|
||
f.user = GetNewControlSmall(DO_USER_CNTL,WinWP);
|
||
if (!f.user || !f.report)
|
||
{
|
||
FAflkNotifyUser(faeDispose,action,nil,nil);
|
||
return(MEM_ERR);
|
||
}
|
||
f.flags = (*data)->flags;
|
||
**data = f;
|
||
MySetCtlValue(f.user,0!=(f.flags&afbUser));
|
||
MySetCtlValue(f.report,0!=(f.flags&afbReport));
|
||
EmbedControl(f.report,ActionGroup);
|
||
EmbedControl(f.user,ActionGroup);
|
||
/* fall-through */
|
||
case faeResize:
|
||
f = **data;
|
||
ButtonFit(f.user);
|
||
ButtonFit(f.report);
|
||
FAMultRect(r,&controlR,&spacing,ControlHi(f.user),2);
|
||
MoveMyCntl(f.user,controlR.left,controlR.top,RectWi(controlR),0);
|
||
OffsetRect(&controlR,RectWi(controlR)+spacing,0);
|
||
MoveMyCntl(f.report,controlR.left,controlR.top,RectWi(controlR),0);
|
||
ShowControl(f.user);
|
||
ShowControl(f.report);
|
||
break;
|
||
|
||
case faeClose:
|
||
case faeDispose:
|
||
if (data)
|
||
{
|
||
f = **data;
|
||
if (f.user) DisposeControl(f.user);
|
||
if (f.report) DisposeControl(f.report);
|
||
f.user = f.report = nil;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeRead:
|
||
data = NewZH(FDflkNUser); /* if we can't find a dozen bytes, we're dead */
|
||
(*action)->data = (void*)data;
|
||
if (dataPtr) StringToNum(dataPtr,&f.flags);
|
||
else f.flags = afbUser | (PrefIsSet(PREF_REPORT)?afbReport:0);
|
||
(*data)->flags = f.flags;
|
||
break;
|
||
|
||
case faeWrite:
|
||
NumToString((*data)->flags,s);
|
||
return(FWriteKey(*(short*)dataPtr,(*action)->action,s));
|
||
break;
|
||
|
||
case faeButton:
|
||
f = **data;
|
||
val = !GetControlValue(button);
|
||
MySetCtlValue(button,val);
|
||
Win->isDirty = CurrentDirty = True;
|
||
flag = (button==f.user) ? afbUser : afbReport;
|
||
if (val)
|
||
(*data)->flags |= flag;
|
||
else
|
||
(*data)->flags &= ~flag;
|
||
break;
|
||
|
||
case faePrint:
|
||
if ((*data)->flags&afbUser)
|
||
{
|
||
DrawRString(NOTIFY_NORM);
|
||
if ((*data)->flags&afbReport)
|
||
{
|
||
DrawRString(AND_PRINT);
|
||
DrawRString(NOTIFY_REPORT);
|
||
}
|
||
}
|
||
else if ((*data)->flags&afbReport)
|
||
{
|
||
DrawRString(NOTIFY_REPORT);
|
||
}
|
||
break;
|
||
|
||
|
||
case faeDo:
|
||
if (0==((*data)->flags&afbUser))
|
||
fpb->dontUser = True;
|
||
fpb->doReport = 0!=((*data)->flags&afbReport);
|
||
fpb->dontReport = !fpb->doReport;
|
||
break;
|
||
|
||
case faeHelp:
|
||
f = **data;
|
||
if (MouseInControl(f.user))
|
||
{
|
||
GetIndString(dataPtr,526,flkhNUser);
|
||
GetControlBounds(f.user,r);
|
||
}
|
||
if (MouseInControl(f.report))
|
||
{
|
||
GetIndString(dataPtr,526,flkhNReport);
|
||
GetControlBounds(f.report,r);
|
||
}
|
||
break;
|
||
}
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* FAflkServerOpts - set server options
|
||
**********************************************************************/
|
||
typedef struct FDflkSOpt **FDflkSOptHandle;
|
||
typedef struct FDflkSOpt
|
||
{
|
||
long flags;
|
||
ControlHandle fetch;
|
||
ControlHandle trash;
|
||
} FDflkSOpt;
|
||
short FAflkServerOpts(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
FDflkSOptHandle data = (FDflkSOptHandle)(*action)->data;
|
||
FDflkSOpt f;
|
||
Rect controlR;
|
||
short spacing;
|
||
short val;
|
||
WindowPtr WinWP;
|
||
ControlHandle button = (ControlHandle)dataPtr;
|
||
Str63 s;
|
||
FilterPBPtr fpb = (FilterPBPtr)dataPtr;
|
||
long flag;
|
||
long uidHash;
|
||
PersHandle pers;
|
||
Boolean lmos;
|
||
|
||
switch (callType)
|
||
{
|
||
case faeInit:
|
||
WinWP = GetMyWindowWindowPtr (Win);
|
||
f.fetch = GetNewControlSmall(DO_FETCH_CNTL,WinWP);
|
||
f.trash = GetNewControlSmall(DO_TRASH_CNTL,WinWP);
|
||
if (!f.fetch || !f.trash)
|
||
{
|
||
FAflkServerOpts(faeDispose,action,nil,nil);
|
||
return(MEM_ERR);
|
||
}
|
||
f.flags = (*data)->flags;
|
||
**data = f;
|
||
MySetCtlValue(f.trash,0!=(f.flags&afbTrash));
|
||
MySetCtlValue(f.fetch,0!=(f.flags&afbFetch));
|
||
lmos = PrefIsSet(PREF_LMOS);
|
||
if (!lmos&&(f.flags&afbFetch))
|
||
{
|
||
HiliteControl(f.trash,255);
|
||
(*data)->flags |= afbTrash;
|
||
MySetCtlValue(f.trash,1);
|
||
}
|
||
else HiliteControl(f.trash,0);
|
||
EmbedControl(f.trash,ActionGroup);
|
||
EmbedControl(f.fetch,ActionGroup);
|
||
/* fall-through */
|
||
case faeResize:
|
||
f = **data;
|
||
ButtonFit(f.fetch);
|
||
ButtonFit(f.trash);
|
||
FAMultRect(r,&controlR,&spacing,ControlHi(f.fetch),2);
|
||
MoveMyCntl(f.fetch,controlR.left,controlR.top,RectWi(controlR),0);
|
||
OffsetRect(&controlR,RectWi(controlR)+spacing,0);
|
||
MoveMyCntl(f.trash,controlR.left,controlR.top,RectWi(controlR),0);
|
||
ShowControl(f.fetch);
|
||
ShowControl(f.trash);
|
||
break;
|
||
|
||
case faeClose:
|
||
case faeDispose:
|
||
if (data)
|
||
{
|
||
f = **data;
|
||
if (f.trash) DisposeControl(f.trash);
|
||
if (f.fetch) DisposeControl(f.fetch);
|
||
f.fetch = f.trash = nil;
|
||
**data = f;
|
||
}
|
||
break;
|
||
|
||
case faeRead:
|
||
data = NewZH(FDflkSOpt); /* if we can't find a dozen bytes, we're dead */
|
||
(*action)->data = (void*)data;
|
||
if (dataPtr) StringToNum(dataPtr,&f.flags);
|
||
else f.flags = 0;
|
||
(*data)->flags = f.flags;
|
||
break;
|
||
|
||
case faeWrite:
|
||
NumToString((*data)->flags,s);
|
||
return(FWriteKey(*(short*)dataPtr,(*action)->action,s));
|
||
break;
|
||
|
||
case faeButton:
|
||
f = **data;
|
||
val = !GetControlValue(button);
|
||
MySetCtlValue(button,val);
|
||
Win->isDirty = CurrentDirty = True;
|
||
flag = (button==f.trash) ? afbTrash : afbFetch;
|
||
if (val)
|
||
f.flags |= flag;
|
||
else
|
||
f.flags &= ~flag;
|
||
**data = f;
|
||
lmos = PrefIsSet(PREF_LMOS);
|
||
if (!lmos&&(f.flags&afbFetch))
|
||
{
|
||
HiliteControl(f.trash,255);
|
||
(*data)->flags |= afbTrash;
|
||
MySetCtlValue(f.trash,1);
|
||
}
|
||
else HiliteControl(f.trash,0);
|
||
break;
|
||
|
||
case faeHelp:
|
||
f = **data;
|
||
if (MouseInControl(f.fetch))
|
||
{
|
||
GetIndString(dataPtr,526,flkhFetch);
|
||
GetControlBounds(f.fetch,r);
|
||
}
|
||
else if (MouseInControl(f.trash))
|
||
{
|
||
GetIndString(dataPtr,526,flkhDelete);
|
||
GetControlBounds(f.trash,r);
|
||
}
|
||
break;
|
||
|
||
case faeDo:
|
||
//Enhanced Filters - the Server Options filter actions is not supported in Light
|
||
if (HasFeature (featureFilterServerOptions)) {
|
||
UseFeature (featureFilterServerOptions);
|
||
flag = (*data)->flags;
|
||
uidHash = (*fpb->tocH)->sums[fpb->sumNum].uidHash;
|
||
pers = TS_TO_PPERS(fpb->tocH,fpb->sumNum);
|
||
#ifdef IMAP
|
||
if ((*fpb->tocH)->imapTOC)
|
||
{
|
||
// This is an IMAP mailbox.
|
||
|
||
Boolean filteringUnderway = IMAPFilteringUnderway();
|
||
|
||
// Make sure progress is displayed while doing the next bit ...
|
||
if (filteringUnderway) IMAPStopFiltering(false);
|
||
|
||
if (flag&afbFetch)
|
||
{
|
||
// Server Options -> Fetch. Download this message if it's not already present.
|
||
if (!IMAPMessageDownloaded(fpb->tocH, fpb->sumNum) && !IMAPMessageBeingDownloaded(fpb->tocH, fpb->sumNum))
|
||
UIDDownloadMessage(fpb->tocH, uidHash, true, true);
|
||
}
|
||
else if (flag&afbTrash)
|
||
{
|
||
// Server Options -> Delete. Delete this message from the IMAP server.
|
||
IMAPDeleteMessageDuringFiltering(fpb->tocH, pers, (*fpb->tocH)->sums[fpb->sumNum].uidHash);
|
||
}
|
||
|
||
// go back to filtering
|
||
if (filteringUnderway) IMAPStartFiltering(fpb->tocH, true);
|
||
}
|
||
else
|
||
{
|
||
// This is a regular mailbox.
|
||
#endif
|
||
//if (IdIsOnPOPD(PERS_POPD_TYPE(pers),POPD_ID,uidHash)) // because of incremental filtering, we may not know it's on the server when we do this
|
||
{
|
||
Boolean skipped = ((*fpb->tocH)->sums[fpb->sumNum].flags & FLAG_SKIPPED)!=0;
|
||
if ((flag&afbFetch) && skipped) AddIdToPOPD(PERS_POPD_TYPE(pers),FETCH_ID,uidHash,False);
|
||
if (flag&afbTrash)
|
||
{
|
||
AddIdToPOPD(PERS_POPD_TYPE(pers),DELETE_ID,uidHash,False);
|
||
TOCSetDirty(fpb->tocH,true);
|
||
}
|
||
if ((*fpb->tocH)->win) Fix1MessServerArea((*fpb->tocH)->win);
|
||
if ((*fpb->tocH)->sums[fpb->sumNum].messH)
|
||
Fix1MessServerArea((*(*fpb->tocH)->sums[fpb->sumNum].messH)->win);
|
||
}
|
||
#ifdef IMAP
|
||
}
|
||
#endif
|
||
}
|
||
break;
|
||
|
||
case faePrint:
|
||
if ((*data)->flags&afbFetch)
|
||
{
|
||
DrawRString(FETCH_PRINT);
|
||
if ((*data)->flags&afbTrash)
|
||
{
|
||
DrawRString(AND_PRINT);
|
||
DrawRString(DELETE_PRINT);
|
||
}
|
||
}
|
||
else if ((*data)->flags&afbTrash)
|
||
{
|
||
DrawRString(DELETE_PRINT);
|
||
}
|
||
break;
|
||
|
||
}
|
||
return(noErr);
|
||
}
|
||
|
||
/**********************************************************************
|
||
*
|
||
**********************************************************************/
|
||
short FAflkAttachments(FACallEnum callType,FActionHandle action,Rect *r,void *dataPtr)
|
||
{
|
||
return(noErr);
|
||
}
|
||
|
||
|
||
#ifndef SPEECH_ENABLED
|
||
short FAflkSpeak (FACallEnum callType, FActionHandle action, Rect *r, void *dataPtr)
|
||
{
|
||
// return noSynthFound;
|
||
return noErr;
|
||
}
|
||
#else
|
||
typedef struct FDflkSpeak **FDflkSpeakHandle;
|
||
typedef struct FDflkSpeak
|
||
{
|
||
SpeakableParts speak;
|
||
ControlHandle popup;
|
||
ControlHandle sender;
|
||
ControlHandle subject;
|
||
VoiceSpec voice;
|
||
} FDflkSpeak;
|
||
/**********************************************************************
|
||
* FAflkSpeak - speak the sender and/or subject
|
||
**********************************************************************/
|
||
short FAflkSpeak (FACallEnum callType, FActionHandle action, Rect *r, void *dataPtr)
|
||
|
||
{
|
||
FDflkSpeakHandle data;
|
||
FDflkSpeak filter;
|
||
FilterPBPtr fpb;
|
||
VoiceSpec voice;
|
||
WindowPtr WinWP;
|
||
ControlHandle theControl;
|
||
Str255 sample;
|
||
Str63 string;
|
||
Rect controlR;
|
||
UPtr spot;
|
||
OSType creator,
|
||
id;
|
||
long speak;
|
||
short spacing,
|
||
value;
|
||
Rect rCntl;
|
||
SpeakableParts iHaveSpoken;
|
||
|
||
data = (FDflkSpeakHandle) (*action)->data;
|
||
|
||
switch (callType) {
|
||
case faeInit:
|
||
WinWP = GetMyWindowWindowPtr (Win);
|
||
filter = **data;
|
||
filter.speak = (*data)->speak;
|
||
filter.sender = GetNewControlSmall (FILT_SPEAK_SENDER_CNTL, WinWP);
|
||
filter.subject = GetNewControlSmall (FILT_SPEAK_SUBJECT_CNTL, WinWP);
|
||
filter.popup = GetNewVoicePopupSmall (FILT_SPEAK_POPUP_CNTL, WinWP, &filter.voice);
|
||
**data = filter;
|
||
if (!filter.sender || !filter.subject) {
|
||
FAflkSpeak (faeDispose, action, nil, nil);
|
||
return (MEM_ERR);
|
||
}
|
||
MySetCtlValue (filter.sender, (filter.speak & speakSender) != 0);
|
||
MySetCtlValue (filter.subject, (filter.speak & speakSubject) != 0);
|
||
EmbedControl(filter.sender,ActionGroup);
|
||
EmbedControl(filter.subject,ActionGroup);
|
||
EmbedControl(filter.popup,ActionGroup);
|
||
|
||
/* fall-through */
|
||
case faeResize:
|
||
filter = **data;
|
||
ButtonFit (filter.sender);
|
||
ButtonFit (filter.subject);
|
||
FAMultRect (r, &controlR, &spacing, ControlHi (filter.sender), 2);
|
||
if (filter.popup) {
|
||
ButtonFit (filter.popup);
|
||
GetControlBounds(filter.popup,&rCntl);
|
||
MoveMyCntl (filter.popup, controlR.left, controlR.top, MIN (RectWi (rCntl), RectWi (controlR)), 0);
|
||
OffsetRect (&controlR, RectWi (controlR) + spacing, 0);
|
||
controlR.right = controlR.left + RectWi (controlR) / 2;
|
||
}
|
||
MoveMyCntl (filter.sender, controlR.left, controlR.top, RectWi (controlR), 0);
|
||
OffsetRect (&controlR, RectWi (controlR) + spacing, 0);
|
||
MoveMyCntl (filter.subject, controlR.left, controlR.top, RectWi (controlR), 0);
|
||
if (filter.popup)
|
||
ShowControl (filter.popup);
|
||
ShowControl (filter.sender);
|
||
ShowControl (filter.subject);
|
||
break;
|
||
|
||
case faeClose:
|
||
case faeDispose:
|
||
if (data) {
|
||
filter = **data;
|
||
if (filter.sender)
|
||
DisposeControl (filter.sender);
|
||
if (filter.subject)
|
||
DisposeControl (filter.subject);
|
||
if (filter.popup)
|
||
DisposeControl (filter.popup);
|
||
filter.sender = filter.subject = filter.popup = nil;
|
||
**data = filter;
|
||
}
|
||
break;
|
||
|
||
case faeRead:
|
||
// Stored as <speakable parts> <voice creator> <voice id>
|
||
data = NewZH (FDflkSpeak); /* if we can't find a dozen or so bytes, we're dead */
|
||
(*action)->data = (void *) data;
|
||
if (dataPtr) {
|
||
spot = (UPtr) dataPtr + 1;
|
||
if (PToken (dataPtr, string, &spot, " ")) MyStringToNum (string,&speak);
|
||
if (PToken (dataPtr, string, &spot, " ")) MyStringToNum (string,&creator);
|
||
if (PToken (dataPtr, string, &spot, " ")) MyStringToNum (string,&id);
|
||
}
|
||
else {
|
||
speak = speakNothing;
|
||
creator = 0;
|
||
id = 0;
|
||
}
|
||
(*data)->speak = speak;
|
||
if (SpeechAvailable ())
|
||
(void) MakeVoiceSpec (creator, id, &(*data)->voice);
|
||
break;
|
||
|
||
case faeWrite:
|
||
// Written as <speakable parts> <voice creator> <voice id>
|
||
NumToString ((*data)->speak, string);
|
||
PLCat (string, (*data)->voice.creator);
|
||
PLCat (string, (*data)->voice.id);
|
||
return (FWriteKey (*(short *) dataPtr, (*action)->action, string));
|
||
break;
|
||
|
||
case faeButton:
|
||
filter = **data;
|
||
theControl = (ControlHandle) dataPtr;
|
||
value = GetControlValue (theControl);
|
||
|
||
Win->isDirty = CurrentDirty = True;
|
||
if (theControl == filter.popup) {
|
||
GetMenuItemText (GetControlPopupMenuHandle(filter.popup), value, string);
|
||
if (*string && !FindVoiceFromName (string, &voice)) {
|
||
(*data)->voice = voice;
|
||
GetRString (sample, SPEAK_SAMPLE_TEXT);
|
||
(void) Speak (&voice, sample + 1, *sample);
|
||
}
|
||
}
|
||
else {
|
||
MySetCtlValue (theControl, !value);
|
||
speak = (theControl == filter.sender) ? speakSender : speakSubject;
|
||
if (!value)
|
||
(*data)->speak |= speak;
|
||
else
|
||
(*data)->speak &= ~speak;
|
||
}
|
||
break;
|
||
|
||
case faePrint:
|
||
filter = **data;
|
||
if (filter.speak) {
|
||
iHaveSpoken = false;
|
||
if (filter.speak & speakSender) {
|
||
DrawRString (SPEAK_SENDERS_NAME);
|
||
iHaveSpoken = true;
|
||
}
|
||
if (filter.speak & speakSubject) {
|
||
if (iHaveSpoken)
|
||
DrawRString(AND_PRINT);
|
||
DrawRString (SPEAK_SUBJECT);
|
||
iHaveSpoken = true;
|
||
}
|
||
}
|
||
else
|
||
DrawRString (SPEAK_NOTHING);
|
||
DrawRString (SPEAK_USING);
|
||
if (GetVoiceName (&filter.voice, string))
|
||
DrawRString (SPEAK_DEFAULT_VOICE);
|
||
else
|
||
DrawString (string);
|
||
break;
|
||
|
||
case faeDo:
|
||
//Enhanced Filters - the speak filter action is not supported in Light
|
||
if (HasFeature (featureFilterSpeak)) {
|
||
UseFeature (featureFilterSpeak);
|
||
filter = **data;
|
||
fpb = (FilterPBPtr) dataPtr;
|
||
|
||
// Speak now or forever hold your peace
|
||
if (filter.speak)
|
||
(void) SpeakMessage (&filter.voice, fpb->tocH, fpb->sumNum, filter.speak | speakSummary, false);
|
||
}
|
||
break;
|
||
|
||
case faeHelp:
|
||
filter = **data;
|
||
if (MouseInControl (filter.popup)) {
|
||
GetIndString (dataPtr, 526, flkhSpeak);
|
||
GetControlBounds(filter.popup,r);
|
||
}
|
||
else
|
||
if (MouseInControl (filter.sender)) {
|
||
GetIndString (dataPtr, 526, flkhSpeakSender);
|
||
GetControlBounds(filter.sender,r);
|
||
}
|
||
else
|
||
if (MouseInControl (filter.subject))
|
||
{
|
||
GetIndString (dataPtr, 526, flkhSpeakSubject);
|
||
GetControlBounds(filter.subject,r);
|
||
}
|
||
break;
|
||
}
|
||
return (noErr);
|
||
}
|
||
#endif
|
||
|
||
short FAflkAddHistory (FACallEnum callType, FActionHandle action, Rect *r, void *dataPtr)
|
||
|
||
{
|
||
FilterPBPtr fpb;
|
||
|
||
switch (callType) {
|
||
case faeInit:
|
||
case faeResize:
|
||
case faeClose:
|
||
case faeDispose:
|
||
break;
|
||
|
||
case faeWrite:
|
||
return(FWriteBool(*(short*)dataPtr,(*action)->action,True));
|
||
break;
|
||
|
||
case faeButton:
|
||
case faePrint:
|
||
break;
|
||
|
||
case faeDo:
|
||
//Enhanced Filters - Add the sender to the nickname cache
|
||
if (HasFeature (featureFilterAddHistory))
|
||
if (fpb = (FilterPBPtr) dataPtr) {
|
||
TextAddrHandle addresses = nil;
|
||
UseFeature (featureFilterAddHistory);
|
||
if (!GatherBoxAddresses (fpb->tocH, 0, fpb->sumNum, fpb->sumNum, &addresses, false)) {
|
||
CacheRecentNickname (LDRef (addresses));
|
||
UL (addresses);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case faeHelp:
|
||
break;
|
||
}
|
||
return (noErr);
|
||
}
|
||
|
||
#ifdef GRIDLINES
|
||
/************************************************************************
|
||
* ControlGridlines - draw gridlines where a control is
|
||
************************************************************************/
|
||
void ControlGridlines(ControlHandle cntl)
|
||
{
|
||
Rect r;
|
||
|
||
GetControlBounds(cntl,&r);
|
||
MoveTo(r.left-10,r.top); Line(10,0); Line(0,-10);
|
||
MoveTo(r.right+10,r.top); Line(-10,0); Line(0,-10);
|
||
MoveTo(r.left-10,r.bottom); Line(10,0); Line(0,10);
|
||
MoveTo(r.right+10,r.bottom); Line(-10,0); Line(0,10);
|
||
}
|
||
#endif
|
||
|
||
|
||
/**********************************************************************
|
||
* RefreshFiltersWindow - bring it to the front and select the last
|
||
* filter if details is true.
|
||
**********************************************************************/
|
||
void RefreshFiltersWindow(FilterRecord newFilter, Boolean details)
|
||
{
|
||
Point c;
|
||
short n = NFilters - 1;
|
||
|
||
if (FLG && *FLG && Win)
|
||
{
|
||
PushGWorld();
|
||
SetPort_(GetMyWindowCGrafPtr(Win));
|
||
LAddRow(1,n,LHand);
|
||
c.h = 0; c.v = n;
|
||
LSetCell(newFilter.name+1,*newFilter.name,c,LHand);
|
||
PopGWorld();
|
||
}
|
||
|
||
//open the filters window if the user hit "add details"
|
||
if (details)
|
||
{
|
||
OpenFiltersWindow();
|
||
PushGWorld();
|
||
SetPort_(GetMyWindowCGrafPtr(Win));
|
||
FilterSelect(n);
|
||
PopGWorld();
|
||
}
|
||
}
|
||
|
||
#endif
|