1 line
46 KiB
C
Executable File
1 line
46 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 "MakeFilter.h"
|
|
#define FILE_NUM 101
|
|
/* Copyright (c) 1996 by QUALCOMM Incorporated */
|
|
|
|
#pragma segment Makefilter
|
|
|
|
// Real Name Queue Structure - to maintain a list of entire addresses.
|
|
typedef struct RNQ RealNameQ, *RealNameQPtr, **RealNameQHandle;
|
|
struct RNQ
|
|
{
|
|
RealNameQHandle next;
|
|
Str255 realName;
|
|
};
|
|
|
|
// RecPopup structure. Makes it easier to maintain the list and popup in parallel
|
|
typedef struct RecPopup
|
|
{
|
|
MenuHandle menu;
|
|
RealNameQHandle listOfNames;
|
|
} RecPopup, *RecPopupPtr;
|
|
|
|
#define Toggle(b) {if (!b) b = true; else b = false;}
|
|
#define IGNORE_RECIPIENTS (RealNameQHandle)(-1)
|
|
|
|
OSErr DoMakeFilterDialog(Boolean *create, Boolean *details, MakeFilterRecPtr mfRecPtr, RecPopupPtr popupInfo);
|
|
OSErr SetUpFilterFromComp(MyWindowPtr win, MakeFilterRecPtr mfRecPtr, RecPopupPtr popupInfo);
|
|
OSErr SetUpFilterFromMbox(MyWindowPtr win, MakeFilterRecPtr mfRecPtr, RecPopupPtr popupInfo);
|
|
OSErr SetUpFilterFromMess(MyWindowPtr win, MakeFilterRecPtr mfRecPtr, RecPopupPtr popupInfo);
|
|
OSErr GatherAddresses(MessHandle messH, HeaderEnum header, Handle *dest, Boolean wantComments);
|
|
OSErr CreateTheFilter(MakeFilterRecPtr mfRecPtr, Boolean details);
|
|
void SetProperDefaultFolder(MakeFilterRecPtr mfRecPtr, Boolean warnUser);
|
|
OSErr FileSpecByName(FSSpecPtr spec,PStr name);
|
|
OSErr FileSpecByNameInMenu(MenuHandle mh,FSSpecPtr spec,PStr name);
|
|
short FindFileByNameIn1Menu(MenuHandle mh, PStr name);
|
|
UPtr SuggestAMailboxName(MakeFilterRecPtr mfRecPtr, RecPopupPtr popupInfo);
|
|
short AnyRPopup(DialogPtr dlog,short top,short left,MenuHandle mh);
|
|
OSErr ANDAddressesToListOfNames(RecPopupPtr popupInfo, UHandle addresses);
|
|
void FlushRNQ(RecPopupPtr popupInfo);
|
|
OSErr BuildAnyRPopupMenu(RecPopupPtr popupInfo);
|
|
void ChangeMenuForFolderSelect(short menu);
|
|
void TweakSubMenuForFolderSelect(short menu);
|
|
void SetDefaultLocation(DialogPtr dlog, Str255 defaultText);
|
|
|
|
/**********************************************************************
|
|
* DoMakeFilter - do Make Filter.
|
|
**********************************************************************/
|
|
void DoMakeFilter(MyWindowPtr win)
|
|
{
|
|
WindowPtr winWP = GetMyWindowWindowPtr (win);
|
|
OSErr err = noErr;
|
|
Boolean create, details;
|
|
MakeFilterRec mfRec;
|
|
RecPopup anyRPopupMenuInfo;
|
|
|
|
#ifdef IMAP
|
|
// make sure the message is downloaded before doing the make filter ...
|
|
if (GetWindowKind(winWP)==MESS_WIN)
|
|
{
|
|
MessHandle messH;
|
|
|
|
// we're doing a make filter with a message window frontmost.
|
|
if ((messH = Win2MessH(win)) && ((*(*messH)->tocH)->imapTOC))
|
|
{
|
|
LDRef(messH);
|
|
EnsureMsgDownloaded((*messH)->tocH, (*messH)->sumNum, false);
|
|
UL(messH);
|
|
}
|
|
}
|
|
else if (GetWindowKind(winWP)==MBOX_WIN)
|
|
{
|
|
TOCHandle tocH;
|
|
short sumNum;
|
|
|
|
// we're doing a make filter with a mailbox frontmost.
|
|
if ((tocH = (TOCHandle)GetMyWindowPrivateData(win)) && (*tocH)->imapTOC)
|
|
{
|
|
for (sumNum=0; sumNum < (*tocH)->count; sumNum++)
|
|
{
|
|
if ((*tocH)->sums[sumNum].selected)
|
|
EnsureMsgDownloaded(tocH, sumNum, false);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Initialize
|
|
WriteZero(&mfRec,sizeof(MakeFilterRec));
|
|
WriteZero (&anyRPopupMenuInfo,sizeof(RecPopup));
|
|
|
|
//Determine the initial values for the make filter dialog
|
|
if (GetWindowKind(winWP)==COMP_WIN)
|
|
err = SetUpFilterFromComp(win, &mfRec, &anyRPopupMenuInfo);
|
|
else if ((GetWindowKind(winWP)==MBOX_WIN) || (GetWindowKind(winWP)==CBOX_WIN))
|
|
err = SetUpFilterFromMbox(win, &mfRec, &anyRPopupMenuInfo);
|
|
else if (GetWindowKind(winWP)==MESS_WIN)
|
|
err = SetUpFilterFromMess(win, &mfRec, &anyRPopupMenuInfo);
|
|
|
|
if (err == noErr)
|
|
{
|
|
//build the anyR Popup menu from the anyRPopupMenuInfo gathered during initialization
|
|
err = BuildAnyRPopupMenu(&anyRPopupMenuInfo);
|
|
|
|
if (err == noErr)
|
|
{
|
|
//put the anyRPopupMenu into our list of menus, if it's been built.
|
|
if (IsValidMenuHandle(anyRPopupMenuInfo.menu)) InsertMenu(anyRPopupMenuInfo.menu,-1);
|
|
|
|
//Display the make filter dialog and allow the user to make changes
|
|
err = DoMakeFilterDialog(&create, &details, &mfRec, &anyRPopupMenuInfo);
|
|
|
|
//Create the filter.
|
|
if (err == noErr && create) err = CreateTheFilter(&mfRec, details);
|
|
}
|
|
}
|
|
|
|
//Cleanup
|
|
if (IsValidMenuHandle(anyRPopupMenuInfo.menu))
|
|
{
|
|
DeleteMenu(MF_ANYR_POPUP_MENU);
|
|
DisposeMenu(anyRPopupMenuInfo.menu);
|
|
}
|
|
if (anyRPopupMenuInfo.listOfNames) FlushRNQ(&anyRPopupMenuInfo);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* DoMakeFilterDialog - do the Make Filter dialog.
|
|
**********************************************************************/
|
|
OSErr DoMakeFilterDialog(Boolean *create, Boolean *details, MakeFilterRecPtr mfRecPtr, RecPopupPtr popupInfo)
|
|
{
|
|
OSErr err = noErr;
|
|
PETEHandle pte;
|
|
PETEDocInitInfo pdi;
|
|
MyWindowPtr makeFilterDialogWin;
|
|
DialogPtr makeFilterDialog;
|
|
extern ModalFilterUPP DlgFilterUPP;
|
|
short itemHit;
|
|
Boolean done = false;
|
|
ControlHandle transferButton;
|
|
Str255 scratch;
|
|
Boolean userDidTransfer = false;
|
|
Boolean userTouchedNewMailboxName = false; //set to true once the user touches the new mailbox name
|
|
Handle anyRPopup;
|
|
Rect anyRPopupRect;
|
|
short anyRPopupType;
|
|
Str255 noneChosen;
|
|
short textFont,textSize;
|
|
SAVE_PORT;
|
|
|
|
ASSERT(create && details && mfRecPtr);
|
|
|
|
//Initialize various local things
|
|
*create = *details = false;
|
|
GetRString(noneChosen,MF_NONE_CHOSEN);
|
|
|
|
//get the makefilter dialog
|
|
SetDialogFont(SmallSysFontID());
|
|
makeFilterDialogWin = GetNewMyDialog(MAKEFILTER_DLOG,nil,nil,InFront);
|
|
SetDialogFont(0);
|
|
|
|
makeFilterDialog = GetMyWindowDialogPtr (makeFilterDialogWin);
|
|
if (!makeFilterDialog) return(WarnUser(MAKEFILTER_ERR,errMakeFilterOpen));
|
|
|
|
//fix the controls
|
|
SetPort(GetDialogPort(makeFilterDialog));
|
|
ConfigFontSetup(makeFilterDialogWin);
|
|
ReplaceAllControls(makeFilterDialog);
|
|
|
|
//Put the first item in the anyR popup in the anyRText field.
|
|
if (IsValidMenuHandle(popupInfo->menu))
|
|
{
|
|
GetMenuItemText(popupInfo->menu, 1, mfRecPtr->anyRText);
|
|
mfRecPtr->anyRSelection = 1;
|
|
}
|
|
else
|
|
{
|
|
mfRecPtr->anyRText[0] = 0;
|
|
mfRecPtr->anyRSelection = 0;
|
|
}
|
|
|
|
// (jp) For setting up our PETE's.
|
|
DefaultPII (makeFilterDialogWin, false, peNoStyledPaste | peClearAllReturns, &pdi);
|
|
|
|
textFont = GetPortTextFont(GetQDGlobalsThePort());
|
|
textSize = GetPortTextSize(GetQDGlobalsThePort());
|
|
// (jp) I've re-ordered things a bit... Here, order of creation determines tabbing
|
|
// order in the world of user panes
|
|
if (pte = CreatePeteUserPane (GetDItemCtl (makeFilterDialog, MF_FROM_EDIT), peNoStyledPaste | peClearAllReturns, &pdi, true)) {
|
|
PeteFontAndSize (pte,textFont,textSize);
|
|
SetNickScanning (pte, nickHighlight | nickComplete | nickSpaces, kNickScanAllAliasFiles, nil, nil, nil);
|
|
makeFilterDialogWin->pte = pte;
|
|
(void) SetKeyboardFocus (GetDialogWindow(makeFilterDialog), GetDItemCtl (makeFilterDialog, MF_FROM_EDIT), kControlEditTextPart);
|
|
}
|
|
if (pte = CreatePeteUserPane (GetDItemCtl (makeFilterDialog, MF_ANYR_EDIT), peNoStyledPaste | peClearAllReturns, &pdi, true)) {
|
|
PeteFontAndSize (pte,textFont, textSize);
|
|
SetNickScanning (pte, nickHighlight | nickComplete | nickSpaces, kNickScanAllAliasFiles, nil, nil, nil);
|
|
}
|
|
if (pte = CreatePeteUserPane (GetDItemCtl (makeFilterDialog, MF_SUBJECT_EDIT), peNoStyledPaste | peClearAllReturns, &pdi, true))
|
|
PeteFontAndSize (pte,textFont, textSize);
|
|
if (pte = CreatePeteUserPane (GetDItemCtl (makeFilterDialog, MF_TRANSFERNEW_EDIT), peNoStyledPaste | peClearAllReturns, &pdi, true))
|
|
PeteFontAndSize (pte,textFont, textSize);
|
|
|
|
CleanPII(&pdi);
|
|
|
|
// (jp) Place the "Any recipient" text in a PETE user pane
|
|
SetPeteDItemText (makeFilterDialogWin, MF_ANYR_EDIT, mfRecPtr->anyRText);
|
|
|
|
// Set the new mailbox and new mailbox in location text.
|
|
SetProperDefaultFolder(mfRecPtr,true);
|
|
SuggestAMailboxName (mfRecPtr, popupInfo);
|
|
SetDefaultLocation(makeFilterDialog, mfRecPtr->defaultText);
|
|
SetPeteDItemText (makeFilterDialogWin, MF_TRANSFERNEW_EDIT, mfRecPtr->transferToNew.name);
|
|
|
|
// Set the Existing Mailbox button to the same mailbox the messages are in, if they're not in IN or OUT:
|
|
transferButton = GetDItemCtl(makeFilterDialog,MF_TRANSFEREXISTING_BUTTON);
|
|
|
|
// If the message is in the In or Out box, NONE CHOSEN is the default.
|
|
if (mfRecPtr->transferToExisting.name[0] == 0)
|
|
{
|
|
SetDICTitle(makeFilterDialog,MF_TRANSFEREXISTING_BUTTON,noneChosen);
|
|
}
|
|
else //use the same mailbox the message is currently in
|
|
{
|
|
SetDICTitle(makeFilterDialog,MF_TRANSFEREXISTING_BUTTON,MailboxSpecAlias(&(mfRecPtr->transferToExisting),scratch));
|
|
mfRecPtr->action = MF_TRANSFEREXISTING_RADIO;
|
|
userDidTransfer = true; //and pretend the user already did a transfer to existing
|
|
}
|
|
|
|
GetDialogItem(makeFilterDialog,MF_ANYR_POPUP,&anyRPopupType,&anyRPopup,&anyRPopupRect);
|
|
|
|
//Enter the right values into the controls
|
|
SetDItemState(makeFilterDialog,MF_INCOMING_CHECKBOX,mfRecPtr->incoming);
|
|
SetDItemState(makeFilterDialog,MF_OUTGOING_CHECKBOX,mfRecPtr->outgoing);
|
|
SetDItemState(makeFilterDialog,MF_MANUAL_CHECKBOX,mfRecPtr->manual);
|
|
|
|
SetDItemState(makeFilterDialog,MF_SUBJECT_RADIO,mfRecPtr->match==MF_SUBJECT_RADIO);
|
|
SetDItemState(makeFilterDialog,MF_FROM_RADIO,mfRecPtr->match==MF_FROM_RADIO);
|
|
SetDItemState(makeFilterDialog,MF_ANYR_RADIO,mfRecPtr->match==MF_ANYR_RADIO);
|
|
|
|
SetDItemState(makeFilterDialog,MF_DELETE_RADIO,mfRecPtr->action==MF_DELETE_RADIO);
|
|
SetDItemState(makeFilterDialog,MF_TRANSFERNEW_RADIO,mfRecPtr->action==MF_TRANSFERNEW_RADIO);
|
|
SetDItemState(makeFilterDialog,MF_TRANSFEREXISTING_RADIO,mfRecPtr->action==MF_TRANSFEREXISTING_RADIO);
|
|
|
|
SetPeteDItemText (makeFilterDialogWin, MF_SUBJECT_EDIT, mfRecPtr->subjectText);
|
|
SetPeteDItemText (makeFilterDialogWin, MF_FROM_EDIT, mfRecPtr->fromText);
|
|
|
|
//Do makefilter
|
|
SetMyCursor(arrowCursor);
|
|
StartMovableModal(makeFilterDialog);
|
|
ShowWindow(GetDialogWindow(makeFilterDialog));
|
|
HiliteButtonOne(makeFilterDialog);
|
|
|
|
do
|
|
{
|
|
do
|
|
{
|
|
*create = *details = false;
|
|
MovableModalDialog(makeFilterDialog,DlgFilterUPP,&itemHit);
|
|
switch(itemHit)
|
|
{
|
|
case MF_DETAILS_BUTTON:
|
|
*details = true;
|
|
case OK_BUTTON:
|
|
*create = true;
|
|
case MF_CANCEL_BUTTON:
|
|
if (itemHit == MF_CANCEL_BUTTON) err = noErr;
|
|
case CANCEL_ITEM: //handle the cmd-. or esc key
|
|
done = true;
|
|
break;
|
|
|
|
case MF_INCOMING_CHECKBOX:
|
|
Toggle(mfRecPtr->incoming);
|
|
SetDItemState(makeFilterDialog,MF_INCOMING_CHECKBOX,mfRecPtr->incoming);
|
|
break;
|
|
|
|
case MF_OUTGOING_CHECKBOX:
|
|
Toggle(mfRecPtr->outgoing);
|
|
SetDItemState(makeFilterDialog,MF_OUTGOING_CHECKBOX,mfRecPtr->outgoing);
|
|
break;
|
|
|
|
case MF_MANUAL_CHECKBOX:
|
|
Toggle(mfRecPtr->manual);
|
|
SetDItemState(makeFilterDialog,MF_MANUAL_CHECKBOX,mfRecPtr->manual);
|
|
break;
|
|
|
|
case MF_SUBJECT_RADIO:
|
|
case MF_FROM_RADIO:
|
|
case MF_ANYR_RADIO:
|
|
mfRecPtr->match = itemHit;
|
|
|
|
//if the user hasn't modified the suggested mailbox name yet, make a new suggestion.
|
|
if (!userTouchedNewMailboxName)
|
|
SetPeteDItemText (makeFilterDialogWin, MF_TRANSFERNEW_EDIT, SuggestAMailboxName (mfRecPtr, popupInfo));
|
|
|
|
//also update the new folder location
|
|
SetProperDefaultFolder(mfRecPtr,true);
|
|
SetDefaultLocation(makeFilterDialog, mfRecPtr->defaultText);
|
|
break;
|
|
|
|
case MF_DELETE_RADIO:
|
|
case MF_TRANSFERNEW_RADIO:
|
|
case MF_TRANSFEREXISTING_RADIO:
|
|
mfRecPtr->action = itemHit;
|
|
SetDItemState(makeFilterDialog,MF_DELETE_RADIO,mfRecPtr->action==MF_DELETE_RADIO);
|
|
SetDItemState(makeFilterDialog,MF_TRANSFERNEW_RADIO,mfRecPtr->action==MF_TRANSFERNEW_RADIO);
|
|
SetDItemState(makeFilterDialog,MF_TRANSFEREXISTING_RADIO,mfRecPtr->action==MF_TRANSFEREXISTING_RADIO);
|
|
|
|
//if this is the first time the user has hit "Transfer to existing", fall through and select a mbox
|
|
if (itemHit == MF_TRANSFEREXISTING_RADIO && !userDidTransfer);
|
|
else break;
|
|
|
|
case MF_TRANSFEREXISTING_BUTTON:
|
|
if (ChooseMailbox(TRANSFER_MENU,CHOOSE_MBOX_TRANSFER,&(mfRecPtr->transferToExisting)))
|
|
{
|
|
//remember that the user hit transfer.
|
|
userDidTransfer = true;
|
|
|
|
//set the transfer existing button title
|
|
SetDICTitle(makeFilterDialog,MF_TRANSFEREXISTING_BUTTON,MailboxSpecAlias(&(mfRecPtr->transferToExisting),scratch));
|
|
mfRecPtr->action = MF_TRANSFEREXISTING_RADIO;
|
|
}
|
|
else if (HasCommandPeriod()) CommandPeriod = false; //hack to keep MovableModalDialog from seeing ESC if pressed during ChooseMailbox.
|
|
break;
|
|
|
|
case MF_TRANSFERNEW_EDIT:
|
|
//Once the user enters something into this field, stop suggesting names for mailboxes.
|
|
mfRecPtr->action = MF_TRANSFERNEW_RADIO;
|
|
userTouchedNewMailboxName = true; //remember that the user has hit this field.
|
|
break;
|
|
|
|
case MF_ANYR_POPUP:
|
|
if (IsValidMenuHandle(popupInfo->menu))
|
|
{
|
|
mfRecPtr->anyRSelection = AnyRPopup(makeFilterDialog, anyRPopupRect.top, anyRPopupRect.left, popupInfo->menu);
|
|
GetMenuItemText(popupInfo->menu, mfRecPtr->anyRSelection, mfRecPtr->anyRText);
|
|
mfRecPtr->match = MF_ANYR_RADIO;
|
|
|
|
//if the user hasn't modified the suggested mailbox name yet, make a new suggestion.
|
|
if (!userTouchedNewMailboxName)
|
|
SetPeteDItemText (makeFilterDialogWin, MF_TRANSFERNEW_EDIT, SuggestAMailboxName (mfRecPtr, popupInfo));
|
|
|
|
//also update the new folder location
|
|
SetProperDefaultFolder(mfRecPtr,false);
|
|
SetDefaultLocation(makeFilterDialog, mfRecPtr->defaultText);
|
|
}
|
|
break;
|
|
|
|
case MF_SUBJECT_EDIT:
|
|
case MF_FROM_EDIT:
|
|
case MF_ANYR_EDIT:
|
|
if (makeFilterDialogWin->pte == GetPeteDItem (makeFilterDialogWin, MF_SUBJECT_EDIT))
|
|
mfRecPtr->match = MF_SUBJECT_RADIO;
|
|
else
|
|
if (makeFilterDialogWin->pte == GetPeteDItem (makeFilterDialogWin, MF_FROM_EDIT))
|
|
mfRecPtr->match = MF_FROM_RADIO;
|
|
else
|
|
if (makeFilterDialogWin->pte == GetPeteDItem (makeFilterDialogWin, MF_ANYR_EDIT))
|
|
mfRecPtr->match = MF_ANYR_RADIO;
|
|
else
|
|
userTouchedNewMailboxName = true; //remember that the user has hit this field.
|
|
|
|
//suggest a new mailbox name
|
|
if (!userTouchedNewMailboxName)
|
|
SetPeteDItemText (makeFilterDialogWin, MF_TRANSFERNEW_EDIT, SuggestAMailboxName (mfRecPtr, popupInfo));
|
|
|
|
//also update the new folder location
|
|
SetProperDefaultFolder(mfRecPtr,false);
|
|
SetDefaultLocation(makeFilterDialog, mfRecPtr->defaultText);
|
|
break;
|
|
|
|
case MF_DEFAULT:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//set the radio buttons
|
|
SetDItemState(makeFilterDialog,MF_SUBJECT_RADIO,mfRecPtr->match==MF_SUBJECT_RADIO);
|
|
SetDItemState(makeFilterDialog,MF_FROM_RADIO,mfRecPtr->match==MF_FROM_RADIO);
|
|
SetDItemState(makeFilterDialog,MF_ANYR_RADIO,mfRecPtr->match==MF_ANYR_RADIO);
|
|
SetDItemState(makeFilterDialog,MF_DELETE_RADIO,mfRecPtr->action==MF_DELETE_RADIO);
|
|
SetDItemState(makeFilterDialog,MF_TRANSFERNEW_RADIO,mfRecPtr->action==MF_TRANSFERNEW_RADIO);
|
|
SetDItemState(makeFilterDialog,MF_TRANSFEREXISTING_RADIO,mfRecPtr->action==MF_TRANSFEREXISTING_RADIO);
|
|
|
|
} while (!done);
|
|
|
|
//Gather values out of the dialog before putting it away
|
|
if (*create)
|
|
{
|
|
GetPeteDItemText (makeFilterDialogWin, MF_SUBJECT_EDIT, mfRecPtr->subjectText);
|
|
GetPeteDItemText (makeFilterDialogWin, MF_FROM_EDIT, mfRecPtr->fromText);
|
|
GetPeteDItemText (makeFilterDialogWin, MF_ANYR_EDIT, mfRecPtr->anyRText);
|
|
|
|
if (mfRecPtr->action==MF_DELETE_RADIO) GetRString(mfRecPtr->transferToExisting.name, TRASH);
|
|
else if (mfRecPtr->action==MF_TRANSFERNEW_RADIO) GetPeteDItemText (makeFilterDialogWin, MF_TRANSFERNEW_EDIT, mfRecPtr->transferToNew.name);
|
|
|
|
//create the new mailbox, if we ought to.
|
|
if (mfRecPtr->action==MF_TRANSFERNEW_RADIO)
|
|
{
|
|
#ifdef IMAP
|
|
// things are different for IMAP mailboxes
|
|
if (IsIMAPVD(mfRecPtr->transferToNew.vRefNum, mfRecPtr->transferToNew.parID))
|
|
{
|
|
FSSpec spec;
|
|
|
|
//First, see if the mailbox already exists. If it does, just do a transfer to existing.
|
|
if (FSMakeFSSpec(mfRecPtr->transferToNew.vRefNum, mfRecPtr->transferToNew.parID,mfRecPtr->transferToNew.name,&spec)==noErr)
|
|
{
|
|
spec.parID = SpecDirId(&spec);
|
|
|
|
mfRecPtr->action = MF_TRANSFEREXISTING_RADIO;
|
|
mfRecPtr->transferToExisting.vRefNum = spec.vRefNum;
|
|
mfRecPtr->transferToExisting.parID = spec.parID;
|
|
PCopy(mfRecPtr->transferToExisting.name,spec.name);
|
|
}
|
|
else //otherwise, create the new mailbox.
|
|
{
|
|
if (BadMailboxName(&mfRecPtr->transferToNew,false)) done = false; //Creation failed.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
//First, see if the mailbox already exists. If it does, just do a transfer to existing.
|
|
if (!BoxSpecByName(&mfRecPtr->transferToNew,mfRecPtr->transferToNew.name))
|
|
{
|
|
mfRecPtr->action = MF_TRANSFEREXISTING_RADIO;
|
|
mfRecPtr->transferToExisting.vRefNum = mfRecPtr->transferToNew.vRefNum;
|
|
mfRecPtr->transferToExisting.parID = mfRecPtr->transferToNew.parID;
|
|
PCopy(mfRecPtr->transferToExisting.name,mfRecPtr->transferToNew.name);
|
|
}
|
|
else //otherwise, create the new mailbox.
|
|
{
|
|
if (BadMailboxName(&mfRecPtr->transferToNew,false))
|
|
done = false; //bad name. Don't allow the user to continue.
|
|
else
|
|
AddBoxHigh(&mfRecPtr->transferToNew);
|
|
}
|
|
#ifdef IMAP
|
|
}
|
|
#endif
|
|
}
|
|
else if (mfRecPtr->action==MF_TRANSFEREXISTING_RADIO) //grab the name of the mailbox to transfer to.
|
|
{
|
|
GetDICTitle(makeFilterDialog,MF_TRANSFEREXISTING_BUTTON,mfRecPtr->transferToExisting.name);
|
|
|
|
//if the user hasn't selected a mailbox from the menus, continue with no mailbox specified.
|
|
if (StringSame(mfRecPtr->transferToExisting.name,noneChosen)) WriteZero(&(mfRecPtr->transferToExisting),sizeof(FSSpec));
|
|
}
|
|
}
|
|
} while (!done);
|
|
|
|
//Cleanup
|
|
DeleteMenu(MF_ANYR_POPUP_MENU);
|
|
DisposePeteUserPaneItem (makeFilterDialogWin, MF_FROM_EDIT);
|
|
DisposePeteUserPaneItem (makeFilterDialogWin, MF_ANYR_EDIT);
|
|
DisposePeteUserPaneItem (makeFilterDialogWin, MF_SUBJECT_EDIT);
|
|
DisposePeteUserPaneItem (makeFilterDialogWin, MF_TRANSFERNEW_EDIT);
|
|
EndMovableModal(makeFilterDialog);
|
|
DisposDialog_(makeFilterDialog);
|
|
|
|
REST_PORT;
|
|
|
|
return(err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* SetUpFilterFromComp - set up the filter according to a comp window
|
|
**********************************************************************/
|
|
OSErr SetUpFilterFromComp(MyWindowPtr win, MakeFilterRecPtr mfRecPtr, RecPopupPtr popupInfo)
|
|
{
|
|
OSErr err = noErr;
|
|
MessHandle messH = Win2MessH(win);
|
|
short heads[] = {TO_HEAD, CC_HEAD, BCC_HEAD};
|
|
short h;
|
|
UHandle addresses = 0;
|
|
|
|
mfRecPtr->outgoing = true;
|
|
mfRecPtr->manual = true;
|
|
|
|
//Grab the addresses in the to:, cc:, or bcc: headers
|
|
for (h=0;!err && h<sizeof(heads)/sizeof(short);h++)
|
|
err = GatherAddresses(messH, heads[h], &addresses, true);
|
|
|
|
//put together the list of recipients
|
|
err = ANDAddressesToListOfNames(popupInfo, addresses);
|
|
|
|
if (addresses) ZapHandle(addresses);
|
|
|
|
//if there was an error building the recipient list, zero it out, but continue.
|
|
if (err != noErr)
|
|
if (popupInfo->listOfNames && popupInfo->listOfNames != IGNORE_RECIPIENTS)
|
|
FlushRNQ(popupInfo);
|
|
|
|
//Grab the address in the from: header
|
|
err = GatherAddresses(messH, FROM_HEAD, &addresses, false);
|
|
if (err || !addresses || !*addresses || !**addresses || (GetHandleSize(addresses)==0))
|
|
mfRecPtr->fromText[0] = 0;
|
|
else
|
|
{
|
|
Str255 scratch;
|
|
|
|
PCopy(mfRecPtr->fromText, *addresses);
|
|
|
|
//grab the real name of the sender, while we're at it.
|
|
if (addresses) ZapHandle(addresses);
|
|
if (GatherAddresses(messH, FROM_HEAD, &addresses, true)==noErr)
|
|
{
|
|
if (addresses && !*addresses && (GetHandleSize(addresses)!=0))
|
|
{
|
|
PCopy(scratch, *addresses);
|
|
BeautifyFrom(scratch);
|
|
if (!StringSame(mfRecPtr->fromText, scratch)) PCopy(mfRecPtr->fromRealName, scratch);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (addresses) ZapHandle(addresses);
|
|
|
|
//Grab the subject
|
|
SuckHeaderText(messH, mfRecPtr->subjectText, sizeof(mfRecPtr->subjectText), SUBJ_HEAD);
|
|
TrimRe(mfRecPtr->subjectText, false);
|
|
TrimInitialWhite(mfRecPtr->subjectText);
|
|
TrimWhite(mfRecPtr->subjectText);
|
|
|
|
//set the default match and action.
|
|
if (mfRecPtr->fromText[0]) mfRecPtr->match = MF_FROM_RADIO;
|
|
else if (mfRecPtr->anyRText[0]) mfRecPtr->match = MF_ANYR_RADIO;
|
|
else mfRecPtr->match = MF_SUBJECT_RADIO;
|
|
|
|
mfRecPtr->action = MF_TRANSFERNEW_RADIO;
|
|
|
|
return (err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* SetUpFilterFromMess - set up filter from at a message window
|
|
**********************************************************************/
|
|
OSErr SetUpFilterFromMess(MyWindowPtr win, MakeFilterRecPtr mfRecPtr, RecPopupPtr popupInfo)
|
|
{
|
|
OSErr err = noErr;
|
|
MessHandle messH;
|
|
short heads[] = {TO_HEAD, CC_HEAD, BCC_HEAD};
|
|
short h;
|
|
UHandle addresses = 0;
|
|
FSSpec spec;
|
|
|
|
messH = Win2MessH(win);
|
|
|
|
// 11/7/97 - sdorner requested that Incoming and Manual be checked by default for all non-out messages.
|
|
mfRecPtr->incoming = true;
|
|
mfRecPtr->outgoing = false;
|
|
mfRecPtr->manual = true;
|
|
|
|
// Remember what mailbox this message is in, if it's not the in box.
|
|
// Will use this as the transfer to existing choice.
|
|
if (((*(*messH)->tocH)->which!=IN) && ((*(*messH)->tocH)->which!=OUT))
|
|
{
|
|
spec = GetMailboxSpec((*messH)->tocH,-1);
|
|
mfRecPtr->transferToExisting.vRefNum = spec.vRefNum;
|
|
mfRecPtr->transferToExisting.parID = spec.parID;
|
|
PCopy(mfRecPtr->transferToExisting.name,spec.name);
|
|
}
|
|
else
|
|
{
|
|
mfRecPtr->transferToExisting.vRefNum = mfRecPtr->transferToExisting.parID = mfRecPtr->transferToExisting.name[0] = 0;
|
|
}
|
|
|
|
//Grab the addresses in the to:, cc:, or bcc: headers
|
|
for (h=0;!err && h<sizeof(heads)/sizeof(short);h++)
|
|
err = GatherAddresses(messH, heads[h], &addresses, true);
|
|
|
|
//put together the popup menu for the recipients
|
|
ANDAddressesToListOfNames(popupInfo, addresses);
|
|
|
|
if (addresses) ZapHandle(addresses);
|
|
|
|
//if there was an error building the recipient list, zero it out, but continue.
|
|
if (err != noErr)
|
|
if (popupInfo->listOfNames && popupInfo->listOfNames != IGNORE_RECIPIENTS)
|
|
FlushRNQ(popupInfo);
|
|
|
|
//Grab the address in the from: header
|
|
err = GatherAddresses(messH, FROM_HEAD, &addresses, false);
|
|
if (err || !addresses || !*addresses || !**addresses || (GetHandleSize(addresses)==0))
|
|
mfRecPtr->fromText[0] = 0;
|
|
else
|
|
{
|
|
Str255 scratch;
|
|
|
|
PCopy(mfRecPtr->fromText, *addresses);
|
|
|
|
//grab the real name of the sender, while we're at it.
|
|
if (addresses) ZapHandle(addresses);
|
|
if (GatherAddresses(messH, FROM_HEAD, &addresses, true)==noErr)
|
|
{
|
|
if (addresses && !*addresses && (GetHandleSize(addresses)!=0))
|
|
{
|
|
PCopy(scratch, *addresses);
|
|
BeautifyFrom(scratch);
|
|
if (!StringSame(mfRecPtr->fromText, scratch)) PCopy(mfRecPtr->fromRealName, scratch);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (addresses) ZapHandle(addresses);
|
|
|
|
|
|
//Grab the subject
|
|
SuckHeaderText(messH, mfRecPtr->subjectText, sizeof(mfRecPtr->subjectText), SUBJ_HEAD);
|
|
TrimRe(mfRecPtr->subjectText, true);
|
|
TrimInitialWhite(mfRecPtr->subjectText);
|
|
TrimWhite(mfRecPtr->subjectText);
|
|
|
|
//set the default match and action.
|
|
if (mfRecPtr->fromText[0]) mfRecPtr->match = MF_FROM_RADIO;
|
|
else if (mfRecPtr->anyRText[0]) mfRecPtr->match = MF_ANYR_RADIO;
|
|
else mfRecPtr->match = MF_SUBJECT_RADIO;
|
|
|
|
mfRecPtr->action = MF_TRANSFERNEW_RADIO;
|
|
|
|
return (err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* SetUpFilterFromMbox - set up looking at the selected message(s)
|
|
**********************************************************************/
|
|
OSErr SetUpFilterFromMbox(MyWindowPtr win, MakeFilterRecPtr mfRecPtr, RecPopupPtr popupInfo)
|
|
{
|
|
OSErr err = noErr;
|
|
TOCHandle tocH = (TOCHandle)GetMyWindowPrivateData(win);
|
|
MyWindowPtr messWin;
|
|
short sumNum;
|
|
short from = 0;
|
|
short to = (*tocH)->count-1;
|
|
MakeFilterRec mfRec;
|
|
Boolean sawDifferentSubject = false;
|
|
Boolean sawDifferentFrom = false;
|
|
Boolean sawDifferentAnyR = false;
|
|
|
|
//Initialize the make filter record
|
|
WriteZero(&mfRec,sizeof(MakeFilterRec));
|
|
|
|
for (sumNum=from;!err && sumNum<=to;sumNum++)
|
|
{
|
|
MiniEvents(); if (CommandPeriod) break;
|
|
if ((*tocH)->sums[sumNum].selected)
|
|
{
|
|
//Fill in the mfRec for each selected message, and save matching stuff in the mfRec we were passed.
|
|
if (messWin = GetAMessage(tocH,sumNum,nil,nil,False))
|
|
{
|
|
WindowPtr messWinWP = GetMyWindowWindowPtr (messWin);
|
|
if ((**tocH).which==OUT) SetUpFilterFromComp(messWin, &mfRec, popupInfo);
|
|
else SetUpFilterFromMess(messWin, &mfRec, popupInfo);
|
|
|
|
//transfer pertinent information from this message to the mfRec we're building.
|
|
|
|
//subject:
|
|
if ((mfRecPtr->subjectText[0] == 0) && !sawDifferentSubject)//nothing in the from field yet.
|
|
PCopy(mfRecPtr->subjectText, mfRec.subjectText); //copy the from we see.
|
|
else if (!sawDifferentSubject) //something's already in the from field, but it's matched so far.
|
|
if (!StringSame(mfRecPtr->subjectText, mfRec.subjectText))
|
|
{
|
|
sawDifferentSubject = true;
|
|
mfRecPtr->subjectText[0] = 0;
|
|
}
|
|
|
|
//from:
|
|
if ((mfRecPtr->fromText[0] == 0) && !sawDifferentFrom) //nothing in the from field yet.
|
|
{
|
|
PCopy(mfRecPtr->fromText, mfRec.fromText); //copy the from we see.
|
|
}
|
|
else if (!sawDifferentFrom) //something's already in the from field, but it's matched so far.
|
|
{
|
|
//The from field always contains the short address.
|
|
if (!StringSame(mfRecPtr->fromText, mfRec.fromText))
|
|
{
|
|
sawDifferentFrom = true;
|
|
mfRecPtr->fromText[0] = 0;
|
|
}
|
|
}
|
|
|
|
//copy over the from real name if we don't yet have one.
|
|
if (!mfRecPtr->fromRealName[0] && mfRec.fromRealName[0]) PCopy(mfRecPtr->fromRealName,mfRec.fromRealName);
|
|
|
|
//copy data about enclosing mailbox if we haven't yet.
|
|
if ((mfRecPtr->transferToExisting.name[0] == 0) && ((**tocH).which!=IN) && ((**tocH).which!=OUT))
|
|
{
|
|
mfRecPtr->transferToExisting.vRefNum = mfRec.transferToExisting.vRefNum;
|
|
mfRecPtr->transferToExisting.parID = mfRec.transferToExisting.parID;
|
|
PCopy(mfRecPtr->transferToExisting.name,mfRec.transferToExisting.name);
|
|
}
|
|
|
|
//Cleanup
|
|
if (!IsWindowVisible (messWinWP)) CloseMyWindow(messWinWP);
|
|
}
|
|
else return (err=WarnUser(MF_SCAN_ERROR,errScanningMbox));
|
|
}
|
|
}
|
|
|
|
//The message we're building a filter for will all be in the same mailbox.
|
|
mfRecPtr->incoming = mfRec.incoming;
|
|
mfRecPtr->outgoing = mfRec.outgoing;
|
|
mfRecPtr->manual = mfRec.manual;
|
|
|
|
//Depending on what field has data in it, choose the default match condition.
|
|
mfRecPtr->action = mfRecPtr->transferToExisting.name[0] == 0 ? MF_TRANSFERNEW_RADIO : MF_TRANSFEREXISTING_RADIO;
|
|
|
|
if (mfRecPtr->fromText[0]) mfRecPtr->match = MF_FROM_RADIO;
|
|
else if (popupInfo->listOfNames && (popupInfo->listOfNames != IGNORE_RECIPIENTS)) mfRecPtr->match = MF_ANYR_RADIO;
|
|
else if (mfRecPtr->subjectText[0]) mfRecPtr->match = MF_SUBJECT_RADIO;
|
|
else err = WarnUser(MF_NO_COMMON_ERROR,errNoCommonElements);
|
|
|
|
return (err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* GatherAddresses - Grab the addresses out of a header.
|
|
**********************************************************************/
|
|
OSErr GatherAddresses(MessHandle messH, HeaderEnum header, Handle *dest, Boolean wantComments)
|
|
{
|
|
OSErr err=noErr;
|
|
Uhandle text=nil;
|
|
Handle littlelist;
|
|
HeadSpec hs;
|
|
|
|
if (!*dest) *dest = NuHandle(0);
|
|
if (!*dest) err = MemError();
|
|
|
|
if (!err && CompHeadFind(messH,header,&hs))
|
|
{
|
|
if (!(err=CompHeadGetText(TheBody,&hs,&text)))
|
|
{
|
|
err=SuckAddresses(&littlelist,text,wantComments,false,false,nil);
|
|
if (littlelist)
|
|
{
|
|
if (**littlelist)
|
|
{
|
|
long size=GetHandleSize_(*dest);
|
|
if (size) SetHandleBig_(*dest,size-1); /* strip final terminator */
|
|
LDRef(littlelist);
|
|
err=HandAndHand(littlelist,*dest);
|
|
UL(littlelist);
|
|
}
|
|
ZapHandle(littlelist);
|
|
ZapHandle(text);
|
|
}
|
|
}
|
|
}
|
|
return (err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* SetProperDefaultFolder - Set the mfRecPtr to point at the right
|
|
* default folder for new mailboxes.
|
|
**********************************************************************/
|
|
void SetProperDefaultFolder(MakeFilterRecPtr mfRecPtr, Boolean warnUser)
|
|
{
|
|
short defaultFolder;
|
|
|
|
if (mfRecPtr->match==MF_SUBJECT_RADIO) defaultFolder = PREF_MF_SUBJECT_DEFAULT_FOLDER;
|
|
else if (mfRecPtr->match==MF_FROM_RADIO) defaultFolder = PREF_MF_FROM_DEFAULT_FOLDER;
|
|
else if (mfRecPtr->match==MF_ANYR_RADIO) defaultFolder = PREF_MF_ANYR_DEFAULT_FOLDER;
|
|
|
|
GetPref(mfRecPtr->defaultText, defaultFolder);
|
|
if (!mfRecPtr->defaultText[0]) //no default folder specified. Use mail folder.
|
|
{
|
|
mfRecPtr->transferToNew.vRefNum = MailRoot.vRef;
|
|
mfRecPtr->transferToNew.parID = MailRoot.dirId;
|
|
GetRString(mfRecPtr->defaultText,MAIL_FOLDER_NAME);
|
|
}
|
|
else
|
|
{
|
|
//see if the default folder exists.
|
|
if (!FileSpecByName(&mfRecPtr->transferToNew, mfRecPtr->defaultText));
|
|
else //it doesn't. Set the default folder to the Mail Folder.
|
|
{
|
|
// warn the user the default folder doesn't exist, unless we were told to shut up about it.
|
|
if (warnUser) WarnUser(MF_DEFAULT_FOLDER_NOT_FOUND,0);
|
|
mfRecPtr->transferToNew.vRefNum = MailRoot.vRef;
|
|
mfRecPtr->transferToNew.parID = MailRoot.dirId;
|
|
GetRString(mfRecPtr->defaultText,MAIL_FOLDER_NAME);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**********************************************************************
|
|
* CreateTheFilter - Part of MakeFilter:
|
|
* actually create the filter, and display the filters window if the
|
|
* user hit "Add Details".
|
|
**********************************************************************/
|
|
OSErr CreateTheFilter(MakeFilterRecPtr mfRecPtr, Boolean details)
|
|
{
|
|
OSErr err = noErr;
|
|
Str31 scratch,head;
|
|
Str255 name;
|
|
Str255 s;
|
|
FActionHandle fa;
|
|
FilterRecord fr;
|
|
FActionProc *fap;
|
|
Boolean folder = false;
|
|
|
|
if (!Filters || !*Filters) err = RegenerateFilters();
|
|
if (err == noErr)
|
|
{
|
|
FRInit(&fr);
|
|
fr.fu.id = FilterNewId();
|
|
fr.fu.lastMatch = GMTDateTime();
|
|
|
|
// Set when this new filter is applied.
|
|
fr.incoming = mfRecPtr->incoming;
|
|
fr.outgoing = mfRecPtr->outgoing;
|
|
fr.manual = mfRecPtr->manual;
|
|
|
|
// Set up the match terms of the new filter.
|
|
fr.terms[0].verb = mbmContains;
|
|
if (mfRecPtr->match==MF_SUBJECT_RADIO)
|
|
{
|
|
GetRString(fr.terms[0].header,HEADER_LABEL_STRN+SUBJ_HEAD);
|
|
PCopyTrim(fr.terms[0].value, mfRecPtr->subjectText, sizeof(fr.terms[0].value));
|
|
}
|
|
else if (mfRecPtr->match==MF_FROM_RADIO)
|
|
{
|
|
GetRString(fr.terms[0].header,HEADER_LABEL_STRN+FROM_HEAD);
|
|
PCopyTrim(fr.terms[0].value, mfRecPtr->fromText, sizeof(fr.terms[0].value));
|
|
}
|
|
else if (mfRecPtr->match==MF_ANYR_RADIO)
|
|
{
|
|
GetRString(fr.terms[0].header, FILTER_ADDRESSEE);
|
|
PCopyTrim(fr.terms[0].value, mfRecPtr->anyRText, sizeof(fr.terms[0].value));
|
|
}
|
|
|
|
// set up the action
|
|
if (!(fa=NewZH(FAction)))
|
|
{
|
|
err = MemError();
|
|
}
|
|
else
|
|
{
|
|
(*fa)->action = flkTransfer;
|
|
fap = FATable(flkTransfer);
|
|
|
|
if (mfRecPtr->action == MF_TRANSFERNEW_RADIO)
|
|
{
|
|
if (Box2Path(&(mfRecPtr->transferToNew),s)==noErr) PCopy(mfRecPtr->transferToNew.name,s);
|
|
err = (*fap)(faeRead,fa,nil,mfRecPtr->transferToNew.name);
|
|
}
|
|
else
|
|
{
|
|
if (Box2Path(&(mfRecPtr->transferToExisting),s)==noErr) PCopy(mfRecPtr->transferToExisting.name,s);
|
|
err = (*fap)(faeRead,fa,nil,mfRecPtr->transferToExisting.name);
|
|
}
|
|
|
|
if (!err)
|
|
{
|
|
LL_Queue(fr.actions,fa,(FActionHandle));
|
|
fa = nil;
|
|
|
|
// build the name
|
|
if (*fr.terms[0].header || *fr.terms[0].value)
|
|
{
|
|
PSCopy(head,fr.terms[0].header);
|
|
if (head[*head]==':') --*head;
|
|
utl_PlugParams(GetRString(scratch,FILTER_NAME),name,
|
|
head,fr.terms[0].value,nil,nil);
|
|
PSCopy(fr.name,name);
|
|
}
|
|
else GetRString(fr.name,UNTITLED);
|
|
|
|
Transmogrify(fr.terms[0].header,FiltMetaEnglishStrn,fr.terms[0].header,FiltMetaLocalStrn);
|
|
|
|
/*
|
|
* save the actions
|
|
*/
|
|
|
|
// study it
|
|
StudyFilter(&fr);
|
|
|
|
// save it
|
|
if (!(err = AppendFilter(&fr, Filters)))
|
|
if (!(err = SaveFilters()))
|
|
RefreshFiltersWindow(fr, details);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(err?WarnUser(MF_SAVE_FILTER_ERROR,errCantSaveFilter):noErr);
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* FileSpecByName - find a file/folder in the Mail Folder.
|
|
************************************************************************/
|
|
OSErr FileSpecByName(FSSpecPtr spec,PStr name)
|
|
{
|
|
MenuHandle mh = GetMHandle(MAILBOX_MENU);
|
|
OSErr err = noErr;
|
|
|
|
//if this is the mail folder, no point in searching the mailbox tree.
|
|
if (EqualStrRes(name, MAIL_FOLDER_NAME))
|
|
{
|
|
GetRString(spec->name, MAIL_FOLDER_NAME);
|
|
spec->vRefNum = MailRoot.vRef;
|
|
spec->parID = MailRoot.dirId;
|
|
}
|
|
else
|
|
{
|
|
err = FileSpecByNameInMenu(mh,spec,name);
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* FileSpecByNameInMenu - search a given menu for a file
|
|
**********************************************************************/
|
|
OSErr FileSpecByNameInMenu(MenuHandle mh,FSSpecPtr spec,PStr name)
|
|
{
|
|
short item;
|
|
short n;
|
|
short sub;
|
|
MenuHandle subMH;
|
|
OSErr err = fnfErr;
|
|
|
|
if (item=FindFileByNameIn1Menu(mh,name))
|
|
{
|
|
//If this item has a submenu, return the vRefNum and parID of the submenu's folder
|
|
if (HasSubmenu(mh,item))
|
|
{
|
|
MenuID2VD(SubmenuId(mh,item),&spec->vRefNum,&spec->parID);
|
|
}
|
|
else //otherwise, return the vRefNum and parID of the folder it lives in
|
|
{
|
|
MenuID2VD(GetMenuID(mh),&spec->vRefNum,&spec->parID);
|
|
}
|
|
return(noErr);
|
|
}
|
|
|
|
n = CountMenuItems(mh);
|
|
for (item=1;item<=n;item++)
|
|
if (HasSubmenu(mh,item))
|
|
{
|
|
sub = SubmenuId(mh,item);
|
|
if (subMH=GetMHandle(sub))
|
|
{
|
|
err = FileSpecByNameInMenu(subMH,spec,name);
|
|
if (!err) break;
|
|
if (err!=fnfErr) break;
|
|
}
|
|
}
|
|
return(err);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* FindFileByNameIn1Menu - find a file in a single menu
|
|
**********************************************************************/
|
|
short FindFileByNameIn1Menu(MenuHandle mh, PStr name)
|
|
{
|
|
Str63 itemTitle;
|
|
short i;
|
|
short n = CountMenuItems(mh);
|
|
short res;
|
|
Boolean root = GetMenuID(mh) == MAILBOX_MENU;
|
|
|
|
for (i=(root?1:3);i<=n;i++)
|
|
if (!root || i!=MAILBOX_BAR1_ITEM && i!=MAILBOX_NEW_ITEM && i!=MAILBOX_OTHER_ITEM)
|
|
{
|
|
if (root) MailboxMenuFile(MAILBOX_MENU,i,itemTitle);
|
|
else MyGetItem(mh,i,itemTitle);
|
|
res = StringComp(name,itemTitle);
|
|
if (!res) return(i); // found it!
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/************************************************************************
|
|
* ChooseMailboxFolder - get the the name of a folder from the mbox menus
|
|
************************************************************************/
|
|
Boolean ChooseMailboxFolder(short menu, short msg, UPtr name)
|
|
{
|
|
short mId;
|
|
WindowPtr theWindow;
|
|
EventRecord event;
|
|
MyWindowPtr dgPtrWin;
|
|
DialogPtr dgPtr;
|
|
Boolean rslt = False;
|
|
Str255 msgStr;
|
|
MenuHandle mh;
|
|
|
|
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);
|
|
ChangeMenuForFolderSelect(menu);
|
|
DrawMenuBar();
|
|
ParamText(GetRString(msgStr,msg),"","","");
|
|
dgPtrWin = GetNewMyDialog (XFER_MENU_DLOG,nil,nil,InFront);
|
|
dgPtr = GetMyWindowDialogPtr (dgPtrWin);
|
|
// dgPtr = GetNewDialog(XFER_MENU_DLOG,nil,InFront);
|
|
DrawDialog(dgPtr);
|
|
SetMyCursor(arrowCursor); SFWTC = True;
|
|
|
|
/*
|
|
* now, let the user choose something:
|
|
*/
|
|
for (;;)
|
|
{
|
|
if (WNE(mDownMask|keyDownMask|updateMask,&event,REAL_BIG))
|
|
{
|
|
if (event.what==updateEvt) MiniMainLoop(&event);
|
|
else break;
|
|
}
|
|
}
|
|
if (event.what==mouseDown)
|
|
{
|
|
if (inMenuBar == FindWindow_(event.where,&theWindow))
|
|
{
|
|
long mSelect = MenuSelect(event.where);
|
|
short mnu, itm;
|
|
|
|
if (!mSelect) mSelect = MenuChoice();
|
|
|
|
mnu = (mSelect>>16)&0xffff;
|
|
itm = mSelect & 0xffff;
|
|
if (mnu==menu || IsMailboxSubmenu(mnu))
|
|
{
|
|
rslt = false;
|
|
mh = GetMHandle(mnu);
|
|
if (mnu == menu && itm == MAILBOX_NEW_ITEM)
|
|
{
|
|
GetRString(name, MAIL_FOLDER_NAME);
|
|
rslt = true;
|
|
}
|
|
else if (itm && !HasSubmenu(mh,itm) && IsEnabled(mnu,itm))
|
|
{
|
|
GetMenuTitle(mh,name);
|
|
rslt = true;
|
|
}
|
|
}
|
|
HiliteMenu(0);
|
|
}
|
|
}
|
|
DisposDialog_(dgPtr);
|
|
BuildBoxMenus();
|
|
MBTickle(nil,nil);
|
|
EnableMenus(FrontWindow_(),False);
|
|
PopGWorld();
|
|
return(rslt);
|
|
}
|
|
|
|
/************************************************************************
|
|
* SuggestAMailboxName - suggest a mailbox name.
|
|
*
|
|
* If the subject is being matched, suggest the first 31 chars of the subject.
|
|
* if the from field is matched, suggest the real name of the sender, if there is one.
|
|
* If anyR is being matched, suggest the recipient in the anyR field.
|
|
************************************************************************/
|
|
UPtr SuggestAMailboxName(MakeFilterRecPtr mfRecPtr, RecPopupPtr popupInfo)
|
|
{
|
|
UPtr spot;
|
|
Str255 suggestedName;
|
|
|
|
suggestedName[0] = 0;
|
|
|
|
//the suggested name will be from the Subject, From, or AnyR fields.
|
|
if (mfRecPtr->match==MF_SUBJECT_RADIO)
|
|
{
|
|
PCopy(suggestedName, mfRecPtr->subjectText);
|
|
}
|
|
else if (mfRecPtr->match==MF_FROM_RADIO)
|
|
{
|
|
if (mfRecPtr->fromRealName[0]) PCopy(suggestedName, mfRecPtr->fromRealName); //use the real name, if available
|
|
else PCopy(suggestedName, mfRecPtr->fromText);
|
|
}
|
|
else if (mfRecPtr->match==MF_ANYR_RADIO)
|
|
{
|
|
short count;
|
|
RealNameQHandle rnq = popupInfo->listOfNames;
|
|
|
|
//grab the real name from the list of names described by the popup menu.
|
|
if (rnq && rnq != IGNORE_RECIPIENTS && (*rnq)->realName)
|
|
{
|
|
for (count = 0; (count < (mfRecPtr->anyRSelection - 1)) && rnq; count++) rnq = (*rnq)->next;
|
|
if (rnq)
|
|
{
|
|
PCopy(suggestedName, (*rnq)->realName);
|
|
BeautifyFrom(suggestedName);
|
|
}
|
|
else GetRString(suggestedName,UNTITLED_MAILBOX);
|
|
}
|
|
}
|
|
|
|
//Clean up the suggested name.
|
|
TrimRe(suggestedName, false);
|
|
TrimInitialWhite(suggestedName);
|
|
TrimWhite(suggestedName);;
|
|
for (spot=suggestedName+1;spot<=suggestedName+suggestedName[0];spot++)
|
|
if (*spot==':') *spot = '-';
|
|
|
|
//And suggest the first 27 characters of the cleaned up name.
|
|
PCopyTrim(mfRecPtr->transferToNew.name, suggestedName, 27);
|
|
|
|
return(mfRecPtr->transferToNew.name);
|
|
}
|
|
|
|
/************************************************************************
|
|
* AnyRPopup - pop up the menu for choosing a recipient. Return the
|
|
* item number of what's chosen.
|
|
************************************************************************/
|
|
short AnyRPopup(DialogPtr dlog, short top, short left, MenuHandle mh)
|
|
{
|
|
MyWindowPtr dlogWin = GetDialogMyWindowPtr (dlog);
|
|
Str255 value;
|
|
short item;
|
|
long sel;
|
|
Point pt;
|
|
GrafPtr origPort;
|
|
|
|
pt.h = left; pt.v = top;
|
|
|
|
GetPort(&origPort);
|
|
SetPort(GetDialogPort(dlog));
|
|
LocalToGlobal(&pt);
|
|
SetPort(origPort);
|
|
|
|
value[0]=0;
|
|
GetPeteDItemText (dlogWin, MF_ANYR_EDIT, value);
|
|
|
|
if (*value && !(item=FindItemByName(mh,value)))
|
|
{
|
|
if (!(item=FindItemByName(mh,"\p-")))
|
|
{
|
|
AppendMenu(mh,"\p-");
|
|
DisableItem(mh,CountMenuItems(mh));
|
|
MyAppendMenu(mh,value);
|
|
}
|
|
else SetMenuItemText(mh, CountMenuItems(mh), value);
|
|
|
|
item = CountMenuItems(mh);
|
|
}
|
|
else if (*value==0) item = 0;
|
|
sel = AFPopUpMenuSelect(mh,pt.v,pt.h,item);
|
|
if (sel&0xffff && sel&0xff && (sel&0xff)!=item)
|
|
{
|
|
MyGetItem(mh,item=sel&0xff,value);
|
|
//make sure the anyR text field gets set to the actual address, not the real name.
|
|
|
|
SetPeteDItemText (dlogWin, MF_ANYR_EDIT, value);
|
|
}
|
|
|
|
return(item);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* ANDAddressesToListOfNames - add the addresses from handle to the
|
|
* list of names we're maintaining. We'll turn it into a popup
|
|
* menu later, and use the list for suggesting names.
|
|
**********************************************************************/
|
|
OSErr ANDAddressesToListOfNames(RecPopupPtr popupInfo, UHandle addresses)
|
|
{
|
|
OSErr err = noErr;
|
|
unsigned char* scan = 0;
|
|
long size = GetHandleSize(addresses);
|
|
Str255 scratch, temp;
|
|
RealNameQHandle nextRNQ, rnq = popupInfo->listOfNames;
|
|
|
|
//if there are no addresses, kill the menu. There are no common addresses.
|
|
if (!addresses || !*addresses || !**addresses) err = errNoCommonAddresses;
|
|
else
|
|
{
|
|
HLock(addresses);
|
|
if (rnq==0) //nothing in the list yet. Add all the addresses.
|
|
{
|
|
scan = *addresses;
|
|
while (scan < (*addresses + size))
|
|
{
|
|
if (rnq = NuHandleClear(sizeof(RealNameQ)))
|
|
{
|
|
PCopy((*rnq)->realName, scan);
|
|
LL_Queue(popupInfo->listOfNames,rnq,(RealNameQHandle));
|
|
}
|
|
else
|
|
{
|
|
err = MemError();
|
|
break;
|
|
}
|
|
scan = scan + *scan + 1;
|
|
while (*scan == 0 && (scan < (*addresses + size))) scan++;
|
|
}
|
|
}
|
|
else // there are some address in the list already. Delete the ones that aren't in addresses.
|
|
{
|
|
rnq = popupInfo->listOfNames;
|
|
while (rnq && rnq != IGNORE_RECIPIENTS)
|
|
{
|
|
// compare the short addresses.
|
|
LDRef(rnq);
|
|
ShortAddr(temp, (*rnq)->realName);
|
|
UL(rnq);
|
|
|
|
nextRNQ = (*rnq)->next;
|
|
|
|
scan = *addresses;
|
|
while (scan < (*addresses + size))
|
|
{
|
|
// the addresses are the same if the short addresses turn out to be equal
|
|
ShortAddr(scratch, scan);
|
|
// if the short address are equivalent, save the longer of the two addresses to the list.
|
|
if (StringSame(temp, scratch))
|
|
{
|
|
if (*scan > *((*rnq)->realName))
|
|
PCopy((*rnq)->realName, scan);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
scan = scan + *scan + 1;
|
|
while (*scan == 0 && (scan < (*addresses + size))) scan++;
|
|
}
|
|
}
|
|
|
|
if (scan >= (*addresses + size)) // reached the end of the address handle, and didn't see it in our list?
|
|
{
|
|
LL_Remove(popupInfo->listOfNames,rnq,(RealNameQHandle));
|
|
if (!popupInfo->listOfNames) popupInfo->listOfNames = IGNORE_RECIPIENTS; //give up.
|
|
}
|
|
//check the next item in the real name list.
|
|
rnq = nextRNQ;
|
|
}
|
|
}
|
|
|
|
HUnlock(addresses);
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* BuildAnyRPopupMenu - build the Any Recipient popup.
|
|
**********************************************************************/
|
|
OSErr BuildAnyRPopupMenu(RecPopupPtr popupInfo)
|
|
{
|
|
OSErr err = noErr;
|
|
RealNameQHandle rnq = popupInfo->listOfNames;
|
|
Str255 scratch;
|
|
|
|
if (rnq && rnq != IGNORE_RECIPIENTS)
|
|
{
|
|
popupInfo->menu = NewMenu(MF_ANYR_POPUP_MENU, "");
|
|
if (popupInfo->menu)
|
|
{
|
|
while (rnq)
|
|
{
|
|
LDRef(rnq);
|
|
ShortAddr(scratch, (*rnq)->realName);
|
|
UL(rnq);
|
|
AppendMenu(popupInfo->menu, scratch);
|
|
rnq = (*rnq)->next;
|
|
}
|
|
}
|
|
}
|
|
return (err);
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* FlushRNQ - flush the real name queue.
|
|
**********************************************************************/
|
|
void FlushRNQ(RecPopupPtr popupInfo)
|
|
{
|
|
RealNameQHandle rnq, nextRNQ;
|
|
|
|
if (rnq = popupInfo->listOfNames)
|
|
{
|
|
if (rnq == IGNORE_RECIPIENTS) rnq = 0;
|
|
|
|
while (rnq)
|
|
{
|
|
nextRNQ = (*rnq)->next;
|
|
ZapHandle(rnq);
|
|
rnq = nextRNQ;
|
|
}
|
|
}
|
|
popupInfo->listOfNames = 0;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* ChangeMenuForFolderSelect - change New... to This Mailbox, and
|
|
* disable everything else . BuildBoxMenus() reverses this process
|
|
**********************************************************************/
|
|
void ChangeMenuForFolderSelect(short menu)
|
|
{
|
|
short menuCount, item, subID;
|
|
MenuHandle mh = GetMHandle(menu);
|
|
|
|
//This only works on the mailbox and transfer menus
|
|
if (mh && (menu == MAILBOX_MENU || menu == TRANSFER_MENU))
|
|
{
|
|
EnableIf(mh,MAILBOX_IN_ITEM,false);
|
|
EnableIf(mh,MAILBOX_OUT_ITEM,false);
|
|
EnableIf(mh,MAILBOX_JUNK_ITEM,false);
|
|
EnableIf(mh,MAILBOX_TRASH_ITEM,false);
|
|
|
|
SetItemR(mh, MAILBOX_NEW_ITEM, CHOOSE_MBOX_THIS_FOLDER); //replace the New... item with "This Mailbox"
|
|
SetMenuItemText(mh, MAILBOX_OTHER_ITEM, "\p-"); //Change Other ... into a divider line
|
|
|
|
//And disable all mailbox entries in the menu
|
|
menuCount = CountMenuItems(mh);
|
|
for(item=MAILBOX_FIRST_USER_ITEM;item<=menuCount;item++)
|
|
{
|
|
// Do submenu with recursion
|
|
if (subID = SubmenuId(mh,item)) TweakSubMenuForFolderSelect(subID);
|
|
// otherwise disable the item. It's a mailbox
|
|
else EnableIf(mh,item,false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
* TweakSubMenuForFolderSelect -
|
|
************************************************************************/
|
|
void TweakSubMenuForFolderSelect(short menu)
|
|
{
|
|
MenuHandle mh;
|
|
short menuCount,subID,item;
|
|
|
|
if (mh = GetMHandle(menu))
|
|
{
|
|
SetItemR(mh, 1, CHOOSE_MBOX_THIS_FOLDER); //replace the New... item with "This Mailbox"
|
|
SetMenuItemText(mh, 2, "\p-"); //Change Other ... into a divider line
|
|
|
|
menuCount = CountMenuItems(mh);
|
|
for(item=3;item<=menuCount;item++)
|
|
{
|
|
if (subID = SubmenuId(mh,item)) TweakSubMenuForFolderSelect(subID);
|
|
else EnableIf(mh,item,false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* SetDefaultLocation - set the default location static text item
|
|
************************************************************************/
|
|
void SetDefaultLocation(DialogPtr dlog, Str255 defaultText)
|
|
{
|
|
Str255 string;
|
|
|
|
ComposeString(string, "\p%p.", defaultText);
|
|
SetDIText(dlog, MF_DEFAULT, string);
|
|
} |