eudora-mac/menu.c

1 line
93 KiB
C
Executable File
Raw Permalink Blame History

/* 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 "menu.h"
#define FILE_NUM 11
/* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
#pragma segment Menu
void SetQItemText(MyWindowPtr win);
Boolean DoDependentMenu(WindowPtr topWinWP,int menu,int item,short modifiers);
void BuildWindowsMenu(Boolean allMenu);
Boolean SameSettingsFile(short vRef,long dirId,UPtr name);
void InsertRecipient(MyWindowPtr win, short which,Boolean all);
void CheckTable(MyWindowPtr win,Boolean all);
void CheckLabel(MyWindowPtr win,Boolean all);
void EnableHelpItems(void);
void NewSigFile(void);
Boolean TextMenuOK(MyWindowPtr win);
void CheckTextItems(MyWindowPtr win,short modifiers,Boolean all);
void TextMenuChoice(short menu,short item,short modifiers);
void MarginMenuChoice(PETEHandle pte,short item,PETEParaInfoPtr pinfo,long *paraValid);
void SaveRecipMenu(MenuHandle mh);
// All this to get rid of the "Change Password Menu Item"
short gDeletedSpecialItem = 9999; // Where have we deleted an item?
Boolean ChangePWMenuShown () { return gDeletedSpecialItem > 1000; }
short AdjustSpecialMenuSelection ( short item ) { return item >= gDeletedSpecialItem ? item + 1 : item; }
short AdjustSpecialMenuItem ( short item ) { return item >= gDeletedSpecialItem ? item - 1 : item; }
#define TICKS2MINS 3600
/*************************************CMM Stuff ***************************************************/
#ifdef USECMM
typedef enum
{
CONTEXT_TERM_ITEM,
CONTEXT_SEPARATOR_ITEM,
CONTEXT_ITEMS_LIMIT
} ContextSpecialItems;
OSStatus DoHandleContextualMenuClick( WindowPtr topWinWP, EventRecord* event );
OSStatus BuildBasicContextMenu( MenuHandle contextMenu );
#endif
/**********************************************************************
* DoMenu - handle a menu selection
**********************************************************************/
// (jp) Not all windows will be ours when this is called (some may be dialog)
// so we really need to pass in a WindowPtr instead of MyWindowPtr
void DoMenu(WindowPtr topWin,long selection,short modifiers)
{
short menu = (selection >> 16) & 0xffff;
short item = selection & 0xffff;
Str255 s;
CHECK_EXPIRE;
#ifdef MENUSTATS
if (LOG_MENU&LogLevel)
{
Str31 mStr,iStr;
PCopy(mStr,"\pnone");
PCopy(iStr,mStr);
if (menu)
{
GetMenuTitle(GetMHandle(menu),mStr);
if (item) MyGetItem(GetMHandle(menu),item,iStr);
}
ComposeLogS(LOG_MENU,nil,"\p%p %p",mStr,iStr);
}
NoteMenuSelection(selection);
#endif
if (!item)
{
long nonSelection;
if (nonSelection = MenuChoice()) // Was a non-selectable menu item selected?
{
short nonMenu = (nonSelection >> 16) & 0xffff;
short nonItem = nonSelection & 0xffff;
if (IsMailboxChoice(nonMenu,nonItem))
if (MyGetItem(GetMHandle(nonMenu),nonItem,s)[1]!='-' || *s!=1)
if (nonMenu==MAILBOX_MENU || ((menu-(g16bitSubMenuIDs?BOX_MENU_START:1))/MAX_BOX_LEVELS) == MAILBOX)
{
// Mailbox folder
MenuHandle hAddMenu;
Handle hStringList;
if (hStringList = NuHandleClear(1))
{
Boolean IsIMAP;
short vRef;
long dirID;
short subMenu;
// If in main mailbox menu, we need to go to a sub level to accurately
// determine if this is an IMAP folder
subMenu = nonMenu==MAILBOX_MENU ? SubmenuId(GetMHandle(nonMenu), nonItem) : 0;
for(hAddMenu = GetMHandle(nonMenu);hAddMenu;hAddMenu = ParentMailboxMenu(hAddMenu,&nonItem))
{
MyGetItem(hAddMenu,nonItem,s);
Munger(hStringList,0,nil,0,s,*s+1); // Insert at front of handle
}
MenuID2VD(subMenu?subMenu:nonMenu,&vRef,&dirID);
IsIMAP = IsIMAPVD(vRef,dirID);
if (!IsIMAP)
{
// Add Eudora Folder
GetDirName(nil,Root.vRef,Root.dirId,s);
Munger(hStringList,0,nil,0,s,*s+1); // Insert at front of handle
}
MBOpenFolder(hStringList,IsIMAP);
DisposeHandle(hStringList);
}
}
}
}
if (!PETEMenuSelectFilter(PETE,selection) && menu && item)
{
PushCursor(watchCursor);
#ifdef TWO
if (!SharedMenuHit(menu,item))
#endif
{
#if __profile__
Boolean doProfile = BUG10;
if (doProfile) ProfilerClear();
#endif
if (menu==FILE_MENU && item==FILE_SAVE_ITEM && 0!=(modifiers&optionKey))
SaveAll();
if (!(topWin && GetWindowKind(topWin)==dialogKind &&
menu==EDIT_MENU && DoModelessEdit(GetWindowMyWindowPtr(topWin),item)) &&
!DoDependentMenu(topWin,menu,item,modifiers) &&
!DoIndependentMenu(menu,item,modifiers))
/*NotImplemented()*/;
#if __profile__
if (doProfile)
{
ProfilerDump("\pEudora Menu Profile");
SetItemMark(GetMHandle(DEBUG_MENU),11,0);
BugFlags &= ~(1L<<(11-1));
}
#endif
}
PopCursor();
}
HiliteMenu(0);
}
#ifdef MENUSTATS
/**********************************************************************
* NoteMenuSelection - save a user's menu selection
**********************************************************************/
void NoteMenuSelection(long selection)
{
struct {short what; long selection;} addme;
static Handle saved;
long size;
FSSpec spec;
short refN;
Str255 user, host;
if (selection!=-1)
{
addme.what = MainEvent.what;
addme.selection = selection;
if (!saved) saved = NuHTempBetter(0);
if (saved) PtrPlusHand(&addme,saved,sizeof(addme));
}
if (saved)
{
size = GetHandleSize(saved);
if (size && (size>20 K || selection==-1))
{
GetPOPInfo(user,host);
PCat(user,"\p-MenuStats");
SimpleMakeFSSpec(Root.vRef,Root.dirId,user,&spec);
FSpDelete(&spec);
PCat(user,"\pNew");
FSpCreate(&spec,CREATOR,'menu',smSystemScript);
if (!FSpOpenDF(&spec,fsRdWrPerm,&refN))
{
SetFPos(refN,fsFromLEOF,0);
AWrite(refN,&size,LDRef(saved));
UL(saved);
MyFSClose(refN);
}
SetHandleBig(saved,0);
}
}
}
#endif
/************************************************************************
* SaveAll - save all windows
************************************************************************/
void SaveAll(void)
{
WindowPtr winWP;
MyWindowPtr win;
RememberOpenWindows();
for (winWP=MyFrontWindow();winWP;winWP=GetNextWindow(winWP)) {
win = GetWindowMyWindowPtr (winWP);
if (IsKnownWindowMyWindow(winWP) && win && IsDirtyWindow(win))
DoMenu(winWP,(FILE_MENU<<16)|FILE_SAVE_ITEM,0);
}
}
/**********************************************************************
* DoIndependentMenu - handle a menu selection that does not depend on
* what window is frontmost. returns True if selection handled, False else
**********************************************************************/
Boolean DoIndependentMenu(int menu,int item,short modifiers)
{
Str255 scratch;
short function;
MenuHandle mh=GetMHandle(menu);
MyWindowPtr newWin;
WindowPtr winWP=MyFrontWindow();
MyWindowPtr win = GetWindowMyWindowPtr (winWP);
FSSpec spec;
short n;
TextAddrHandle addr;
Boolean plain = 0!=(modifiers&shiftKey);
short kind;
#ifdef ETL
HeadSpec hs;
#endif
switch (menu)
{
case APPLE_MENU:
switch (item)
{
case APPLE_ABOUT_ITEM:
DoAboutUIUCmail();
return(True);
case APPLE_ABOUT_TRANS_ITEM:
ETLDoAbout();
return(True);
default:
return(False);
}
break;
case EDIT_MENU:
if (item==EDIT_PASTE_ITEM && modifiers&optionKey) item = EDIT_QUOTE_ITEM; // ugly hack, but otherwise shift-opt-cmd-v doesn't work
switch (item)
{
case EDIT_FINISH_ITEM:
// (jp) this is being moved in here to handle things a bit more generically...
/* If the user pressed Command-Shift-Option-Comma, temporarily toggle nickname type-ahead. This
change will get reset to the setting in preferences the next time a composition window receives
an activate/deactivate event. */
if (IsMyWindow(winWP) && win) {
if (win->pte && HasNickCompletion (win->pte))
if ((modifiers & (cmdKey | shiftKey | optionKey)) == (cmdKey | shiftKey | optionKey))
ToggleNicknameTypeAhead (win->pte);
else
FinishAlias (win->pte, (modifiers & optionKey) != 0 && (HasNickExpansion (win->pte) || HasNickCompletion (win->pte)), True, false);
return(True);
}
break;
case EDIT_UNDO_ITEM:
DoUndo();
return(True);
break;
case EDIT_SELECT_ITEM:
{
if (win->pte)
{
PeteSelectAll(win,win->pte);
return(True);
}
}
break;
case EDIT_COPY_ITEM:
if (win->pte)
{
PeteEdit(win,win->pte,plain ? peeCopyPlain:peeCopy,&MainEvent);
if (modifiers&optionKey) UnwrapClip();
}
break;
case EDIT_CLEAR_ITEM:
if (win->pte) PeteEdit(win,win->pte,peeClear,&MainEvent);
break;
case EDIT_CUT_ITEM:
if (win->pte)
{
PeteEdit(win,win->pte,plain ? peeCutPlain:peeCut,&MainEvent);
if (modifiers&optionKey) UnwrapClip();
}
break;
case EDIT_PASTE_ITEM:
if (win->pte)
{
PeteEdit(win,win->pte,PrefIsSetOrNot(PREF_PASTE_PLAIN,modifiers,shiftKey) ? peePastePlain:peePaste,&MainEvent);
}
break;
case EDIT_QUOTE_ITEM:
if (win->pte)
{
PetePasteQ(win,PrefIsSetOrNot(PREF_PASTE_PLAIN,modifiers,shiftKey));
}
break;
case EDIT_WRAP_ITEM:
if (win->pte)
{
PeteWrap(win,win->pte,(modifiers&optionKey)!=0);
}
break;
#ifdef SPEECH_ENABLED
case EDIT_SPEAK_ITEM:
if ((modifiers & shiftKey)!=0)
(void) SpeakSelectedText (nil, win->pte);
break;
#endif
case EDIT_SPELL_ITEM:
FindSpeller();
return(True);
break;
#ifdef DIAL
case EDIT_DIAL_ITEM:
if (win->pte)
{
PeteString(scratch,win->pte);
Dial(scratch,kDialDefault);
}
break;
#endif
default:
if (item>EDIT_SPELL_ITEM)
if (modifiers & optionKey)
DelWSService(item,true);
else
HandleWordServices(win,item);
return(True);
break;
}
break;
#ifdef WINTERTREE
case SPELL_HIER_MENU:
SpellMenu(item,modifiers);
return(True);
break;
#endif
#ifdef ETL
case TLATE_SEL_HIER_MENU:
if (win && win->hasSelection && win->pte)
{
PeteGetTextAndSelection(win->pte,nil,&hs.value,&hs.stop);
hs.start = hs.value;
}
else if (IsMessWindow(winWP))
CompHeadFind(Win2MessH(win),0,&hs);
else if (win && win->pte)
{
hs.start = hs.value = 0;
hs.stop = PETEGetTextLen(PETE,win->pte);
}
else break;
ETLTransSelection(win->pte,&hs,item);
break;
#endif
case TEXT_HIER_MENU:
case FONT_HIER_MENU:
case COLOR_HIER_MENU:
case MARGIN_HIER_MENU:
case TEXT_SIZE_HIER_MENU:
TextMenuChoice(menu,item,modifiers);
break;
case HELP_MENU:
case kHMHelpMenuID:
n = EndHelpCount;
if (item==n--) {ReportABug();break;}
else if (item==n--) {MakeASuggestion();break;}
else if (item==n--) {InsertSystemConfig(win->pte); break;}
#ifndef DEATH_BUILD
#ifdef NAG
else
// Payment & Registration<6F>
if (item==n--)
OpenPayWin ();
#else
else if (GetPrefLong(PREF_REGISTER)!=0x0fffffff && item==n--) {RegisterEudoraHi(); break;}
else if (item==n--) PurchaseEudora();
#endif
#endif
else HelpTextWin(item);
break;
case FILE_MENU:
switch (item)
{
case FILE_NEW_ITEM:
(void) OpenText(nil,nil,nil,nil,True,GetRString(scratch,UNTITLED),False,False);
return(True);
break;
#ifdef TWO
case FILE_OPENSEL_ITEM:
if (!AttIsSelected(win,win->pte,-1,-1,attAll+(modifiers&controlKey?attFinder:0),nil,nil))
URLIsSelected(win,win->pte,-1,-1,urlAll,nil,nil);
break;
#endif
case FILE_OPENDOC_ITEM:
DoSFOpen(modifiers);
break;
case FILE_CLOSE_ITEM:
if (modifiers&optionKey)
{
CloseAll(False);
return(True);
}
else if (IsMyWindow(MyFrontWindow()))
{
CloseMyWindow(MyFrontWindow());
return(True);
}
else
return(False);
break;
case FILE_IMPORT_MAIL_ITEM:
DoMailImport();
break;
case FILE_EXPORT_ITEM:
DoFileExport();
break;
case FILE_SEND_ITEM:
if (SendThreadRunning)
SendImmediately=True;
else
XferMail(False,True,True,False,True,modifiers);
return(True);
case FILE_CHECK_ITEM:
XferMail(True,PrefIsSet(PREF_SEND_CHECK),True,False,True,modifiers);
return(True);
case FILE_PAGE_ITEM:
DoPageSetup();
return(True);
case FILE_QUIT_ITEM:
DoQuit(false);
return(True);
}
break;
case NEW_TO_HIER_MENU:
if (newWin=DoComposeNew(addr=MenuItem2Handle(menu,item)))
{
#ifdef TWO
MessHandle messH =(MessHandle)GetMyWindowPrivateData(newWin);
ApplyDefaultStationery(newWin,True,True);
UpdateSum(messH,SumOf(messH)->offset,SumOf(messH)->length);
#endif
ShowMyWindow(GetMyWindowWindowPtr(newWin));
}
ZapHandle(addr);
return(True);
break;
case FIND_HIER_MENU:
DoFind(item,modifiers);
return(True);
break;
case MESSAGE_MENU:
switch(item)
{
case MESSAGE_NEW_ITEM:
// ignore cmd-shift-N here when we're using an alternate command key for check mail.
if (!PrefIsSet(PREF_ALTERNATE_CHECK_MAIL_CMD) || ((modifiers&shiftKey)==0))
{
if (newWin=DoComposeNew(0))
{
MessHandle messH =(MessHandle)GetMyWindowPrivateData(newWin);
#ifdef TWO
ApplyDefaultStationery(newWin,True,True);
UpdateSum(messH,SumOf(messH)->offset,SumOf(messH)->length);
#endif
ShowMyWindow(GetMyWindowWindowPtr(newWin));
}
return(True);
}
break;
}
break;
case MAILBOX_MENU:
{
short refN = CurResFile ();
if (item>=MAILBOX_FIRST_USER_ITEM || item<MAILBOX_BAR1_ITEM)
{
MailboxMenuFile(menu,item,scratch);
FSMakeFSSpec(MailRoot.vRef,MailRoot.dirId,scratch,&spec);
(void) GetMailbox(&spec,True);
}
#ifdef TWO
else if (item==MAILBOX_NEW_ITEM)
{
GetTransferParams(MAILBOX_MENU,item,&spec,nil);
}
else if (item==MAILBOX_OTHER_ITEM)
{
if (!AskGraft(MailRoot.vRef,MailRoot.dirId,&spec))
(void) GetMailbox(&spec,True);
}
#endif
UseResFile (refN);
return(True);
break;
}
case NEW_WITH_HIER_MENU:
//Stationery - no support for this in Light
if (HasFeature (featureStationery))
NewMessageWith(item);
break;
case SPECIAL_MENU:
item = AdjustSpecialMenuSelection (item);
switch ( item )
{
#ifdef CTB
case SPECIAL_CTB_ITEM:
(void) InitCTB(True);
return(True);
#endif
case SPECIAL_SETTINGS_ITEM:
DoSettings(GetPrefLong(PREF_LAST_SCREEN));
return(True);
case SPECIAL_FORGET_ITEM:
if (HasFeature (featureMultiplePersonalities) && DoWeUseSelectedPersonalities())
ForgetPersPassword();
else
InvalidatePasswords(False,False,True);
if (PrefIsSet(PREF_KERBEROS)) KerbDestroy();
return(True);
case SPECIAL_TRASH_ITEM:
if (HasFeature (featureMultiplePersonalities) && DoWeUseSelectedPersonalities())
EmptyIMAPPersTrash();
else
{
#ifdef IMAP
if (IMAPExists())
{
Boolean expunge = false;
//
// Remove Deleted Messages
//
// if the frontmost window is a mailbox
if (winWP && GetWindowKind(winWP)==MBOX_WIN)
{
// and it's an IMAP mailbox
if (((TOCHandle)GetMyWindowPrivateData(win)) && (*((TOCHandle)GetMyWindowPrivateData(win)))->imapTOC)
{
// and fancy trash is off for it
if (!FancyTrashForThisPers((TOCHandle)GetMyWindowPrivateData(win)))
{
// and the option key is pressed, expunge it
if (!(modifiers&shiftKey)&&(modifiers&optionKey))
{
expunge = true;
return (IMAPRemoveDeletedMessages((TOCHandle)GetMyWindowPrivateData(win)));
}
}
}
}
//
// Empty Trash
//
if (!expunge) EmptyTrash(false, ((modifiers&shiftKey)&&!(modifiers&optionKey)), (!(modifiers&shiftKey)&&(modifiers&optionKey)));
}
else
EmptyTrash(true, false, false);
#else
EmptyTrash();
#endif
}
return(True);
case SPECIAL_CHANGE_ITEM:
if (HasFeature (featureMultiplePersonalities) && DoWeUseSelectedPersonalities())
ChangePersPassword();
else
ChangePassword();
return(True);
#ifdef THREADING_ON
#ifndef BATCH_DELIVERY_ON
case SPECIAL_FILTER_ITEM:
FilterXferMessages();
break;
#endif
#endif
default:
if (item>SPECIAL_BAR4_ITEM)
{
ETLSpecial(item-SPECIAL_BAR4_ITEM);
return(True);
}
break;
}
break;
case SCRIPTS_MENU:
DoScriptMenu(item);
return true;
#ifdef DEBUG
case WIND_PROP_HIER_MENU:
if (IsMyWindow(winWP)) DoWindowPropMenu(win,item,modifiers);
return true;
#endif
case WINDOW_MENU:
if (item==WIN_PROPERTIES_ITEM)
{
DoWindowPropMenu(win,wpmTabs,modifiers);
return true;
}
switch (item)
{
#ifdef TWO
case WIN_FILTERS_ITEM:
OpenFiltersWindow();
break;
#endif
case WIN_ALIASES_ITEM:
OpenABWin((MainEvent.modifiers&shiftKey)?CurAddr(win,scratch):nil);
break;
case WIN_PH_ITEM:
{
Str255 string;
if (win && IsMyWindow(winWP) && (modifiers&shiftKey) && win->hasSelection && win->pte)
{
PeteSelectedString(string,win->pte);
if (*string && string[*string]==',') --*string;
OpenPh(string);
}
else
OpenPh(nil);
break;
}
case WIN_MAILBOX_ITEM:
OpenMBWin();
break;
case WIN_SIGNATURES_ITEM:
OpenSignaturesWin();
break;
case WIN_PERSONALITIES_ITEM:
if (HasFeature (featureMultiplePersonalities))
OpenPersonalitiesWin();
break;
case WIN_STATIONERY_ITEM:
if (HasFeature (featureStationery))
OpenStationeryWin();
break;
case WIN_LINK_ITEM:
if (HasFeature (featureLink))
OpenLinkWin();
break;
case WIN_STATISTICS_ITEM:
if (HasFeature (featureStatistics))
OpenStatWin();
break;
#ifdef TASK_PROGRESS_ON
case WIN_TASKS_ITEM:
OpenTasksWin();
TaskDontAutoClose = true;
break;
#endif
case WIN_DRAWER_ITEM:
kind = GetWindowKind(winWP);
if (kind==MBOX_WIN||kind==CBOX_WIN)
MBDrawerToggle(win);
break;
default:
HandleWindowChoice(item);
break;
}
return true;
case INSERT_TO_HIER_MENU:
if (IsMyWindow(MyFrontWindow()))
InsertRecipient(GetWindowMyWindowPtr(MyFrontWindow()),item,HasFeature (featureNicknameWatching) && PrefIsSetOrNot(PREF_NICK_AUTO_EXPAND,modifiers,optionKey));
return(True);
case EMOTICON_HIER_MENU:
if (IsMyWindow(MyFrontWindow()))
EmoInsert(GetWindowMyWindowPtr(MyFrontWindow()),item);
return(True);
break;
case TLATE_SET_HIER_MENU:
ETLDoSettings(item);
break;
#ifdef DEBUG
case DEBUG_MENU:
{
short theMark;
if (item<=16)
{
GetItemMark(mh,item,&theMark);
if (theMark)
{
SetItemMark(mh,item,0);
BugFlags &= ~(1L<<(item-1));
}
else
{
SetItemMark(mh,item,checkMark);
BugFlags |= (1L<<(item-1));
}
}
else
switch (item)
{
case dbDebugger:
Debugger();
n = *(short*)0; // Cause exception to fall into GDB
break;
#ifdef IMAP
case dbIMAPMsgFlags: IMAPCollectFlags(); break;
#endif
case dbSLReseLeaks: SLResetLeaks();
case dbDumpPte:
if (IsMyWindow(winWP) && win && win->pte) PeteDump(win->pte);
break;
#ifdef NAG
case dbNag: DebugNagging (); break;
#endif
case dbDumpCtl:
if (winWP)
{
FindFolder(kOnSystemDisk,kDesktopFolderType,false,&spec.vRefNum,&spec.parID);
PCopy(spec.name,"\pControl Hierarchy");
UniqueSpec(&spec,31);
DumpControlHierarchy(winWP,&spec);
}
break;
#ifdef AD_WINDOW
case dbAdWin:
ToggleAdWindow((modifiers&optionKey)==0);
break;
#endif
case dbAudit:
{
// extern void AskSendAudit(void);
AskSendAudit();
break;
}
case dbLWSPMatch:
#define TM(res,lf,tx,s,e) if (res!=PPMatchLWSP(lf,tx,s,e)) {Debugger();PPMatchLWSP(lf,tx,s,e);}
#define TM2(cntns,strt,nd,lf,tx) TM(cntns,lf,tx,false,false); TM(cntns&&strt,lf,tx,true,false); TM(cntns&&nd,lf,tx,false,true); TM(cntns&&strt&&nd,lf,tx,true,true);
TM2(true,false,false,"\p123","\p01234");
TM2(true,false,true,"\p123","\p0123");
TM2(true,true,false,"\p123","\p1234");
TM2(true,true,true,"\p1 2 3","\p1 2 3");
TM2(true,true,true,"\p1 2 3","\p1 2 3");
TM2(true,true,true,"\p1 2 3","\p1 2 3");
TM2(true,true,true,"\p1 2\r\r\r3","\p1 2 3");
TM2(false,false,false,"\p1 23","\p1 2 3");
TM2(true,false,false,"\p1 2 3","\p0 1 2 3 4");
TM2(true,false,true,"\p1 2 3","\p0 1 2 3");
TM2(true,true,false,"\p1 2 3","\p1 2 3 4");
TM2(true,true,true,"\p1 2\r\r\r3","\p 1 2 3 ");
break;
case dbAddRecvdStat:
{
// display all open files
FCBPBRec fcb;
short err;
Str63 name;
Zero(fcb);
for(fcb.ioFCBIndx=1;true;fcb.ioFCBIndx++)
{
fcb.ioNamePtr = name;
fcb.ioVRefNum = 0;
if (err=PBGetFCBInfo(&fcb,False)) break;
Dprintf("\p%d - %p, vol: %d, fileref: %d",fcb.ioFCBIndx,name,fcb.ioVRefNum,fcb.ioRefNum);
}
}
break;
case dbAddSentStat: UpdateNumStat(kStatSentMail,1); break;
}
return(True);
}
break;
case AD_SELECT_HIER_MENU: DebugAdMenu(item,modifiers); break;
#endif
default:
if (!IsMailboxChoice(menu,item)) return(False);
function = (menu-(g16bitSubMenuIDs?BOX_MENU_START:1))/MAX_BOX_LEVELS;
switch (function)
{
case MAILBOX:
if (item>=MAILBOX_FIRST_USER_ITEM-MAILBOX_BAR1_ITEM)
{
GetTransferParams(GetMenuID(mh),item,&spec,nil);
(void) GetMailbox(&spec,True);
}
#ifdef TWO
else if (item==MAILBOX_OTHER_ITEM-MAILBOX_BAR1_ITEM)
{
Menu2VD(mh,&spec.vRefNum,&spec.parID);
#ifdef IMAP
// if this is an IMAP cache directory, open the mailbox instead of grafting
GetMenuTitle(mh,spec.name);
if (IsIMAPMailboxFile(&spec))
{
(void) GetMailbox(&spec,True);
}
else
{
if (!AskGraft(spec.vRefNum,spec.parID,&spec))
(void) GetMailbox(&spec,True);
}
#else
if (!AskGraft(spec.vRefNum,spec.parID,&spec))
(void) GetMailbox(&spec,True);
#endif
}
else if (item==MAILBOX_NEW_ITEM-MAILBOX_BAR1_ITEM)
GetTransferParams(menu,item,&spec,nil);
#endif
return(True);
case TRANSFER:
break;
}
}
return(False);
}
/**********************************************************************
* DoDependentMenu - handle a menu selection whose behavior depends
* on what window is frontmost. returns True if item handled, False else
**********************************************************************/
Boolean DoDependentMenu(WindowPtr topWinWP,int menu,int item,short modifiers)
{
MyWindowPtr topWin = GetWindowMyWindowPtr (topWinWP);
#ifdef THREADING_ON
#ifndef BATCH_DELIVERY_ON
if((menu==SPECIAL_MENU) && (item==SPECIAL_FILTER_ITEM) && modifiers&optionKey)
return False;
#endif
#endif
if (topWinWP != nil)
{
if (IsPlugwindow(topWinWP))
return(PlugwindowMenu(topWinWP,(menu<<16)|item));
else if ((GetWindowKind(topWinWP)>userKind ||
GetWindowKind(topWinWP)==dialogKind) &&
topWin->menu)
return((*(topWin)->menu)(topWin,menu,item,modifiers));
}
return(False);
}
/**********************************************************************
* MenuItemIsSeparator - returns true if the given item in the given
* menu is a divider line
**********************************************************************/
Boolean MenuItemIsSeparator(MenuHandle theMenu, short item)
{
Str255 itemString;
if (!theMenu) return false;
GetMenuItemText(theMenu, item, itemString);
return (itemString[0] && (itemString[1] == '-')) ? true : false;
}
/**********************************************************************
* EnableMenuItems - enable menu items, depending on the type and state of
* the topmost window
**********************************************************************/
void EnableMenuItems(Boolean all)
{
int kind;
Boolean dirty = False, selection = False;
MenuHandle mh;
WindowPtr winWP = MyFrontWindow();
MyWindowPtr win = GetWindowMyWindowPtr(winWP);
WindowPtr nextWin;
Boolean hasTx=False, ro=False;
Boolean scrapFull;
Boolean outside = False;
Boolean curMessage = False;
Boolean force = False;
Boolean compRo = False;
Boolean html = False;
Boolean composeHTML = !PrefIsSet(PREF_SEND_ENRICHED_NEW);
Boolean plugwindow = IsPlugwindow(winWP);
Boolean hasNickScan = False;
short field=0;
PETEHandle pte=nil;
Str63 txt;
long transFlags;
#ifdef TWO
short itm,n;
MenuHandle txtSubMenuHdl;
short itemNo, numTxtSubMenuItems;
Boolean textOK;
Boolean hasPreview = false;
Boolean hasDrawer = false;
TOCHandle tocH = NULL;
#endif
/*
* figure out just what's in front
*/
if (winWP==(WindowPtr)(-1)) {winWP = nil; force = True;}
if (winWP==nil)
{
kind=0;
dirty=False; selection=False; hasTx=False; ro = True;
if (keyFocusedFloater)
{
hasTx = true;
selection = MyWinHasSelection(keyFocusedFloater);
pte = keyFocusedFloater->pte;
ro = PETESelectionLocked(PETE,pte,-1,-1);
}
}
else
{
kind = GetWindowKind(winWP);
if (kind >= userKind && kind!=EMS_PW_WINDOWKIND)
{
dirty = IsDirtyWindow(win);
selection = win->hasSelection || MyWinHasSelection(win);
pte = win->pte;
hasTx = pte!=nil;
if (kind==COMP_WIN)
{
compRo = SENT_OR_SENDING(SumOf(Win2MessH(win))->state);
field = CompHeadCurrent(pte);
}
else if (kind==PREF_WIN)
kind = 1; /* not a normal window */
else if (kind==MESS_WIN)
{
html = MessOptIsSet(Win2MessH(win),OPT_HTML);
}
else if (kind==MBOX_WIN || kind==CBOX_WIN)
{
tocH = (TOCHandle)GetMyWindowPrivateData(win);
if (LastMsgSelected(tocH)>=0)
{
n = FirstMsgSelected(tocH);
ASSERT(n>=0);
html = 0!=((*tocH)->sums[n].opts&OPT_HTML);
}
hasPreview = (*tocH)->previewID && (*tocH)->previewPTE;
hasDrawer = (*tocH)->drawer;
}
if (pte)
{
ro = PETESelectionLocked(PETE,pte,-1,-1);
}
}
if (IsMyWindow (winWP))
if (hasNickScan = HasNickScanCapability (win->pte)) {
hasTx = true;
ro = PETESelectionLocked (PETE, win->pte, -1, -1);
}
// figure out what's behind it
for (nextWin=GetNextWindow(winWP);nextWin;nextWin=GetNextWindow(nextWin))
if (IsWindowVisible(nextWin)) break;
}
if (plugwindow) PlugwindowEnable(winWP,&transFlags);
/*
* enable menus accordingly, if anything has changed
*/
curMessage = kind==MESS_WIN || kind==COMP_WIN ||
((kind==MBOX_WIN || kind==CBOX_WIN) && selection);
outside = curMessage && (kind==MESS_WIN || kind==MBOX_WIN);
if (!HMGetHelpMenuHandle(&mh) && mh) /* the check for nil is needed courtesy of Norton Utilities, crap that it is */
EnableIf(mh,EndHelpCount-2,all||hasTx&&!ro);
EnableIf(GetMHandle(APPLE_MENU),APPLE_ABOUT_ITEM,all||!ModalWindow);
if (ETLExists()) EnableIf(GetMHandle(APPLE_MENU),APPLE_ABOUT_ITEM+1,all||!ModalWindow);
mh = GetMHandle(FILE_MENU);
EnableIf(mh,FILE_NEW_ITEM,(all||!ModalWindow));
EnableIf(mh,FILE_OPENDOC_ITEM,(all||!ModalWindow));
EnableIf(mh,FILE_CLOSE_ITEM,(all||kind!=0&&kind!=TBAR_WIN&&kind!=PROG_WIN&&!ModalWindow&&(!plugwindow||(transFlags&EMS_MENU_FILE_CLOSE))));
EnableIf(mh,FILE_OPENSEL_ITEM,all||
kind==MESS_WIN && AttIsSelected(win,pte,-1,-1,0,nil,nil) || hasTx && urlNot!=URLIsSelected(win,pte,-1,-1,0,nil,nil) ||
((kind==MBOX_WIN||kind==CBOX_WIN||kind==MB_WIN||kind==PERS_WIN||kind==SIG_WIN||kind==STA_WIN||kind==LINK_WIN||kind==IMPORTER_WIN) && selection));
EnableIf(mh,FILE_BROWSE_ITEM,all||html);
EnableIf(mh,FILE_SAVE_ITEM,all||(win!=nil && (CurrentModifiers()&optionKey))||dirty||(plugwindow&&(transFlags&EMS_MENU_FILE_SAVE)));
EnableIf(mh,FILE_SAVE_AS_ITEM,all||curMessage||kind==TEXT_WIN||IsSearchWindow(winWP)||kind==ALIAS_WIN);
EnableIf(mh,FILE_IMPORT_MAIL_ITEM,gImportersAvailable && (all||!ModalWindow));
EnableIf(mh,FILE_PAGE_ITEM,(all||!ModalWindow));
EnableIf(mh,FILE_PRINT_ITEM,all||curMessage||kind==PH_WIN||kind==TEXT_WIN||kind==ALIAS_WIN||kind==FILT_WIN||kind==STAT_WIN);
EnableIf(mh,FILE_PRINT_ONE_ITEM,all||curMessage||kind==PH_WIN||kind==TEXT_WIN||kind==ALIAS_WIN||kind==FILT_WIN||kind==STAT_WIN);
mh = GetMHandle(WINDOW_MENU);
EnableIf(mh,WIN_MINIMIZE_ITEM,all||win!=nil&&kind!=TBAR_WIN&&kind!=AD_WIN);
EnableIf(mh,WIN_BEHIND_ITEM,all||win!=nil&&nextWin!=nil&&GetWindowKind(nextWin)!=TBAR_WIN);
EnableIf(mh,WIN_DRAWER_ITEM,all||kind==MBOX_WIN||kind==CBOX_WIN);
SetItemMark(mh,WIN_DRAWER_ITEM,hasDrawer?checkMark:0);
mh = GetMHandle(EDIT_MENU);
if ((win && kind<userKind) || (plugwindow&&(transFlags&EMS_MENU_EDIT_UNDO)))
{
Str63 scratch;
GetRString(scratch,UNDO);
SetMenuItemText(mh,EDIT_UNDO_ITEM,scratch);
EnableIf(mh,EDIT_UNDO_ITEM,(all||win!=nil||plugwindow) && !ModalWindow);
}
else
SetUndoMenu(win);
if (all) EnableItem(mh,EDIT_UNDO_ITEM);
EnableIf(mh,EDIT_CUT_ITEM,(all||win && (kind<userKind || selection && hasTx && !ro && field!=ATTACH_HEAD)) || (plugwindow&&(transFlags&EMS_MENU_EDIT_CUT)));
#ifdef ONE
EnableIf(mh,EDIT_COPY_ITEM,(all||win && (kind<userKind || selection&&hasTx&&field!=ATTACH_HEAD)) || (plugwindow&&(transFlags&EMS_MENU_EDIT_COPY)));
#else
EnableIf(mh,EDIT_COPY_ITEM,(all||win && (kind<userKind||selection&&field!=ATTACH_HEAD)) || (plugwindow&&(transFlags&EMS_MENU_EDIT_COPY)));
#endif
scrapFull = IsScrapFull();
textOK = TextMenuOK(win);
EnableIf(mh,EDIT_PASTE_ITEM,(all||win && (scrapFull &&
(!ro && hasTx || kind==PH_WIN) || kind<userKind)) || (plugwindow&&(transFlags&EMS_MENU_EDIT_PASTE)));
EnableIf(mh,EDIT_QUOTE_ITEM,all||scrapFull && !ro && hasTx && (kind!=COMP_WIN || !CompHeadCurrent(pte)));
EnableIf(mh,EDIT_CLEAR_ITEM,(all||win && (kind<userKind || selection && (!ro || kind==COMP_WIN))) || (plugwindow&&(transFlags&EMS_MENU_EDIT_CLEAR)));
EnableIf(mh,EDIT_WRAP_ITEM,all||win && selection && !ro && hasTx && textOK);
EnableIf(mh,EDIT_SELECT_ITEM,(all||win && !plugwindow && kind!=PICT_WIN && (hasTx||kind!=FILT_WIN) && kind!=TBAR_WIN) || (plugwindow&&(transFlags&EMS_MENU_EDIT_SELECTALL)));
EnableIf(mh,EDIT_INSERT_TO_ITEM,all||hasTx&&!ro);
EnableIf(mh,EDIT_INSERT_EMOTICON_ITEM,all||hasTx&&!ro);
EnableIf(mh,EDIT_FINISH_ITEM,all||hasNickScan && (hasTx&&!ro));
EnableIf(mh,EDIT_TEXT_ITEM,all||textOK||TFBMenusAllowed(win));
EnableIf(mh,EDIT_SPELL_ITEM,all||!ModalWindow);
#ifdef SPEECH_ENABLED
// EnableIf(mh,EDIT_SPEAK_ITEM,SpeechAvailable () && (all||kind==MESS_WIN || kind==COMP_WIN
// || (kind==MBOX_WIN || kind==CBOX_WIN)&&selection));
EnableIf(mh,EDIT_SPEAK_ITEM,SpeechAvailable () && (all
|| (kind==MESS_WIN || kind==COMP_WIN)
|| ((kind==MBOX_WIN || kind==CBOX_WIN) && selection)
|| (hasTx&& selection)));
#else
EnableIf(mh,EDIT_SPEAK_ITEM,false);
#endif
EnableIf(mh,EDIT_PROCESS_ITEM,all||(hasTx||hasPreview)&&!compRo);
#ifdef WINTERTREE
EnableIf(mh,EDIT_ISPELL_HOOK_ITEM,all||hasTx&&HaveSpeller());
EnableSpellMenu(all);
#endif
#ifdef DIAL
EnableIf(mh,EDIT_DIAL_ITEM,all|| selection&&hasTx);
#endif
n = CountMenuItems(mh);
for (itm=EDIT_SPELL_ITEM+1;itm<=n;itm++)
{
#ifdef WINTERTREE
SetItemCmd(mh,itm,'6'+itm-EDIT_SPELL_ITEM);
#else
SetItemCmd(mh,itm,'5'+itm-EDIT_SPELL_ITEM);
#endif
EnableIf(mh,itm,all||hasTx/*&&!ro*/);
}
#ifdef DEBUG
{
extern Boolean gPLDownloadInProgress;
EnableIf(GetMHandle(AD_SELECT_HIER_MENU),1/*so sue me*/,!gPLDownloadInProgress);
}
#endif
EnableIf(GetMHandle(TEXT_HIER_MENU),0,all||textOK||TFBMenusAllowed(win));
EnableIf(GetMHandle(FONT_HIER_MENU),0,all||textOK);
EnableIf(GetMHandle(COLOR_HIER_MENU),0,all||textOK);
mh = GetMHandle(MARGIN_HIER_MENU);
EnableIf(mh,0,all||textOK);
EnableIf(mh,CountMenuItems(mh),all||textOK&&composeHTML);
EnableIf(GetMHandle(TLATE_SEL_HIER_MENU),0,all||(hasTx||hasPreview)&&!compRo);
txtSubMenuHdl=GetMHandle(TEXT_HIER_MENU);
numTxtSubMenuItems=CountMenuItems(txtSubMenuHdl);
for (itemNo=1;itemNo<=numTxtSubMenuItems;itemNo++)
{
if (!MenuItemIsSeparator(txtSubMenuHdl,itemNo))
EnableIf(txtSubMenuHdl,itemNo,all||textOK);
}
if (textOK && !all)
{
EnableIf(txtSubMenuHdl,tmURL,curMessage && composeHTML && URLOkHere(pte));
EnableIf(txtSubMenuHdl,tmRule,curMessage && composeHTML);
EnableIf(txtSubMenuHdl,tmGraphic,curMessage && composeHTML);
}
if (kind==MBOX_WIN || kind==CBOX_WIN) CheckSortItems(win);
EnableHelpItems();
EnableFindMenu(all);
mh = GetMHandle(MESSAGE_MENU);
GetRString(txt,PrefIsSet(PREF_REPLY_ALL)?REPLY_ALL:REPLY);
SetMenuItemText(mh,MESSAGE_REPLY_ITEM,txt);
EnableIf(mh,MESSAGE_REPLY_ITEM,all||outside);
EnableIf(mh,MESSAGE_FORWARD_ITEM,all||kind==MESS_WIN || kind==COMP_WIN
|| (kind==MBOX_WIN || kind==CBOX_WIN)&&selection);
EnableIf(mh,MESSAGE_REDISTRIBUTE_ITEM,all||outside);
EnableIf(mh,MESSAGE_SALVAGE_ITEM,all||kind==MESS_WIN || kind==COMP_WIN
|| (kind==MBOX_WIN || kind==CBOX_WIN)&&selection);
EnableIf(mh,MESSAGE_REPLY_WITH_ITEM,HasFeature(featureStationery)&&(all||outside));
EnableIf(GetMHandle(REPLY_WITH_HIER_MENU),0,HasFeature(featureStationery)&&(all||outside));
EnableIf(mh,MESSAGE_FORWARD_TO_ITEM,all||kind==MESS_WIN || kind==COMP_WIN
|| (kind==MBOX_WIN || kind==CBOX_WIN)&&selection);
EnableIf(mh,MESSAGE_REDIST_TO_ITEM,all||outside);
EnableIf(mh,MESSAGE_QUEUE_ITEM,all||
kind==COMP_WIN || kind==CBOX_WIN&&selection);
EnableIf(mh,MESSAGE_CHANGE_ITEM,all||curMessage);
EnableIf(mh,MESSAGE_DELETE_ITEM,all||curMessage);
EnableIf(mh,MESSAGE_JUNK_ITEM,HasFeature(featureJunk)&&(all||JunkItemsEnable(win,false)));
EnableIf(mh,MESSAGE_NOTJUNK_ITEM,HasFeature(featureJunk)&&(all||JunkItemsEnable(win,true)));
EnableIf(mh,MESSAGE_ATTACH_ITEM,all||kind==COMP_WIN&&!compRo);
EnableIf(mh,MESSAGE_ATTACH_TLATE_ITEM,all||kind==COMP_WIN&&!compRo);
EnableIf(GetMHandle(TLATE_ATT_HIER_MENU),0,all||kind==COMP_WIN&&!compRo);
EnableIf(GetMHandle(TLATE_SET_HIER_MENU),0,all||!ModalWindow);
GetRString(txt,PrefIsSet(PREF_AUTO_SEND)?SEND_M_ITEM:QUEUE_M_ITEM);
SetMenuItemText(mh,MESSAGE_QUEUE_ITEM,txt);
mh = GetMHandle(CHANGE_HIER_MENU);
EnableIf(mh,0,curMessage||all);
EnableIf(mh,CHANGE_QUEUEING_ITEM,
all||kind==COMP_WIN || kind==CBOX_WIN&&selection);
#ifdef TWO
EnableIf(mh,CHANGE_STATUS_ITEM,all||curMessage);
#endif
EnableIf(mh,CHANGE_PRIOR_ITEM,all||curMessage);
EnableIf(mh,CHANGE_LABEL_ITEM,all||curMessage);
EnableIf(mh,CHANGE_PERS_ITEM,HasFeature(featureMultiplePersonalities)&&(all||(curMessage&&PersCount()>1)));
// I dunno why we did this SD 6/23/04
// if (EnableIf(GetMHandle(TRANSFER_MENU),0,all||curMessage||DirtyHackForChooseMailbox)) DrawMenuBar();
mh = GetMHandle(SPECIAL_MENU);
#ifdef CTB
EnableIf(mh,AdjustSpecialMenuItem(SPECIAL_CTB_ITEM),all||UseCTB);
#endif
EnableIf(mh,AdjustSpecialMenuItem(SPECIAL_FORGET_ITEM),all ||
(PersAnyPasswords() || PrefIsSet(PREF_KERBEROS) || KeychainAvailable() && PrefIsSet(PREF_KEYCHAIN)) && !SendThreadRunning && !CheckThreadRunning);
EnableIf(mh,AdjustSpecialMenuItem(SPECIAL_MAKE_NICK_ITEM),all||curMessage||CanMakeNick());
EnableIf(mh,AdjustSpecialMenuItem(SPECIAL_MAKEFILTER_ITEM),all||curMessage);
EnableIf(mh,AdjustSpecialMenuItem(SPECIAL_SORT_ITEM),all||kind==MBOX_WIN||kind==CBOX_WIN);
if (kind==MBOX_WIN||kind==CBOX_WIN)
EnableIf(GetMHandle(SORT_HIER_MENU),SORT_MAILBOX_ITEM,all||(*(TOCHandle)GetMyWindowPrivateData(win))->virtualTOC);
EnableIf(mh,AdjustSpecialMenuItem(SPECIAL_TLATE_SETTINGS_ITEM),all||!ModalWindow&&ETLExists());
#ifdef TWO
EnableIf(mh,AdjustSpecialMenuItem(SPECIAL_FILTER_ITEM),all||curMessage);
EnableIf(mh,AdjustSpecialMenuItem(SPECIAL_CHANGE_ITEM),all||!PrefIsSet(PREF_KERBEROS));
#endif
#ifdef THREADING_ON
#ifndef BATCH_DELIVERY_ON
if (CurrentModifiers()&optionKey)
EnableIf(mh,AdjustSpecialMenuItem(SPECIAL_FILTER_ITEM),all||((NeedToFilterIn && !CheckThreadRunning) || (NeedToFilterOut && !SendThreadRunning)));
#endif
#endif
if (kind==COMP_WIN || kind==CBOX_WIN) SetQItemText(win);
/*
* this is a maverick menu item
*/
#ifdef THREADING_ON
EnableIf(GetMHandle(FILE_MENU),FILE_SEND_ITEM,(all||(!ModalWindow && SendQueue>0 && !SendImmediately)));
EnableIf(GetMHandle(FILE_MENU),FILE_CHECK_ITEM,(all||(!ModalWindow && !CheckThreadRunning && !(PrefIsSet(PREF_POP_SEND) && SendThreadRunning))));
#else
EnableIf(GetMHandle(FILE_MENU),FILE_SEND_ITEM,(all||(SendQueue>0)&&!ModalWindow));
#endif
EnableServerItems(win,-1,all || (CurrentModifiers()&optionKey),((CurrentModifiers()&shiftKey)!=0));
CheckPrior(win,all);
// Preferences menu for MacOS X
if (HaveTheDiseaseCalledOSX())
{
if (all|| (!all && !ModalWindow))
EnableMenuCommand (NULL, kHICommandPreferences);
else
DisableMenuCommand (NULL, kHICommandPreferences);
}
if (win && win->menuEnable)
(*win->menuEnable)(win);
}
#ifdef TWO
/**********************************************************************
* EnableHelpItems - enable the help menu items
**********************************************************************/
void EnableHelpItems(void)
{
MenuHandle mh;
short itm;
Str255 name;
if (!HMGetHelpMenuHandle(&mh) && OriginalHelpCount)
{
for (itm = EndHelpCount-1;itm>OriginalHelpCount;itm--)
{
if (ModalWindow) DisableItem(mh,itm);
else
{
GetMenuItemText(mh,itm,name);
if (*name!=1 || name[1]!='-') EnableItem(mh,itm);
}
}
}
}
#endif
/**********************************************************************
* MailboxKindaMenu - is this a mailbox kind of menu?
**********************************************************************/
short MailboxKindaMenu(short mnu,short item,PStr s,FSSpecPtr spec)
{
Boolean xfer;
if (spec) *spec->name = 0;
if (IsMailboxChoice(mnu,item))
{
GetTransferParams(mnu,item,spec,&xfer);
return(xfer ? TRANSFER_MENU:MAILBOX_MENU);
}
return(mnu);
}
#pragma segment MenuMain
/**********************************************************************
* EnableMenus - enable menus, depending on the type and state of
* the topmost window
**********************************************************************/
void EnableMenus(WindowPtr winWP,Boolean all)
{
Boolean mBar = False;
MyWindowPtr win = GetWindowMyWindowPtr (winWP);
Boolean curMessage = False;
short kind;
MenuHandle mh = nil;
/*
* figure out just what's in front
*/
if (winWP!=nil)
{
kind = GetWindowKind(winWP);
if (kind >= userKind)
{
switch (kind) {
case MESS_WIN:
case COMP_WIN:
curMessage = true;
break;
case MBOX_WIN:
case CBOX_WIN:
if (win) {
TOCHandle tocH = (TOCHandle) GetMyWindowPrivateData (win);
if (!((*tocH)->hasFileView && (*tocH)->fileView) && !SearchViewIsMailbox(tocH))
if (win->hasSelection || (tocH && (*tocH)->previewID))
curMessage = true;
}
break;
}
}
}
/*
* enable menus accordingly, if anything has changed
*/
mBar=EnableIf(mh = GetMHandle(FILE_MENU),0,!NoMenus && (all||!ModalWindow||AreAllModalsPlugwindows()))||mBar;
mBar=EnableIf(GetMHandle(APPLE_MENU),0,True)||mBar;
mBar=EnableIf(GetMHandle(MAILBOX_MENU),0,!NoMenus && (all||!ModalWindow))||mBar;
mBar=EnableIf(GetMHandle(EDIT_MENU),0,!NoMenus && !(win&&win->noEditMenu) && (all||XfUndoH||IsPlugwindow(winWP)||win!=nil&&!ProgressIsOpen()))||mBar;
mBar=EnableIf(GetMHandle(MESSAGE_MENU),0,!NoMenus && (all||!ModalWindow))||mBar;
mBar=EnableIf(GetMHandle(TRANSFER_MENU),0,!NoMenus && (all||curMessage||DirtyHackForChooseMailbox))||mBar;
mBar=EnableIf(GetMHandle(SPECIAL_MENU),0,!NoMenus && (all||!ModalWindow))||mBar;
mBar=EnableIf(GetMHandle(WINDOW_MENU),0,!NoMenus && (all||!ModalWindow))||mBar;
SetWindowPropMenu(win,true,all,checkMark,CurrentModifiers());
/*
* draw the menu bar if that's necessary
*/
if (mBar)
{
DrawMenuBar();
TBForceIdle();
}
}
/************************************************************************
* EnableIf - enable a menu item based on an expression.
* Returns True is the menu bar needs to be redrawn.
************************************************************************/
Boolean EnableIf(MenuHandle mh, short item, Boolean expr)
{
Boolean result;
short mark;
if (!mh) return(False);
expr = expr ? 1 : 0; /* normalize */
result = item==0 && ((IsMenuItemEnabled(mh,0))!=(expr));
if (expr)
EnableItem(mh,item);
else
DisableItem(mh,item);
/*
* if submenu, able that
*/
if (item && HasSubmenu(mh,item))
{
mark = SubmenuId(mh,item);
EnableIf(GetMHandle(mark),0,expr);
}
return (result);
}
/**********************************************************************
* TextMenuOK - is it ok to show the text menu?
**********************************************************************/
Boolean TextMenuOK(MyWindowPtr win)
{
WindowPtr winWP = GetMyWindowWindowPtr(win);
if (!IsMyWindow(winWP)) return(False);
if (!win->pte) return(False);
if (PETESelectionLocked(PETE,win->pte,-1,-1)) return(False);
switch(GetWindowKind(winWP))
{
case COMP_WIN: return(!CompHeadCurrent(win->pte));
case MESS_WIN: return(win->pte==(*Win2MessH(win))->bodyPTE);
case TEXT_WIN: return(True);
default: return(False);
}
}
#pragma segment Ends
/************************************************************************
*
************************************************************************/
Boolean SameSettingsFile(short vRef,long dirId,UPtr name)
{
#pragma unused(dirId)
FSSpec spec;
if (GetFileByRef(SettingsRefN,&spec)) return(False);
return(vRef == Root.vRef && dirId == Root.vRef && StringSame(name,spec.name));
}
#pragma segment BuildMenus
/**********************************************************************
* NewMessageWith - start a new message with a bit of stationery
**********************************************************************/
OSErr NewMessageWith(short item)
{
MyWindowPtr win;
//Stationery - no support for this in Light
if (HasFeature (featureStationery)) {
win = DoComposeNew(nil);
if (!win) return(1);
ApplyIndexStationery(win,item,True,True);
ShowMyWindow(GetMyWindowWindowPtr(win));
}
return(0);
}
/**********************************************************************
*
**********************************************************************/
void TextMenuChoice(short menu, short item,short modifiers)
{
MyWindowPtr win = GetWindowMyWindowPtr (MyFrontWindow());
PETEHandle pte;
PETETextStyle ps;
PETEStyleEntry pse;
Str255 font;
MCEntryPtr mc;
PETEParaInfo pinfo;
long textValid=0;
long paraValid=0;
Boolean hasInsert;
long pStart, pStop;
Boolean clearGraphic = false;
pte = win ? win->pte : nil;
if (PeteIsValid(pte))
{
PeteGetTextAndSelection(pte,nil,&pStart,&pStop);
hasInsert = pStart==pStop;
PeteStyleAt(pte,(pStart==pStop)?kPETECurrentStyle:kPETECurrentSelection,&pse);
ps = pse.psStyle.textStyle;
switch(menu)
{
case TEXT_HIER_MENU:
if (item==tmPlain)
{
if (modifiers&optionKey)
{
PeteStyleAt(pte,kPETEDefaultStyle,&pse);
ps = pse.psStyle.textStyle;
textValid = peAllValid;
pinfo.tabHandle = nil;
PETEGetParaInfo(PETE,pte,kPETEDefaultPara,&pinfo);
paraValid = peAllParaValid & ~peTabsValid;
if (UseFlowOutExcerpt) paraValid &= ~peQuoteLevelValid;
clearGraphic = true;
}
else
{
ps.tsFace = 0;
textValid = bold|italic|underline|outline|shadow|condense|extend;
}
}
else if (item<tmBar1)
{
if (ps.tsFace&(1<<(item-2)))
ps.tsFace &= ~(1<<(item-2));
else
ps.tsFace |= 1<<(item-2);
textValid = (1<<(item-2));
}
else if (tmLeft<=item && item<=tmRight)
{
UseFeature (featureStyleJust);
pStart = pStop = -1; // use selection
PeteParaRange(pte,&pStart,&pStop);
PeteParaConvert(pte,pStart,pStop);
pinfo.justification = teFlushDefault;
paraValid = peJustificationValid;
switch(item)
{
case tmLeft:
pinfo.justification = teFlushLeft;
break;
case tmCenter:
pinfo.justification = teCenter;
break;
case tmRight:
pinfo.justification = teFlushRight;
break;
}
}
else if (item==tmQuote || item==tmUnquote) {
UseFeature (featureStyleQuote);
IncrementQuoteLevel(pte,-1,-1,item==tmQuote?1:-1);
}
else if (item==tmURL)
{
UseFeature (featureStyleLink);
InsertURL(pte);
return;
}
else if (item==tmRule)
{
UseFeature (featureStyleHorzRule);
PeteInsertRule(pte,-1,0,0,true,true,true);
return;
}
else if (item==tmGraphic)
{
CompAttach(win,true);
return;
}
break;
case TEXT_SIZE_HIER_MENU:
#ifdef USERELATIVESIZES
ps.tsSize = kPETERelativeSizeBase+item-tfbSizeNormal;
#else
ps.tsSize = IncrementTextSize(FontSize,item-tfbSizeNormal);
#endif
textValid = peSizeValid;
break;
case FONT_HIER_MENU:
GetMenuItemText(GetMHandle(FONT_HIER_MENU),item,font);
ps.tsFont = GetFontID(font);
if (ps.tsFont==FontID) ps.tsFont = kPETEDefaultFont;
#ifdef USEFIXEDDEFAULTFONT
if (ps.tsFont==FixedID) ps.tsFont = kPETEDefaultFixed;
#endif
textValid = peFontValid;
break;
case COLOR_HIER_MENU:
if (ThereIsColor)
{
UseFeature (featureStyleColor);
if (item==1 || !(mc = GetMCEntry(COLOR_HIER_MENU,item)))
DEFAULT_COLOR(ps.tsColor);
else
ps.tsColor = mc->mctRGB2;
textValid = peColorValid;
}
break;
case MARGIN_HIER_MENU:
pStart = pStop = -1; // use selection
PeteParaRange(pte,&pStart,&pStop);
PeteParaConvert(pte,pStart,pStop);
MarginMenuChoice(pte,item,&pinfo,&paraValid);
break;
}
}
if (!hasInsert && paraValid && textValid) PetePrepareUndo(pte,peUndoStyleAndPara,-1,-1,nil,nil);
if (clearGraphic) PeteClearGraphic(pte,-1,-1);
if (paraValid) PETESetParaInfo(PETE,pte,-1,&pinfo,paraValid);
if (textValid) PETESetTextStyle(PETE,pte,-1,-1,&ps,textValid);
if (!hasInsert && paraValid && textValid) PeteFinishUndo(pte,peUndoStyleAndPara,-1,-1);
PeteSetDirty(pte);
if (paraValid) PeteWhompHiliteRegionBecausePeteWontFixIt(pte);
if (textValid || paraValid) (*PeteExtra(pte))->quoteScanned = 0;
}
/**********************************************************************
* MarginMenuChoice - apply a margin style
**********************************************************************/
void MarginMenuChoice(PETEHandle pte,short item,PETEParaInfoPtr pinfo,long *paraValid)
{
PeteSaneMargin marg;
Str255 scratch;
short width = GetRLong(TAB_DISTANCE)*FontWidth;
MenuHandle mh = GetMHandle(MARGIN_HIER_MENU);
*paraValid = 0;
Zero(*pinfo);
PETEGetParaInfo(PETE,pte,-1,pinfo);
if (item==CountMenuItems(mh))
{
UseFeature (featureStyleBullet);
GetCurEditorMargins(pte,&marg);
if (pinfo->paraFlags & peListBits)
{
pinfo->paraFlags &= ~peListBits;
marg.first--;
marg.second--;
// It would look better right-indented, but Pete didn't do it that way
// marg.right--;
}
else
{
pinfo->paraFlags |= peDiskList;
marg.first++;
marg.second++;
// It would look better right-indented, but Pete didn't do it that way
// marg.right++;
}
*paraValid = peFlagsValid;
}
else
{
UseFeature (featureStyleMargin);
if (Ascii2Margin(GetRString(scratch,MarginStrn+item),nil,&marg)) return;
if (pinfo->paraFlags & peListBits)
{
marg.first++;
marg.second++;
marg.right++;
}
}
*paraValid |= peIndentValid|peStartMarginValid|peEndMarginValid;
PeteConvertMarg(pte,kPETEDefaultPara,&marg,pinfo);
}
/**********************************************************************
*
**********************************************************************/
void SetMenuTexts(short modifiers,Boolean allMenu)
{
WindowPtr winWP = MyFrontWindow();
MyWindowPtr win = GetWindowMyWindowPtr(winWP);
short kind = winWP?GetWindowKind(winWP) : 0;
Boolean option = (modifiers & optionKey)!=0;
Boolean shift = (modifiers & shiftKey)!=0;
Boolean command = (modifiers & cmdKey)!=0;
Boolean select = IsMyWindow(winWP) && win && win->hasSelection;
Str255 scratch, suffix;
MenuHandle mh;
Boolean all = PrefIsSet(PREF_REPLY_ALL);
Boolean turbo = PrefIsSet(PREF_TURBO_REDIRECT);
#ifdef IMAP
Boolean imap = IMAPExists();
TOCHandle tocH = nil;
if (win && kind == MBOX_WIN) tocH = (TOCHandle)GetMyWindowPrivateData(win);
#endif
/*
* check the mailbox represented by the topmost window
*/
CheckBox(win,allMenu);
#ifdef TWO
CheckState(win,allMenu,0);
CheckLabel(win,allMenu);
CheckPers(win,HasFeature(featureMultiplePersonalities)&&allMenu);
#endif
CheckTable(win,allMenu);
/*
* build the Windows menu
*/
BuildWindowsMenu(allMenu);
/*
* file menu
*/
mh = GetMHandle(FILE_MENU);
SetItemR(mh,FILE_SAVE_ITEM,option?SAVE_ALL_ITEXT:SAVE_ITEXT);
SetItemR(mh,FILE_CLOSE_ITEM,option?CLOSE_ALL_ITEXT:CLOSE_ITEXT);
SetItemR(mh,FILE_SAVE_AS_ITEM,shift&&kind==ALIAS_WIN?SAVE_AS_SEL_ITEXT:SAVE_AS_ITEXT);
SetItemR(mh,FILE_PRINT_ITEM,shift?PRINT_SEL_ITEXT:PRINT_ITEXT);
SetItemR(mh,FILE_SEND_ITEM,option?SEND_SPECIAL_ITEXT:SEND_ITEXT);
#ifdef IMAP
if (tocH && !option && shift && (*tocH)->imapTOC && !PrefIsSet(PREF_ALTERNATE_CHECK_MAIL_CMD))
GetRString(scratch,IMAP_CHECK_SPECIAL_ITEXT);
else
#endif
GetRString(scratch,option?CHECK_SPECIAL_ITEXT:CHECK_MAIL);
SetCheckItem(scratch);
/*
* edit menu
*/
mh = GetMHandle(EDIT_MENU);
SetItemR(mh,EDIT_COPY_ITEM,option?
(shift?COPY_UNWRAP_PLAIN_ITEXT:COPY_UNWRAP_ITEXT):
(shift?COPY_PLAIN_ITEXT:COPY_ITEXT));
SetItemR(mh,EDIT_PASTE_ITEM,(PrefIsSet(PREF_PASTE_PLAIN)?!shift:shift)?PASTE_PLAIN_ITEXT:PASTE_ITEXT);
SetItemR(mh,EDIT_WRAP_ITEM,option?UNWRAP_ITEXT:WRAP_ITEXT);
SetItemR(mh,EDIT_FINISH_ITEM,HasFeature(featureNicknameWatching)&&option?FINISH_EXP_ITEXT:FINISH_ITEXT);
SetItemR(mh,EDIT_INSERT_TO_ITEM,HasFeature(featureNicknameWatching)&&option?INSERT_EXP_ITEXT:INSERT_ITEXT);
#ifdef SPEECH_ENABLED
SetItemR(mh,EDIT_SPEAK_ITEM,shift?SPEAK_SEL_ITEXT:SPEAK_ITEXT);
#endif
SetMenuItemBasedOnFeature (mh, EDIT_FINISH_ITEM, featureNicknameWatching, -1);
SetMenuItemBasedOnFeature (mh, EDIT_SPEAK_ITEM, featureSpeak, -1);
SetMenuItemBasedOnFeature (mh, EDIT_ISPELL_HOOK_ITEM, featureSpellChecking, -1);
mh=GetMHandle(TEXT_HIER_MENU);
SetMenuItemBasedOnFeature (mh, tmQuote, featureStyleQuote, -1);
SetMenuItemBasedOnFeature (mh, tmUnquote, featureStyleQuote, -1);
SetMenuItemBasedOnFeature (mh, tmLeft, featureStyleJust, -1);
SetMenuItemBasedOnFeature (mh, tmCenter, featureStyleJust, -1);
SetMenuItemBasedOnFeature (mh, tmRight, featureStyleJust, -1);
SetMenuItemBasedOnFeature (mh, tmMargin, featureStyleMargin, -1);
SetMenuItemBasedOnFeature (mh, tmColor, featureStyleColor, -1);
SetMenuItemBasedOnFeature (mh, tmRule, featureStyleHorzRule, -1);
SetMenuItemBasedOnFeature (mh, tmGraphic, featureStyleGraphics, -1);
SetMenuItemBasedOnFeature (mh, tmURL, featureStyleLink, -1);
/*
* message menu
*/
mh = GetMHandle(MESSAGE_MENU);
GetRString(scratch,REPLY);
*suffix = 0;
if (shift) PCatR(suffix,REP_SELECTION);//select?REP_SELECTION:REP_NOSEL);
if (all!=option) PCatR(suffix,REP_ALL);
PCat(scratch,suffix);
SetMenuItemText(mh,MESSAGE_REPLY_ITEM,scratch);
if (HasFeature (featureStationery)) {
PCatR(scratch,REP_WITH);
SetMenuItemText(mh,MESSAGE_REPLY_WITH_ITEM,scratch);
}
SetMenuItemBasedOnFeature (mh, MESSAGE_JUNK_ITEM, featureJunk, -1);
SetMenuItemBasedOnFeature (mh, MESSAGE_NOTJUNK_ITEM, featureJunk, -1);
*scratch = 0;
if (turbo!=option) GetRString(scratch,TURBO);
PCatR(scratch,REDIRECT);
if ((turbo!=option) && shift) PCatR(scratch,TB_REDIR_NO_DEL);
PCatR(scratch,TO_ITEXT);
SetMenuItemText(mh,MESSAGE_REDIST_TO_ITEM,scratch);
SetItemR(mh,MESSAGE_QUEUE_ITEM,option?CHANGE_QUEUEING:
(PrefIsSet(PREF_AUTO_SEND)?SEND_M_ITEM:QUEUE_M_ITEM));
SetItemR(mh,MESSAGE_DELETE_ITEM,option&&shift?NUKE_ITEXT:DELETE_ITEXT);
SetMenuItemBasedOnFeature (mh, MESSAGE_NEW_WITH_ITEM, featureStationery, -1);
SetMenuItemBasedOnFeature (mh, MESSAGE_REPLY_WITH_ITEM, featureStationery, -1);
/*
* special
*/
mh = GetMHandle(SPECIAL_MENU);
SetItemR(mh,AdjustSpecialMenuItem(SPECIAL_MAKE_NICK_ITEM),
shift&&select?MAKE_SEL_NICK_ITEXT:MAKE_NICK_ITEXT);
SetItemR(mh,AdjustSpecialMenuItem(SPECIAL_SORT_ITEM),option?SORT_DESCEND_ITEXT:SORT_ITEXT);
#ifdef THREADING_ON
#ifndef BATCH_DELIVERY_ON
SetItemR(mh,AdjustSpecialMenuItem(SPECIAL_FILTER_ITEM),option?FILTER_WAITING_ITEXT:FILTER_ITEXT);
#endif
#endif
#ifdef IMAP
// an imap personality exists
if (imap)
{
// There's a frontmost window, and it's a mailbox
if (tocH)
{
// if fancy trash is off for this mailbox, use the REMOVE_DELETED_MESSAGE string
if ((*tocH)->imapTOC && !FancyTrashForThisPers(tocH))
{
SetItemR(mh,AdjustSpecialMenuItem(SPECIAL_TRASH_ITEM),(option&!shift?IMAP_REMOVE_DELETED_MESSAGES_ITEXT:IMAP_EMPTY_TRASH));
}
else
{
// fancy trash is on, or the frontmost mailbox is a pop mailbox ...
short text = (*tocH)->imapTOC ? IMAP_EMPTY_CURRENT_TRASH : IMAP_EMPTY_LOCAL_TRASH;
SetItemR(mh,AdjustSpecialMenuItem(SPECIAL_TRASH_ITEM),(shift&!option?text:(option&!shift?IMAP_EMPTY_REMOTE_TRASH:IMAP_EMPTY_TRASH)));
}
}
else
{
// There's no toc frontmost. Use "Empty Trash for Selected Personalities" if we ought to
SetItemR(mh,AdjustSpecialMenuItem(SPECIAL_TRASH_ITEM),HasFeature(featureMultiplePersonalities)&&DoWeUseSelectedIMAPPersonalities()?IMAP_EMPTY_PERS_TRASH:IMAP_EMPTY_TRASH);
// if option is pressed, but not shift, use "Empty All Trash Mailoxes"
if (option && !shift) SetItemR(mh,AdjustSpecialMenuItem(SPECIAL_TRASH_ITEM),IMAP_EMPTY_REMOTE_TRASH);
}
}
#endif
// Use special items for change/forget password if personalities window is open
if ( ChangePWMenuShown ())
SetItemR(mh,AdjustSpecialMenuItem(SPECIAL_CHANGE_ITEM),HasFeature(featureMultiplePersonalities)&&DoWeUseSelectedPersonalities()?CHANGE_PERS_PW:CHANGE_PW);
SetItemR(mh,AdjustSpecialMenuItem(SPECIAL_FORGET_ITEM),HasFeature(featureMultiplePersonalities)&&DoWeUseSelectedPersonalities()?FORGET_PERS_PW:FORGET_PW);
// Enable plugin special menu items for current user state
ETLEnableSpecialItems();
/*
* text?
*/
CheckTextItems(win,modifiers,allMenu); //Styled Text - don't allow user to compose or send styled text
/*
* windows menu
*/
mh = GetMHandle (WINDOW_MENU);
SetMenuItemBasedOnFeature (mh, WIN_PERSONALITIES_ITEM, featureMultiplePersonalities, 1);
SetMenuItemBasedOnFeature (mh, WIN_STATIONERY_ITEM, featureStationery, 1);
SetMenuItemBasedOnFeature (mh, WIN_LINK_ITEM, featureLink, 1);
SetMenuItemBasedOnFeature (mh, WIN_STATISTICS_ITEM, featureStatistics, 1);
SetMenuItemBasedOnFeature (mh, WIN_DRAWER_ITEM, featureMBDrawer, 1);
// contextual search
if (mh = GetMHandle(FIND_HIER_MENU))
{
Str255 mItemStr;
// for now, we just search the web
GetRString(suffix,SEARCH_FOR_WEB);
// if we have a string, show it in the menu
if (win && win->pte && !AttIsSelected(nil,win->pte,-1,-1,0,nil,nil) && *PeteSelectedString(scratch,win->pte) && !IsAllLWSP(scratch))
{
CollapseLWSP(scratch);
*scratch = MIN(*scratch,63);
ComposeRString(mItemStr,SEARCH_FOR_FMT,suffix,scratch);
}
// if no string, just say search web
else
ComposeRString(mItemStr,SEARCH_NOTHING_FMT,SEARCH_FOR_WEB);
// update the item
SetMenuItemText(mh,FIND_SEARCH_WEB_ITEM,mItemStr);
}
SetWindowPropMenu(win,false,false,checkMark,modifiers);
#ifdef DEBUG
CheckCurrentAd();
#endif
}
/**********************************************************************
* CheckTextItems - check the appropriate items in the text menu & submenus
**********************************************************************/
void CheckTextItems(MyWindowPtr win,short modifiers,Boolean all)
{
PETETextStyle ps;
PETEStyleEntry pse;
MenuHandle mh;
Str255 fontName;
short item;
PETEParaInfo pinfo;
mh = GetMHandle(TEXT_HIER_MENU);
CheckNone(mh);
if (!TextMenuOK(win)) return;
PeteStyleAt(win->pte,kPETECurrentStyle,&pse);
ps = pse.psStyle.textStyle;
if (ps.tsSize==kPETEDefaultSize) ps.tsSize = FontSize;
if (ps.tsFont==kPETEDefaultFont) ps.tsFont = FontID;
#ifdef USEFIXEDDEFAULTFONT
if (ps.tsFont==kPETEDefaultFixed) ps.tsFont = FixedID;
#endif
if (!ps.tsFace)
{
if (!(modifiers&optionKey)) SetItemMark(mh,tmPlain,checkMark);
}
else
{
if (ps.tsFace&bold) SetItemMark(mh,tmBold,checkMark);
if (ps.tsFace&italic) SetItemMark(mh,tmItalic,checkMark);
if (ps.tsFace&underline) SetItemMark(mh,tmUnderline,checkMark);
}
SetItemR(mh,tmPlain,
(modifiers&optionKey)?PLAIN_ALL_ITEM:PLAIN_TEXT_MITEM);
mh = GetMHandle(TEXT_SIZE_HIER_MENU);
#ifdef USERELATIVESIZES
if(ps.tsSize < 0)
item = ps.tsSize - kPETERelativeSizeBase;
else
#endif
item = FindSizeInc(ps.tsSize)-FindSizeInc(FontSize);
if (item<-3) item = -3;
else if (item>3) item = 3;
CheckNone(mh);
SetItemMark(mh,tfbSizeNormal+item,checkMark);
mh = GetMHandle(FONT_HIER_MENU);
CheckNone(mh);
GetFontName(ps.tsFont,fontName);
if (item=FindItemByName(mh,fontName))
SetItemMark(mh,item,checkMark);
Zero(pinfo);
PETEGetParaInfo(PETE,win->pte,-1,&pinfo);
mh = GetMHandle(MARGIN_HIER_MENU);
SetItemMark(mh,CountMenuItems(mh),(pinfo.paraFlags & peListBits) ? checkMark:0);
}
/************************************************************************
* SetQItemText - set the text of the Queue For Delivery menu item
************************************************************************/
void SetQItemText(MyWindowPtr win)
{
WindowPtr winWP = GetMyWindowWindowPtr (win);
TOCHandle tocH = nil;
int sumNum = -1;
if (GetWindowKind(winWP)==COMP_WIN)
{
tocH = (*(MessHandle)GetMyWindowPrivateData(win))->tocH;
sumNum = (*(MessHandle)GetMyWindowPrivateData(win))->sumNum;
}
else if (GetWindowKind(winWP)==CBOX_WIN)
{
tocH = (TOCHandle)GetMyWindowPrivateData(win);
for (sumNum=0;sumNum<(*tocH)->count;sumNum++)
if ((*tocH)->sums[sumNum].selected) break;
}
if (tocH && sumNum >= 0 && sumNum < (*tocH)->count)
{
#ifdef THREADING_ON
if ((*tocH)->sums[sumNum].state==SENT || ((*tocH)->sums[sumNum].state==BUSY_SENDING))
#else
if ((*tocH)->sums[sumNum].state==SENT)
#endif
{
DisableItem(GetMHandle(MESSAGE_MENU),MESSAGE_QUEUE_ITEM);
DisableItem(GetMHandle(CHANGE_HIER_MENU),CHANGE_QUEUEING_ITEM);
}
else
{
EnableItem(GetMHandle(MESSAGE_MENU),MESSAGE_QUEUE_ITEM);
EnableItem(GetMHandle(CHANGE_HIER_MENU),CHANGE_QUEUEING_ITEM);
}
}
}
/**********************************************************************
* CheckTable - check the proper translit table
**********************************************************************/
void CheckTable(MyWindowPtr win,Boolean all)
{
MenuHandle mh = GetMHandle(TABLE_HIER_MENU);
TOCHandle tocH;
Boolean isOut = False;
short tableId;
if (all && mh)
{
EnableItem(GetMHandle(CHANGE_HIER_MENU),CHANGE_TABLE_ITEM);
CheckNone(mh);
return;
}
if (win && mh && NewTables)
{
switch (GetWindowKind(GetMyWindowWindowPtr (win)))
{
case COMP_WIN:
isOut = True;
case MESS_WIN:
tableId = SumOf(Win2MessH(win))->tableId;
break;
case CBOX_WIN:
isOut = True;
case MBOX_WIN:
if (!win->hasSelection && !all)
{
DisableItem(GetMHandle(CHANGE_HIER_MENU),CHANGE_TABLE_ITEM);
return;
}
else
{
tocH = (TOCHandle)GetMyWindowPrivateData(win);
tableId = (*tocH)->sums[FirstMsgSelected(tocH)].tableId;
}
}
TrashMenu(mh,1);
AddXlateTables(isOut,tableId,False,mh);
EnableItem(GetMHandle(CHANGE_HIER_MENU),CHANGE_TABLE_ITEM);
}
else if (mh) DisableItem(GetMHandle(CHANGE_HIER_MENU),CHANGE_TABLE_ITEM);
}
#ifdef TWO
/************************************************************************
* CheckLabel - put a check next to the current message's label
************************************************************************/
void CheckLabel(MyWindowPtr win,Boolean all)
{
WindowPtr winWP = GetMyWindowWindowPtr (win);
MenuHandle mh = GetMHandle(LABEL_HIER_MENU);
short n;
if (!mh) return;
/*
* uncheck old one
*/
CheckNone(mh);
if (all) return;
if (IsMyWindow(winWP))
{
MessHandle messH = (MessHandle) GetMyWindowPrivateData(win);
TOCHandle tocH = (TOCHandle) GetMyWindowPrivateData(win);
/*
* set n to current color
*/
n = REAL_BIG;
if (IsMessWindow(winWP))
n = SumColor(SumOf(messH));
else if (GetWindowKind(winWP)==MBOX_WIN && win->hasSelection)
{
n = FirstMsgSelected(tocH);
n = GetSumColor(tocH,n);
}
else return;
/*
* turn into item number
*/
n = Label2Menu(n);
/*
* mark it
*/
SetItemMark(mh,n,checkMark);
}
}
/************************************************************************
* CheckState - put a check next to the current message's state
************************************************************************/
void CheckState(MyWindowPtr win,Boolean all,short origItem)
{
WindowPtr winWP = GetMyWindowWindowPtr (win);
MenuHandle mh = GetMHandle(STATE_HIER_MENU);
MessHandle messH = win?(MessHandle) GetMyWindowPrivateData(win):nil;
TOCHandle tocH = win?(TOCHandle) GetMyWindowPrivateData(win):nil;
short n;
Boolean out=False;
short kind = winWP ? GetWindowKind(winWP) : 0;
/*
* uncheck old one
*/
CheckNone(mh);
for (n=CountMenuItems(mh);n;n--)
if (n!=statmBar) EnableItem(mh,n);
DisableItem(mh,statmUnsendable);
DisableItem(mh,statmTimed);
DisableItem(mh,statmBusySending);
if (all)
{
EnableItem(mh,0);
return;
}
if (IsMyWindow(winWP))
{
/*
* set n to current state
*/
n = 0;
if (kind==MESS_WIN || kind==COMP_WIN)
{
n = SumOf(messH)->state;
EnableItem(mh,0);
out = kind==COMP_WIN;
}
else if ((kind==MBOX_WIN || kind==CBOX_WIN) && win->hasSelection)
{
n = (*tocH)->sums[FirstMsgSelected(tocH)].state;
EnableItem(mh,0);
out = kind==CBOX_WIN;
}
else
{
DisableItem(mh,0);
return;
}
/*
* check the appropriate item
*/
if (n>0) SetItemMark(mh,Status2Item(n),checkMark);
/*
* disable the appropriate items
*/
if (!out || n==SENT)
{
DisableItem(mh,statmSendable);
DisableItem(mh,statmQueued);
}
}
else SetItemMark(mh,origItem,diamondChar);
}
#endif
/************************************************************************
* CheckPrior - put a check next to the current message's priority
************************************************************************/
void CheckPrior(MyWindowPtr win,Boolean all)
{
WindowPtr winWP = GetMyWindowWindowPtr (win);
MenuHandle mh = GetMHandle(PRIOR_HIER_MENU);
MessHandle messH = win?(MessHandle) GetMyWindowPrivateData(win):nil;
TOCHandle tocH = win?(TOCHandle) GetMyWindowPrivateData(win):nil;
short n;
/*
* uncheck old one
*/
EnableItem(mh,0);
CheckNone(mh);
if (all)
{
EnableItem(mh,pymLower);
EnableItem(mh,pymRaise);
return;
}
if (IsMyWindow(winWP))
{
/*
* set n to current state
*/
n = REAL_BIG;
if (IsMessWindow(winWP))
n = Prior2Display(SumOf(messH)->priority);
else if (GetWindowKind(winWP)==MBOX_WIN && win->hasSelection)
{
n = FirstMsgSelected(tocH);
n = Prior2Display((*tocH)->sums[n].priority);
}
else return;
/*
* mark it
*/
if (n) SetItemMark(mh,n,checkMark);
EnableIf(mh,pymLower,n!=pymLowest);
EnableIf(mh,pymRaise,n!=pymHighest);
}
}
/**********************************************************************
* CheckBox - check the topmost mailbox, and disable in transfer menu
**********************************************************************/
void CheckBox(MyWindowPtr win,Boolean all)
{
WindowPtr winWP = GetMyWindowWindowPtr (win);
TOCHandle tocH;
Str31 name;
short n;
FSSpec spec;
if (CheckedMenu && CheckedItem)
{
SetItemMark(CheckedMenu,CheckedItem,0);
CheckedMenu = nil;
}
if (all) return;
if (!IsMyWindow(winWP)) return;
if (GetWindowKind(winWP)==MBOX_WIN)
tocH = (TOCHandle) GetMyWindowPrivateData(win);
else if (GetWindowKind(winWP)==MESS_WIN)
tocH = (*(MessHandle) GetMyWindowPrivateData(win))->tocH;
else
{
if (GetWindowKind(winWP)==CBOX_WIN ||
GetWindowKind(winWP)==COMP_WIN)
SetItemMark(CheckedMenu=GetMHandle(MAILBOX_MENU),
CheckedItem=MAILBOX_OUT_ITEM,checkMark);
return;
}
if ((*tocH)->which==IN)
SetItemMark(CheckedMenu=GetMHandle(MAILBOX_MENU),
CheckedItem=MAILBOX_IN_ITEM,checkMark);
else if ((*tocH)->which==TRASH)
SetItemMark(CheckedMenu=GetMHandle(MAILBOX_MENU),
CheckedItem=MAILBOX_TRASH_ITEM,checkMark);
else if ((*tocH)->which==OUT)
SetItemMark(CheckedMenu=GetMHandle(MAILBOX_MENU),
CheckedItem=MAILBOX_OUT_ITEM,checkMark);
else if ((*tocH)->which==JUNK)
SetItemMark(CheckedMenu=GetMHandle(MAILBOX_MENU),
CheckedItem=MAILBOX_JUNK_ITEM,checkMark);
else
{
spec = GetMailboxSpec(tocH,-1);
if ((*tocH)->imapTOC) // look for enclosing folder if this is an IMAP cache mailbox
{
short menu, item;
if (noErr==Spec2Menu(&spec, false, &menu, &item))
{
CheckedMenu=GetMHandle(menu?menu:MAILBOX_MENU);
CheckedItem=item;
SetItemMark(CheckedMenu,CheckedItem,checkMark);
}
}
else if (0<=(n=FindDirLevel(spec.vRefNum,spec.parID)))
{
PCopy(name,spec.name);
CheckedMenu=GetMHandle(n?n:MAILBOX_MENU);
CheckedItem=FindItemByName(CheckedMenu,name);
SetItemMark(CheckedMenu,CheckedItem,checkMark);
}
}
}
/**********************************************************************
*
**********************************************************************/
void InsertSystemConfig(PETEHandle pte)
{
Accumulator a;
long start;
if (!AccuInit(&a) && !AddConfig(&a,False))
{
CompReallyPreferBody((*PeteExtra(pte))->win);
PetePrepareUndo(pte,peUndoPaste,-1,-1,&start,nil);
if (PETEInsertText(PETE,pte,-1,a.data,nil))
{
AccuZap(a);
PeteKillUndo(pte);
}
else PeteFinishUndo(pte,peUndoPaste,start,-1);
}
}
/************************************************************************
* SetCheckItem - put the time of the next mail check in the Check Mail
* item.
************************************************************************/
void SetCheckItem(PStr item)
{
short n;
uLong checkTicks = PersCheckTicks();
if (checkTicks && AutoCheckOK())
{
checkTicks = MAX(checkTicks,TickCount()+3600);
PCat(item,"\p ");
n = *item+1;
TimeString((LocalDateTime()-TickCount()/60)+checkTicks/60,False,item+n,nil);
item[0] += item[n]+1;
item[n] = '(';
PCatC(item,')');
}
SetMenuItemText(GetMHandle(FILE_MENU),FILE_CHECK_ITEM,item);
}
/************************************************************************
* InsertRecipient - insert a given recipient in a window
************************************************************************/
void InsertRecipient(MyWindowPtr win, short which,Boolean all)
{
Str63 scratch;
long start;
NicknameWatcherFocusChange (win->pte); /* MJN */
//Undo.didClick=True;
PetePrepareUndo(win->pte,peCantUndo,-1,-1,&start,nil);
InsertCommaIfNeedBe(win->pte,nil);
MyGetItem(GetMHandle(NEW_TO_HIER_MENU),which,scratch);
PeteInsertPtr(win->pte,-1,scratch+1,*scratch);
if (all && HasNickExpansion (win->pte))
// if (all && ((*PeteExtra(win->pte))->nick.fieldCheck ? (*(*PeteExtra(win->pte))->nick.fieldCheck) (win->pte) : HasNickExpansion (win->pte)))
FinishAlias(win->pte,all,False, true);
PeteFinishUndo(win->pte,peUndoPaste,start,-1);
// NicknameWatcherMaybeModifiedField (win->pte); /* MJN */
}
/************************************************************************
* BuildWindowsMenu
************************************************************************/
void BuildWindowsMenu(Boolean allMenu)
{
Str255 title;
WindowPtr winWP;
MyWindowPtr win;
MenuHandle mh = GetMHandle(WINDOW_MENU);
RGBColor color;
if (mh)
{
TrashMenu(mh,WIN_LIMIT);
for (winWP=FrontWindow();winWP;winWP=GetNextWindow(winWP))
if (WinWPWindowsMenuEligible(winWP))
{
win = GetWindowMyWindowPtr (winWP);
GetWTitle(winWP,title);
if (*title>31)
{
*title = 31;
title[31] = '<EFBFBD>';
}
MyAppendMenu(mh,title);
if (allMenu) DisableItem(mh,CountMenuItems(mh));
if (GetWindowKind(winWP)==COMP_WIN)
SetItemStyle(mh,CountMenuItems(mh),italic);
if (IsMyWindow(winWP) && ThereIsColor && win->label)
SetMenuColor(mh,CountMenuItems(mh),GetLabelColor(win->label,&color));
if (GetWindowKind(winWP)==MBOX_WIN || GetWindowKind(winWP)==CBOX_WIN)
{
if ((*(TOCHandle)GetMyWindowPrivateData(win))->unread) SetItemStyle(mh,CountMenuItems(mh),UnreadStyle);
}
}
}
}
/************************************************************************
* TrashMenu - get rid of a menu, beginning at a particular item
************************************************************************/
void TrashMenu(MenuHandle mh, short beginAtItem)
{
short count,id,item;
MenuHandle subMh;
Byte type;
Handle oldSuite;
if (!mh) return;
for (count=CountMenuItems(mh),item=beginAtItem?beginAtItem:1;item<=count;item++)
{
oldSuite = nil;
if (!GetMenuItemIconHandle(mh,item,&type,&oldSuite) && type==kMenuIconSuiteType && oldSuite)
DisposeIconSuite(oldSuite,true);
if (HasSubmenu(mh,item))
{
id = SubmenuId(mh,item);
subMh = GetMHandle(id);
TrashMenu(subMh,0);
SetItemCmd(mh,item,0);
DeleteMenu(id);
DisposeMenu(subMh);
}
}
if (beginAtItem>0)
while (count>=beginAtItem) DeleteMenuItem(mh,count--);
}
#ifdef USECMM
#pragma mark -
#pragma mark ---CMM Stuff---
/*************************************CMM Stuff ***************************************************/
/************************************************************************************************
What's left to do with implementing the Contextual Menu Manager?
Here's the scoop:
First, to turn CMM use on, you need to define USECMM in conf.h
Within the contextual menu, there are two groups of items:
1> There are universal, non-context-specific (but hopefully unversally relevant) items which are
always present in the contextual menu.
2> There are context-specific items which are present depending on where the context click
occurs and conditions at the time of the click.
Implementation of the first group is pretty much done. Which items are included in this group
may be easily adjust by editing the static array called 'basicCMenuInfo', which is defined at the
top of the DoHandleContextualMenuClick function. This array is a list of items to be added to
the contextual menu, designated by menu id and menu item number. The list is terminated by an
entry whose menu id is CONTEXT_MENU and whose item number is CONTEXT_TERM_ITEM.
Implementation of the second group is only just begun. The framework is as follows:
I added a field to the MyWindowStruct data structure called buildCMenu. buildCMenu is a pointer
to a function whic should describe which context-specific items to add for a context click in
that window. Two examples below for the Message and Composition window are MessBuildCMenu and
CompBuildCMenu. If buildCMenu is nil for a window, then no context-specific menu items are shown
for context clicks in that window.
In addition, the general case of selecting text in a window and then context-clicking in that
window has not been addressed yet. Once this is addressed, several items from the edit menu
should be appended to any context-specific menu. The function to append these menu items has
already been written, though it is not called anywhere just yet. It is the AppendEditCMenu
function below and should be passed the handle-style array of context-specific items for a window
once that array has been created and it is deemed that text is selected.
One final note is that selected items in general need to be passed through the contextual menu
manager's facilities for processing various pre-defined data types (i.e. Apple Data Detectors).
This is the superset of the text selection situation described in the paragraph above. This can
be acocmplished by passing the appropriate AEDesc to the ContextualMenuSelect function, where I
am presently passing a nil.
Known problems:
couldn't figure out how to detect if a context-click had occurred in the toolbar, so when a
context-click occurs there, the current front window is deactivated and I attempt to make the
toolbar the currently active window. Obviously, this is not an especially good thing, but I'm
sure it is easy to fix for someone with a more thorough understanding of the source than I have.
-- Forest Hill 1/27/98 <mailto:alm_hillf@carleton.edu>
************************************************************************************************/
void HandleContextualMenuClick( WindowPtr topWinWP, EventRecord* event )
{
switch( DoHandleContextualMenuClick( topWinWP, event ) )
{
case noErr:
case userCanceledErr:
break;
default:
SysBeep( 10 );
}
}
/************************************************************************************************
DoHandleContextualMenuClick - handles contextual menu click events. Needs to be passed pointers
to the top window and to the contextual menu click event.
************************************************************************************************/
OSStatus DoHandleContextualMenuClick( WindowPtr topWinWP, EventRecord* event )
{
MyWindowPtr win;
MyWindowPtr topWin;
WindowPtr winWP; //window where the click happened
OSStatus err = noErr; //for returning errors
UInt32 outSelectionType; //what type of selection happened in the contextual menu?
SInt16 outMenuID; //which menu was the item selected from (probably the contextual menu)
UInt16 menuItem; //which item was selected
short winPart; //which part of a window did the click occur in?
MenuHandle contextMenu; //handle to the ocntextual menu
uLong res; // result of menu select
AEDesc selectionDesc;
MenuHandle mh; // handle to the menu that contains the selected item
NullADList(&selectionDesc,nil);
//which window (and part) did the click occur in?
winPart = FindWindow_( event->where, &winWP );
//if it wasn't the current top window, then makeit so
if( winWP != topWinWP )
{
if( winWP )
{
SelectWindow_( winWP );
UsingWindow( winWP );
UpdateMyWindow(winWP);
NotUsingWindow( winWP );
}
topWinWP = winWP;
}
//make sure menu items are correctly enabled and disabled, and that the texts are correct
EnableMenus(winWP,false);
EnableMenuItems(false);
SetMenuTexts(CurrentModifiers(),false);
//down, boy!
//scamwatch was leaving its tooltip up over the menu
MyHMHideTag();
//create the contextual menu
contextMenu = NewMenu( CONTEXT_MENU, "\p" );
if( !contextMenu ) return( MemError() );
//insert it as a hierarchical menu
InsertMenu( contextMenu, hierMenu );
#ifdef USECMM_BAD
//build the basic menu items
err = BuildBasicContextMenu( contextMenu );
if( err ){ goto oops; }
#endif
//we are now using this window! nobody else touch it!
UsingWindow( topWinWP );
//add on the context-specific menus, if there are any
topWin = GetWindowMyWindowPtr (topWinWP);
if (IsMyWindow(topWinWP) && topWin && topWin->buildCMenu)
err = (*topWin->buildCMenu)(topWin,event,contextMenu);
if( err ) goto oops;
//add edit items, if any
ASSERT(topWin);
if (topWin)
{
err = AppendEditItems(topWin,event,contextMenu);
if( err ){ goto oops; }
}
// got some text?
//err = CreateTEHObj(topWinWP,&selectionDesc);
win = GetWindowMyWindowPtr (winWP);
if (IsMyWindow(topWinWP) && win && win->pte)
{
long startSel, endSel;
Handle text;
PeteGetTextAndSelection(win->pte,&text,&startSel,&endSel);
err = AECreateDesc(typeChar,LDRef(text)+startSel,endSel-startSel,&selectionDesc);
UL(text);
}
else err = errAENoSuchObject;
MightSwitch();
//display the menu and allow the user to select items from it
err = ContextualMenuSelect( contextMenu, event->where, false, kCMHelpItemNoHelp, "\p", err ? nil: &selectionDesc,
&outSelectionType, &outMenuID, &menuItem );
AfterSwitch();
if( err ) goto oops;
// In which menu does the selected item actually live in?
mh = GetMenuHandle(outMenuID);
//respond to the item selected, if any
switch( outSelectionType )
{
case kCMNothingSelected:
case kCMShowHelpSelected:
break;
//if a menu items was selected
case kCMMenuItemSelected:
GetMenuItemCommandID(mh,menuItem,&res);
if (MailboxKindaMenu((res>>16)&0xffff,res&0xffff,nil,nil)) UseFeature(featureContextualFiling);
DoMenu(topWinWP, res, event->modifiers);
break;
}
oops:
//we're done using the window
NotUsingWindow( topWinWP );
//get rid of the contextual menu
DeleteMenu( CONTEXT_MENU );
DisposeMenu( contextMenu );
DisposeADList(&selectionDesc,nil);
return( err );
}
#ifdef NEVER
/************************************************************************************************
BuildBasicContextMenu - builds the basic universal-items-only contextual menu, given an array of
CMenuInfo's whose last element contains the values CONTEXT_MENU and CONTEXT_TERM_ITEM.
************************************************************************************************/
OSStatus BuildBasicContextMenu( MenuHandle contextMenu, CMenuInfo* basicCMenuInfo )
{
MenuHandle srcMenu; //source menu for desired items to add to contextual menu
short i, //counter
startItems; //number of items in the menu to begin with
Str255 itemString; //string for transfering menu items to contextual menu
//find out how many items there are to begin with ( most likely 0 )
startItems = CountMenuItems( contextMenu );
//walk through until we get to the CONTEXT_TERM_ITEM
for( i=0; !( basicCMenuInfo[i].srcMenuID == CONTEXT_MENU && basicCMenuInfo[i].srcMenuItem == CONTEXT_TERM_ITEM ); i++ )
{
//get a handle to the specified source menu for this item
srcMenu = GetMenuHandle( basicCMenuInfo[i].srcMenuID );
if( !srcMenu ) return( nilHandleErr );
//if it's a separator item, then add a separator
if( basicCMenuInfo[i].srcMenuID == CONTEXT_MENU && basicCMenuInfo[i].srcMenuItem == CONTEXT_SEPARATOR_ITEM )
AppendMenu( contextMenu, "\p-" );
//otherwise, add the specific item
else
{
//get the text for the desired item
GetMenuItemText( srcMenu, basicCMenuInfo[i].srcMenuItem, itemString );
//add a new item to the context menu
AppendMenu( contextMenu, "\pitem" );
//set the text for the new menu item
SetMenuItemText( contextMenu, startItems+i+1, itemString );
//if the item in the original menu is disabled, then disable the item in the context menu also
if( basicCMenuInfo[i].srcMenuItem < 32 && !( (**srcMenu).enableFlags & ( 0x00000001 << basicCMenuInfo[i].srcMenuItem ) ) )
DisableItem( contextMenu, startItems+i+1 );
}
}
//we had no problems
return( noErr );
}
#endif
#pragma mark -
#ifdef USECMM_BAD
/************************************************************************************************
AppendEditCMenu - appends items from the edit menu to a CMenuInfo handle-style array. THIS CALL
IS NOT IN USE UNTIL TEXT-SENSITIVE CONTEXTS CAN BE DISCERNED.
************************************************************************************************/
OSStatus AppendEditCMenu( CMenuInfoHndl* specCMenuInfo )
{
short numItems, //number of items to add to the contextual menu
start; //starting point in the CMenuInfo list
OSStatus err; //for returning errors
static CMenuInfo editCMInfo[] = //items to add to the contextual menu list
{ CONTEXT_MENU, CONTEXT_SEPARATOR_ITEM, //separator line
EDIT_MENU, EDIT_CUT_ITEM, //"cut" item
EDIT_MENU, EDIT_COPY_ITEM, //"copy" item
EDIT_MENU, EDIT_PASTE_ITEM, //"paste" item
EDIT_MENU, EDIT_QUOTE_ITEM, //"paste as quotation" item
EDIT_MENU, EDIT_CLEAR_ITEM, //"clear" item
EDIT_MENU, EDIT_SELECT_ITEM, //"select all" item
EDIT_MENU, EDIT_WRAP_ITEM, //"wrap selection" item
CONTEXT_MENU, CONTEXT_TERM_ITEM }; //item to mark end of array
//make sure we got a valid handle-array to begin with
if( !(*specCMenuInfo) )
return( nilHandleErr );
//count how many items there are to be added
for( numItems=0; !( editCMInfo[numItems].srcMenuID == CONTEXT_MENU && editCMInfo[numItems].srcMenuItem == CONTEXT_TERM_ITEM ); numItems++ )
;
//figure out where to start adding items in the array
for( start=0; !( (**specCMenuInfo)[start].srcMenuID == CONTEXT_MENU && (**specCMenuInfo)[start].srcMenuItem == CONTEXT_TERM_ITEM ); start++ )
;
//adjust the size of the array
SetHandleSize( (Handle)*specCMenuInfo, GetHandleSize( (Handle)*specCMenuInfo ) + sizeof( CMenuInfo ) * ( numItems + 1 ) );
err = MemError(); if( err ) return( err );
//add the items to the list
BlockMove( editCMInfo, &(**specCMenuInfo)[start], numItems+1 );
return( noErr );
}
#endif
#endif
/************************************************************************
* MyEnableItem - override EnableItem to support > 31 items if available
************************************************************************/
#undef EnableItem
void MyEnableItem(MenuHandle mh,short item)
{
EnableMenuItem(mh,item);
}
/************************************************************************
* MyDisableItem - override DisableItem to support > 31 items if available
************************************************************************/
#undef DisableItem
void MyDisableItem(MenuHandle mh,short item)
{
DisableMenuItem(mh,item);
}
#define DisableItem MyDisableItem
/************************************************************************
* AddSelectionAsTo - add the current selection to the recipient menus
************************************************************************/
void AddSelectionAsTo(void)
{
MyWindowPtr win = GetWindowMyWindowPtr (FrontWindow_());
Str255 scratch;
if (!win->pte) return;
AddStringAsTo(PeteSelectedString(scratch,win->pte));
}
/************************************************************************
* AddStringAsTo - add a string to the recipient menus
************************************************************************/
void AddStringAsTo(UPtr string)
{
short spot,result;
MenuHandle mh;
Str127 oldItem;
short menu;
if (EmptyRecip) spot = 1;
else
{
mh = GetMHandle(NEW_TO_HIER_MENU);
for (spot=1;spot<=CountMenuItems(mh);spot++)
{
MyGetItem(mh,spot,oldItem);
result = StringComp(string,oldItem);
if (result==0) return;
if (result<0) break;
}
}
for (menu=NEW_TO_HIER_MENU;menu<=INSERT_TO_HIER_MENU;menu++)
{
if (EmptyRecip) DeleteMenuItem(GetMHandle(menu),1);
MyInsMenuItem(GetMHandle(menu),string,spot-1);
}
EmptyRecip = False;
ToMenusChanged();
}
/************************************************************************
* RemoveFromTo - remove something from the recipient menus
************************************************************************/
void RemoveFromTo(UPtr name)
{
short menu,item;
if (item=BinFindItemByName(GetMHandle(NEW_TO_HIER_MENU),name))
{
EmptyRecip = CountMenuItems(GetMHandle(NEW_TO_HIER_MENU))==1;
for (menu=NEW_TO_HIER_MENU;menu<=INSERT_TO_HIER_MENU;menu++)
if (EmptyRecip)
{
SetItemR(GetMHandle(menu),item,NO_RECIPS);
DisableMenuItem(GetMHandle(menu),item);
}
else DeleteMenuItem(GetMHandle(menu),item);
ToMenusChanged();
}
}
/************************************************************************
* ToMenusChanged - see that the recipient menus get written out
************************************************************************/
void ToMenusChanged(void)
{
SaveRecipMenu(GetMenuHandle(NEW_TO_HIER_MENU));
}
/**********************************************************************
* FixRecipMenu - fix old recip menus
**********************************************************************/
void FixRecipMenu(void)
{
MenuHandle mh = GetMHandle(NEW_TO_HIER_MENU);
Str255 str, scratch;
short item;
Str31 verboten;
UPtr key, spot, end;
Str31 nickname, candidate;
short digit;
Handle h;
Boolean changed = False;
GetRString(verboten,ALIAS_VERBOTEN);
end = verboten+*verboten+1;
if (!RegenerateAllAliases(False) && !EmptyRecip)
{
for (item=CountMenuItems(mh);item;item--)
{
MyGetItem(mh,item,str);
for (key=str+1;key<=str+*str;key++)
for (spot=verboten+1;spot<end;spot++)
if (*spot==*key)
{
PSCopy(scratch,str);
BeautifyFrom(scratch);
SanitizeFN(nickname,scratch,NICK_BAD_CHAR,NICK_REP_CHAR,false);
digit = 0;
if (IsAnyNickname(nickname))
{
*nickname = MIN(27,*nickname);
do
{
NumToString(++digit,scratch);
PCopy(candidate,nickname);
PSCat(candidate,scratch);
}
while (IsAnyNickname(candidate));
PCopy(nickname,candidate);
}
h = NuHTempBetter(*str+3);
if (h)
{
RemoveFromTo(str);
PCopy(*h,str);
(*h)[*str+1] = 0;
(*h)[*str+2] = 0;
NewNickLow(h,nil,0,nickname,True,nrDifferent,True);
ZapHandle(h);
item=CountMenuItems(mh)+1;//rescan
}
goto nextItem;
}
nextItem:;
}
}
}
/**********************************************************************
* SetupRecipMenus - setup the recipient menus
**********************************************************************/
void SetupRecipMenus(void)
{
Handle hRecip = GetResource('STR#',RECIPIENT_STRN);
if (!hRecip)
{
// Check for old recipient menu as MENU resource
MenuHandle mh;
if ((mh = GetMenu(NEW_TO_HIER_MENU+1000)) ||
(mh = GetMenu(NEW_TO_HIER_MENU+900)))
{
// Save as STR# resource
SaveRecipMenu(mh);
ReleaseResource(mh);
hRecip = GetResource('STR#',RECIPIENT_STRN);
}
}
SetupRecipMenusWith(hRecip);
}
/**********************************************************************
* SetupRecipMenusWith - setup the recipient menus using specified data
**********************************************************************/
void SetupRecipMenusWith(Handle hRecip)
{
MenuHandle mh;
short menu,itemCnt,i;
Str63 scratch;
StringPtr sItem;
// If menus are already set up, delete them and redo them
for (menu=NEW_TO_HIER_MENU;menu<=INSERT_TO_HIER_MENU;menu++)
if (mh=GetMenuHandle(menu))
{
DeleteMenu(menu);
DisposeMenu(mh);
}
// Create menus
itemCnt = hRecip ? CountStrnRes(hRecip) : 0;
EmptyRecip = !itemCnt;
for (menu=NEW_TO_HIER_MENU;menu<=INSERT_TO_HIER_MENU;menu++)
{
switch (menu)
{
case NEW_TO_HIER_MENU: MyGetItem(GetMenuHandle(MESSAGE_MENU),MESSAGE_NEW_TO_ITEM,scratch); break;
case FORWARD_TO_HIER_MENU: MyGetItem(GetMenuHandle(MESSAGE_MENU),MESSAGE_FORWARD_TO_ITEM,scratch); break;
case REDIST_TO_HIER_MENU: MyGetItem(GetMenuHandle(MESSAGE_MENU),MESSAGE_REDIST_TO_ITEM,scratch); break;
case INSERT_TO_HIER_MENU: MyGetItem(GetMenuHandle(EDIT_MENU),EDIT_INSERT_TO_ITEM,scratch); break;
}
if (!(mh = NewMenu(menu,scratch)))
DieWithError(GET_MENU,MemError());
InsertMenu(mh,-1);
if (EmptyRecip)
{
// Put in "No Recipients" menu item
AppendMenu(mh,"\p ");
SetItemR(mh,1,NO_RECIPS);
SetItemStyle(mh,1,italic);
DisableItem(mh,1);
}
else
{
// Load up menu
for(i=1,sItem=LDRef(hRecip)+sizeof(short);i<=itemCnt;i++,sItem+=*sItem+1)
MyAppendMenu(mh,sItem);
UL(hRecip);
}
CalcMenuSize(mh);
}
AttachHierMenu(MESSAGE_MENU,MESSAGE_NEW_TO_ITEM,NEW_TO_HIER_MENU);
AttachHierMenu(MESSAGE_MENU,MESSAGE_FORWARD_TO_ITEM,FORWARD_TO_HIER_MENU);
AttachHierMenu(MESSAGE_MENU,MESSAGE_REDIST_TO_ITEM,REDIST_TO_HIER_MENU);
AttachHierMenu(EDIT_MENU,EDIT_INSERT_TO_ITEM,INSERT_TO_HIER_MENU);
}
/**********************************************************************
* SaveRecipMenu - save recipient menu to resource
**********************************************************************/
void SaveRecipMenu(MenuHandle mh)
{
Handle hRecip;
Accumulator a;
short n,i;
Str255 s;
if (!mh) return;
if (!(hRecip = GetResource('STR#',RECIPIENT_STRN)))
{
// Create a new resource
hRecip = NuHandleClear(sizeof(short));
if (!hRecip) return;
AddResource_(hRecip,'STR#',RECIPIENT_STRN,"");
}
else
SetHandleSize(hRecip,sizeof(short));
n = CountMenuItems(mh);
if (n==1 && !IsMenuItemEnabled(mh,1))
n = 0; // Only "no recipients" item
AccuInitWithHandle(&a,hRecip);
for(i=1;i<=n;i++)
{
GetMenuItemText(mh,i,s);
AccuAddPtr(&a,s,*s+1);
}
AccuTrim(&a);
**(short**)hRecip = n;
ChangedResource(hRecip);
WriteResource(hRecip);
}
/**********************************************************************
* PruneRecipMenu - remove anything that isn't a nickname
**********************************************************************/
void PruneRecipMenu(void)
{
Str255 str;
short item;
MenuHandle mh = GetMHandle(NEW_TO_HIER_MENU);
if (mh)
{
for (item=CountMenuItems(mh);item;item--)
{
MyGetItem(mh,item,str);
if (!IsAnyNickname(str))
RemoveFromTo(str);
}
}
}
/**********************************************************************
* HMGetHelpMenuHandle - under Carbon need to setup our own help menu
**********************************************************************/
OSErr HMGetHelpMenuHandle(MenuRef *mh)
{
long sysVers;
static MenuRef helpMenu;
if (mh==nil)
{
// do it all over again!
helpMenu = nil;
return noErr;
}
if (!helpMenu)
{
Gestalt(gestaltSystemVersion, &sysVers);
if (sysVers >= 0x0a00)
{
// Only do this for OS X or greater
if (helpMenu = GetMenu(HELP_MENU))
InsertMenu(helpMenu,0);
}
else
HMGetHelpMenu(&helpMenu,nil);
}
*mh = helpMenu;
return helpMenu ? noErr : -1;
}
static char checkKey = 0;
static char attachKey = 0;
static char minimizeKey = 0;
/**********************************************************************
* AdjustStupidCommandKeys - OS X steps on cmd-M and cmd-A. Reassign
* the command key for these menu items.
**********************************************************************/
void AdjustStupidCommandKeys(void)
{
MenuHandle mHandle;
short command;
char key;
UInt8 modifiers;
Boolean altCheck = PrefIsSet(PREF_ALTERNATE_CHECK_MAIL_CMD);
Boolean altAttach = !PrefIsSet(PREF_NO_ALTERNATE_ATTACH_CMD);
// Check Mail ...
mHandle = GetMHandle(FILE_MENU);
if (!checkKey)
{
GetItemCmd(mHandle,FILE_CHECK_ITEM,&command);
checkKey = (char)command;
}
if (checkKey)
{
ReadReplacmentCommandKeyPref(COMMAND_KEY_CHECKMAIL_REPLACEMENT, &key, &modifiers);
SetItemCmd(mHandle,FILE_CHECK_ITEM,altCheck?key:checkKey);
SetMenuItemModifiers(mHandle,FILE_CHECK_ITEM,altCheck?modifiers:kMenuNoModifiers);
}
// Attach Document ...
mHandle = GetMHandle(MESSAGE_MENU);
if (!attachKey)
{
GetItemCmd(mHandle,MESSAGE_ATTACH_ITEM,&command);
attachKey = (char)command;
}
if (attachKey)
{
ReadReplacmentCommandKeyPref(COMMAND_KEY_ATTACH_REPLACEMENT, &key, &modifiers);
SetItemCmd(mHandle,MESSAGE_ATTACH_ITEM,altAttach?key:attachKey);
SetMenuItemModifiers(mHandle,MESSAGE_ATTACH_ITEM,altAttach?modifiers:kMenuNoModifiers);
}
// Minimize Window ...
mHandle = GetMHandle(WINDOW_MENU);
if (!minimizeKey)
{
GetItemCmd(mHandle,WIN_MINIMIZE_ITEM,&command);
minimizeKey = (char)command;
}
if (minimizeKey) SetItemCmd(mHandle,WIN_MINIMIZE_ITEM,altCheck?minimizeKey:0);
}
/**********************************************************************
* ReadReplacmentCommandKeyPref - read the replacement command key.
**********************************************************************/
OSErr ReadReplacmentCommandKeyPref(short pref, char *key, UInt8 *modifiers)
{
OSErr err = noErr;
Str255 commandKeyPref;
// initialize
*key = 0;
*modifiers = kMenuNoModifiers;
GetRString(commandKeyPref, pref);
if (commandKeyPref[0] == 2)
{
// first character are the modifers
if ((commandKeyPref[1] >= '0') && (commandKeyPref[1] <= '8')) *modifiers = commandKeyPref[1] - '0';
// second character is the command key
*key = commandKeyPref[2];
}
else err = 1;
return (err);
}
/**********************************************************************
* STUPIDCheckMailHack - Make sure cmd-option-M still invokes Check
* Mail Specially.
**********************************************************************/
long STUPIDCheckMailHack(EventRecord *event)
{
long select = 0;
char keyPressed = UnadornMessage(event);
Boolean optionPressed = ((event->modifiers) & optionKey)!=0;
char origKey = checkKey;
char replacementKey;
UInt8 modifiers;
// if the replacement command doesn't use option, option-replacement will invoke check mail specially.
if (ReadReplacmentCommandKeyPref(COMMAND_KEY_CHECKMAIL_REPLACEMENT, &replacementKey, &modifiers)==noErr)
{
if ((modifiers & optionKey)==0)
{
origKey = replacementKey;
}
}
if (isupper(keyPressed)) keyPressed = tolower(keyPressed);
if (isupper(origKey)) origKey = tolower(origKey);
if ((keyPressed == origKey) && optionPressed) select = ((FILE_MENU << 16)&0xFFFF0000) + FILE_CHECK_ITEM;
return (select);
}