/* 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. */ /* File: taskProgress.c Author: Clarence Wong Date: Augutst 1997 - ... Copyright (c) 1997 by QUALCOMM Incorporated Comments: Much of this code is borrowed from Alan Bird's stationerywin.c and Steve Dorner's progress.c */ #include "taskProgress.h" #include "task_ldef.h" // Task Progress controls enum { kNetworkPopup=0, kFilterButton, kStopButton, kHelpButton, }; #define FILE_NUM 104 #pragma segment TaskProgressWindow static ControlHandle FilterButton = nil; /************************************************************************ * prototypes ************************************************************************/ static void TPDoDidResize(MyWindowPtr win, Rect *oldContR); static void TPDoZoomSize(MyWindowPtr win,Rect *zoom); static void TPDoUpdate(MyWindowPtr win); static void TPDoActivate(MyWindowPtr win); static Boolean TPDoClose(MyWindowPtr win); static void TPDoButton(MyWindowPtr win,ControlHandle button,long modifiers,short part); static void TPDoClick(MyWindowPtr win,EventRecord *event); static void TPDoCursor(Point mouse); static Boolean TPDoKey(MyWindowPtr win, EventRecord *event); static void TPDoShowHelp(MyWindowPtr win,Point mouse); static Boolean TPPosition(Boolean save, MyWindowPtr win); static void TPIdle(MyWindowPtr win); UPtr GetNextCheckTime (UPtr item); UPtr GetLastCheckTime (UPtr item); static void DrawTPProgress(MyWindowPtr win, Rect *lRect,Handle data); static void DrawTPFilter(MyWindowPtr win, Rect *lRect,Handle data); static void DrawTPError(MyWindowPtr win, Rect *lRect,Handle data); static void PositionAllCells(void); static void SetTPWTitle(void); static pascal void FooterUserPaneBackground (ControlHandle control, ControlBackgroundPtr info); static pascal void SetWindowBackground (ControlHandle control, ControlBackgroundPtr info); OSErr TPAddHelpButton(taskErrHandle taskErrs); #define kListInset 10 #define kTextInset 10 #define kCellIndent 4 #define PROG_BAR_WI 100 #define PROG_TOTAL_HI ((PROG_BOX_HI * 3) + INSET + (2*kCellIndent)) #define kRemainWidth 40 #define kLastMailCheckWidth 140 #define kNextMailCheckWidth 145 #define kNextTimeRefCon 'tpnx' #define kLastTimeRefCon 'tpls' #define kFooterRefCon 'tpft' #define kNetworkRefCon 'tpnc' #define kListPaneRefCon 'tplp' #define kNetworkWidth 24 #define kNetworkHeight 20 #define PROG_WI (GetRLong(PROG_CONT_WIDTH) + (2*kListInset)) ListHandle TaskListHandle = nil; taskErrHandle TaskErrorList = nil; /************************************************************************ * InitPrbl ************************************************************************/ void InitPrbl(ProgressBlock **prbl,short vert,ControlHandle *stopButton) { if (TaskProgressWindow) { short stopWidth = 0, stopHeight = 0; #ifdef DEBUG short mid; #endif MyWindowPtr win = TaskProgressWindow; WindowPtr winWP = GetMyWindowWindowPtr(win); Rect contR; ControlHandle listPaneCntl=FindControlByRefCon(TaskProgressWindow,kListPaneRefCon); ASSERT(listPaneCntl); LDRef(prbl); if (!(*stopButton)) { if (*stopButton = GetNewControlSmall(TASK_PROGRESS_STOP_CNTL,winWP)) if (listPaneCntl) EmbedControl(*stopButton,listPaneCntl); // SafeWazooControl(win,*stopButton,TASKS_WIN); } if (*stopButton) { ButtonFit(*stopButton); stopWidth = ControlWi(*stopButton); stopHeight = ControlHi(*stopButton); } contR = win->contR; InsetRect(&contR,kTextInset,kTextInset); // title && progbar SetRect(&(*prbl)->rects[kpTitle],contR.left+kListInset,vert,PROG_WI-PROG_BAR_WI-INSET-kListInset-GROW_SIZE,vert+PROG_BOX_HI); SetRect(&(*prbl)->rects[kpBar],PROG_WI-PROG_BAR_WI-INSET-GROW_SIZE-kListInset,vert,PROG_WI-INSET-GROW_SIZE-kListInset,vert+PROG_BAR_HI); if (!(*prbl)->bar) { if ((*prbl)->bar = NewControl(winWP,&(*prbl)->rects[kpBar], "", false, 0,0,100, kControlProgressBarProc, 0 )) if (listPaneCntl) EmbedControl((*prbl)->bar,listPaneCntl); // SafeWazooControl(win,(*prbl)->bar,TASKS_WIN); } else MoveMyCntl((*prbl)->bar,(*prbl)->rects[kpBar].left,(*prbl)->rects[kpBar].top,0,0); vert += PROG_BOX_HI; // subtitle and remaining counter SetRect(&(*prbl)->rects[kpSubTitle],contR.left+INSET+kListInset,vert,PROG_WI-stopWidth-GROW_SIZE-INSET-kRemainWidth-kListInset,vert+PROG_BOX_HI); SetRect(&(*prbl)->rects[kpRemaining],(*prbl)->rects[kpSubTitle].right+4,vert,PROG_WI-stopWidth-GROW_SIZE-INSET-kListInset,vert+PROG_BOX_HI); vert += PROG_BOX_HI; // message SetRect(&(*prbl)->rects[kpMessage],contR.left+INSET+kListInset,vert,PROG_WI-stopWidth-GROW_SIZE-INSET-kListInset,vert+PROG_BOX_HI); #ifdef DEBUG mid = ((*prbl)->rects[kpTitle].top + (*prbl)->rects[kpTitle].bottom)/2; SetRect(&(*prbl)->rects[kpBeat], 2+kListInset, mid-1, (*prbl)->rects[kpTitle].left-2,mid+1); #endif /* * move the stop button */ if (*stopButton) MoveMyCntl(*stopButton,PROG_WI-stopWidth-GROW_SIZE-INSET-kListInset,(*prbl)->rects[kpSubTitle].top,stopWidth,stopHeight); UL(prbl); } } /************************************************************************ * InvalTPRect - ************************************************************************/ void InvalTPRect(Rect *invalRect) { Rect newInvalRect=(*TaskListHandle)->rView; if (SectRect(&newInvalRect, invalRect, &newInvalRect)) InvalWindowRect(GetMyWindowWindowPtr(TaskProgressWindow),&newInvalRect); } /************************************************************************ * DrawTaskProgressBar - ************************************************************************/ #undef LUpdate void DrawTaskProgressBar(ControlHandle bar) { if (TaskProgressWindow) { RgnHandle rgn = NewRgn(); Rect r; CGrafPtr port = GetWindowPort(GetControlOwner(bar)); RgnHandle oldClip = SavePortClipRegion(port); PositionAllCells(); if (rgn) { r = (*TaskListHandle)->rView; RectRgn(rgn,&r); SectRgn(MyGetPortVisibleRegion(port),rgn,rgn); SectRgn(oldClip,rgn,rgn); SetPortClipRegion(port,rgn); Update1Control(bar,rgn); DisposeRgn(rgn); RestorePortClipRegion(port,oldClip); } } } /************************************************************************ * DrawTP - ************************************************************************/ static void DrawTPProgress(MyWindowPtr win, Rect *lRect,Handle data) { WindowPtr winWP = GetMyWindowWindowPtr(win); ProgressBlock **prbl; ProgressRectEnum which; threadDataHandle threadData; #ifdef NEVER ThreadID threadID; Rect beatRect; #endif Rect clipRect; RgnHandle rgn, newRgn; Str255 mesg; threadData=(threadDataHandle)data; ASSERT(threadData); if (!threadData) return; rgn = NewRgn(); newRgn = NewRgn(); if (rgn && newRgn && (prbl = (*threadData)->prbl)) { GetClip(rgn); LDRef(threadData); InitPrbl(prbl,lRect->top,&(*threadData)->stopButton); UL(threadData); LDRef(prbl); for (which=0;which<=kpTitle;which++) { MoveTo((*prbl)->rects[which].left,(*prbl)->rects[which].bottom-4); if (which==kpTitle) TextFace(bold); else TextFace(0); if (newRgn && rgn) { RectRgn(newRgn, &(*prbl)->rects[which]); SectRgn(newRgn, rgn, newRgn); SetClip(newRgn); } PSCopy(mesg,(*prbl)->messages[which]); TruncString(RectWi((*prbl)->rects[which]),mesg,truncEnd); DrawString(mesg); } clipRect = (*TaskListHandle)->rView; ClipRect(&clipRect); RectRgn(rgn,lRect); SectRgn(rgn,MyGetPortVisibleRegion(GetWindowPort(winWP)),rgn); if ((*threadData)->stopButton) if (!IsControlVisible((*threadData)->stopButton)) ShowControl((*threadData)->stopButton); else Update1Control((*threadData)->stopButton,rgn); if ((*prbl)->bar) Update1Control((*prbl)->bar,rgn); UL(prbl); } if (rgn) DisposeRgn(rgn); if (newRgn) DisposeRgn(newRgn); } #ifndef BATCH_DELIVERY_ON /************************************************************************ * DrawTPFilter - ************************************************************************/ static void DrawTPFilter(MyWindowPtr win, Rect *lRect,Handle data) { short vert = lRect->top; Str255 num; if ((*FilterButton)->contrlRect.top != vert+PROG_BOX_HI) MoveMyCntl(FilterButton,PROG_WI-ControlWi(FilterButton)-GROW_SIZE-INSET-kListInset,vert+PROG_BOX_HI,ControlWi(FilterButton),ControlHi(FilterButton)); // SetGreyControl(FilterButton,CheckThreadRunning); // pane not present during checking if (!IsControlVisible(FilterButton)) { HiliteControl(FilterButton,0); ShowControl(FilterButton); } else Draw1Control(FilterButton); vert += PROG_BOX_HI; MoveTo(win->contR.left+kTextInset+kListInset, vert-4); TextFace(bold); DrawRString(TP_WAITING_TO_DELIVER); vert += PROG_BOX_HI; MoveTo(win->contR.left+kTextInset+INSET+kListInset, vert-4); TextFace(0); DrawRString(TP_LEFT_TO_DELIVER); NumToString(TempInCount, num); MoveTo((*FilterButton)->contrlRect.left-kRemainWidth, vert-4); DrawString(num); vert += PROG_BOX_HI; MoveTo(win->contR.left+kTextInset+INSET+kListInset, vert-4); DrawRString(TP_CLICK_TO_DELIVER); } #endif /************************************************************************ * DrawTPError - ************************************************************************/ static void DrawTPError(MyWindowPtr win, Rect *lRect,Handle data) { taskErrHandle taskErr = (taskErrHandle) data; short vert = lRect->top; Str255 text; Rect box, rView; if (taskErr) { TEHandle teh; vert += (win->vPitch - FontDescent); MoveTo(win->contR.left+kTextInset+kListInset, vert); TextFace(bold); rView = (*TaskListHandle)->rView; ClipRect(&rView); DrawString(PCopy(text,(*taskErr)->taskDesc)); vert+=FontDescent; TextFace(0); SetRect(&box,win->contR.left+kTextInset+INSET+kListInset,vert,PROG_WI-kListInset,lRect->bottom); ClipRect(&rView); // strip all initial and trailing white space // TETextBox Sucks!!! if (teh = TEStyleNew(&box, &box)) { TextStyle txStyle; Point aPoint; PCopy(text,(*taskErr)->errMess); //TrimAllWhite(text); JDB 980218 TESetText(&text[1],text[0],teh); if ((*taskErr)->errExplanation[0]) { TESetSelect(32767,32767,teh); PCopy(text,(*taskErr)->errExplanation); //TrimAllWhite(text); JDB 980218 TEInsert(&text[1],text[0],teh); } // if it doesn't fit, try condensing aPoint = TEGetPoint((*teh)->teLength, teh); if (!PtInRect(aPoint,&(*teh)->viewRect)) { TESetSelect(0,(*teh)->teLength,teh); txStyle.tsFace=condense; TESetStyle(doFace,&txStyle,true, teh); } TEUpdate(&box, teh); TEDispose(teh); } // the help button { ControlHandle helpButton = (*taskErr)->helpButton; RgnHandle rgn = NewRgn(); WindowPtr winWP = GetMyWindowWindowPtr(TaskProgressWindow); if (rgn) { RectRgn(rgn,lRect); SectRgn(rgn,MyGetPortVisibleRegion(GetWindowPort(winWP)),rgn); MoveMyCntl(helpButton,lRect->right-ControlWi(helpButton)-GROW_SIZE-INSET-kListInset,lRect->bottom-ControlHi(helpButton)-INSET,0,0); if (!IsControlVisible(helpButton)) ShowControl(helpButton); else Update1Control(helpButton,rgn); } } } } /************************************************************************ * PositionAllCells - really just draw invisible cells, since our * draw functions reposition controls ************************************************************************/ static void PositionAllCells(void) { WindowPtr TaskProgressWindowWP = GetMyWindowWindowPtr(TaskProgressWindow); Cell theCell; short bounds; Rect cellRect,rWin, emptyRect, visibleRect; Boolean next=true; RgnHandle updateRgn=NewRgn(); SAVE_STUFF; bounds=(*TaskListHandle)->dataBounds.bottom; visibleRect=(*TaskListHandle)->visible; SetRect(&emptyRect,0,0,0,0); SetPort_(GetWindowPort(TaskProgressWindowWP)); GetWindowUpdateRgn(TaskProgressWindowWP,updateRgn); // don't want to add movecontrol regions to update region, so save and restore updateRgn for(theCell.h=theCell.v=0;next;next=LNextCell(false,true,&theCell,TaskListHandle)) { LRect(&cellRect,theCell,TaskListHandle); if (!EqualRect(&emptyRect,&cellRect) && !PtInRect(theCell,&visibleRect)) ListItemDraw(false,&cellRect,theCell,TaskListHandle); } GetWindowStructureBounds(TaskProgressWindowWP,&rWin); ValidWindowRect(TaskProgressWindowWP,&rWin); InvalWindowRgn(TaskProgressWindowWP,updateRgn); DisposeRgn(updateRgn); REST_STUFF; } /************************************************************************ * FooterUserPaneBackground - ************************************************************************/ pascal void FooterUserPaneBackground (ControlHandle control, ControlBackgroundPtr info) { if (TaskProgressWindow) { if (TaskProgressWindow->backBrush) SetThemeWindowBackground(GetMyWindowWindowPtr(TaskProgressWindow),kThemeActiveModelessDialogBackgroundBrush,False); else RGBBackColor(&TaskProgressWindow->backColor); SetUpControlBackground(control,RectDepth(&TaskProgressWindow->contR),ThereIsColor); } } /************************************************************************ * SetWindowBackground - ************************************************************************/ pascal void SetWindowBackground (ControlHandle control, ControlBackgroundPtr info) { if (TaskProgressWindow) RGBBackColor(&TaskProgressWindow->backColor); } /************************************************************************ * OpenTaskWin - ************************************************************************/ void OpenTasksWin(void) { OpenTasksWinBehind(BehindModal); NewError = false; } /************************************************************************ * OpenTaskWinBehind - * behind parameter: * InFront = -1 = frontmost * nil = lastmost * ModalWindow = frontmost nonmodal ************************************************************************/ void OpenTasksWinBehind(void* behind) { OSErr err=0; MyWindowPtr win; WindowPtr frontWin; WindowPtr winWP; threadDataHandle threadData; ControlHandle cntl, footerCntl=nil; Rect r, bounds, rView; Point cSize; taskErrHandle taskErrs; DECLARE_UPP(ListItemDef,ListDef); DECLARE_UPP(FooterUserPaneBackground,ControlUserPaneBackground); DECLARE_UPP(SetWindowBackground,ControlUserPaneBackground); INIT_UPP(ListItemDef,ListDef); INIT_UPP(FooterUserPaneBackground,ControlUserPaneBackground); INIT_UPP(SetWindowBackground,ControlUserPaneBackground); if (ModalWindow) frontWin = ModalWindow; else { // need to also check for modal file dialog... if it doesn't belong to us, leave it frontmost. if (frontWin = FrontWindow()) if ((GetWindowKind(frontWin) >= MBOX_WIN) && (GetWindowKind(frontWin) < LIMIT_WIN)) frontWin = nil; } if (TaskProgressWindow) { WindowPtr TaskProgressWindowWP = GetMyWindowWindowPtr(TaskProgressWindow); if (frontWin) SendBehind(TaskProgressWindowWP,frontWin); else UserSelectWindow(TaskProgressWindowWP); SelectOpenWazoo(TASKS_WIN); // Select if in a wazoo return; } if (behind==InFront) behind=frontWin ? frontWin : InFront; // if behind==nil, open window behind everyone else except toolbar if (behind==nil) { WindowPtr newBehind=FrontWindow_(); if (newBehind) { if (GetWindowKind(newBehind)==TBAR_WIN) newBehind = InFront; else for (newBehind;GetNextWindow(newBehind);newBehind=GetNextWindow(newBehind)) if (GetWindowKind(GetNextWindow(newBehind))==TBAR_WIN) break; } behind = (void *)(newBehind ? newBehind : InFront); } if (!(win=GetNewMyWindow(TASKS_WIND,nil,nil,behind,false,false,TASKS_WIN))) {err=MemError(); goto fail;} winWP = GetMyWindowWindowPtr (win); SetWinMinSize(win,-1,-1); TaskProgressWindow = win; if (InAThread()) ProgWindow = TaskProgressWindow; SetPort_(GetWindowPort(winWP)); ConfigFontSetup(win); MySetThemeWindowBackground(win,kThemeListViewBackgroundBrush,False); if (!(FilterButton = GetNewControlSmall(TASK_PROGRESS_FILTER_CNTL,winWP))) {goto fail;} ButtonFit(FilterButton); HideControl(FilterButton); OutlineControl(FilterButton,true); /* * allocate the list handle */ SetRect(&rView,win->contR.left+INSET,win->topMargin+INSET,win->contR.right,win->contR.bottom); cSize.v = PROG_TOTAL_HI; cSize.h = 0; SetRect(&bounds,0,0,1,0); if (!(TaskListHandle = CreateNewList(ListItemDefUPP,TASK_LDEF,&rView,&bounds,cSize,GetMyWindowWindowPtr(TaskProgressWindow),True,False,False,True))) goto fail; (*TaskListHandle)->selFlags = lOnlyOne|lNoNilHilite; (*TaskListHandle)->indent.v = kCellIndent; (*TaskListHandle)->indent.h = kCellIndent; SetRect(&r,-REAL_BIG,-REAL_BIG,REAL_BIG,REAL_BIG); if (cntl = NewControl(winWP, &r, "",True,kControlSupportsEmbedding+kControlWantsActivate+kControlHasSpecialBackground,0,0, kControlUserPaneProc, kListPaneRefCon)) { SetControlData(cntl,0,kControlUserPaneBackgroundProcTag,sizeof(ControlUserPaneBackgroundUPP),(void*)&SetWindowBackgroundUPP); EmbedControl(FilterButton,cntl); } else goto fail; if (footerCntl = NewControl(winWP,&r,"\p",True,kControlHasSpecialBackground|kControlSupportsEmbedding,0,0,kControlUserPaneProc,kFooterRefCon)) SetControlData(footerCntl,0,kControlUserPaneBackgroundProcTag,sizeof(ControlUserPaneBackgroundUPP),(void*)&FooterUserPaneBackgroundUPP); if (cntl = NewControl(winWP, &r, "",True, 0,0,0, kControlStaticTextProc, kNextTimeRefCon)) { SetBevelFontSize(cntl,applFont,10); SetBevelTextAlign(cntl,teFlushRight); if (footerCntl) EmbedControl(cntl,footerCntl); } if (cntl = NewControl(winWP, &r, "",True, 0,0,0, kControlStaticTextProc, kLastTimeRefCon)) { SetBevelFontSize(cntl,applFont,10); SetBevelTextAlign(cntl,teFlushLeft); if (footerCntl) EmbedControl(cntl,footerCntl); } // (jp) Don't allow icon buttons to be created REAL_BIG... Exhausts memory under alternate themes. SetRect (&r, 0, 0, 16, 16); if (cntl = NewControlSmall(winWP,&r,"\p",True,TP_NETWORK_MENU,kControlContentIconRef+kControlBehaviorMultiValueMenu, 0,kControlBevelButtonSmallBevelProc+kControlBevelButtonMenuOnRight,kNetworkRefCon)) { SetBevelIcon(cntl,TP_NETWORK_ICON,0,0,nil); //Gives 82a2 fits. SD //SetBevelFontSize(cntl,applFont,10); if (footerCntl) EmbedControl(cntl,footerCntl); } InsetRect(&win->contR,6,6); win->maxSize.h = 0; win->didResize = TPDoDidResize; win->close = TPDoClose; win->update = TPDoUpdate; win->activate = TPDoActivate; win->position = TPPosition; win->button = TPDoButton; win->click = TPDoClick; win->idle = TPIdle; win->cursor = TPDoCursor; win->help = TPDoShowHelp; win->key = TPDoKey; win->app1 = TPDoKey; win->zoomSize = TPDoZoomSize; win->dontControl = True; win->dontDrawControls = True; win->dontActivate = True; ShowMyWindowBehind(winWP,(behind==InFront) ? nil : behind); SetTPWTitle(); MyWindowDidResize(win,&win->contR); // add data to task list for(threadData=gThreadData;threadData && !err;threadData=(*threadData)->next) err = AddListItemEntry((*TaskListHandle)->dataBounds.bottom, DrawTPProgress, (Handle)threadData,TaskListHandle); #ifndef BATCH_DELIVERY_ON if (!err && !CheckThreadRunning) err = AddFilterTask(); #endif for(taskErrs=TaskErrorList;taskErrs && !err;taskErrs=(*taskErrs)->next) { err = AddListItemEntry((*TaskListHandle)->dataBounds.bottom, DrawTPError, (Handle)taskErrs,TaskListHandle); if (!err) TPAddHelpButton(taskErrs); } if (err) goto fail; TaskDontAutoClose = !PrefIsSet(PREF_TASK_PROGRESS_AUTO); if (IsWazoo(winWP)) TaskDontAutoClose = true; UpdateMyWindow(winWP); gTaskProgressInitied = true; return; fail: if (TaskProgressWindow) CloseMyWindow(GetMyWindowWindowPtr(TaskProgressWindow)); WarnUser(COULDNT_WIN,err); return; } /************************************************************************ * TPAddHelpButton - add the help button to an error string ************************************************************************/ OSErr TPAddHelpButton(taskErrHandle taskErrs) { ControlHandle helpButton; ControlHandle listPaneCntl=FindControlByRefCon(TaskProgressWindow,kListPaneRefCon); WindowPtr winWP = GetMyWindowWindowPtr(TaskProgressWindow); if (helpButton = GetNewControlSmall(TP_HELP_BUTTON,winWP)) { if (listPaneCntl) EmbedControl(helpButton,listPaneCntl); ButtonFit(helpButton); (*taskErrs)->helpButton = helpButton; return noErr; } return MemError(); } /************************************************************************ * OpenTaskWinErrors - ************************************************************************/ void OpenTasksWinErrors(void) { Point pt; pt.h = pt.v = -1; OpenTasksWin(); if (TaskProgressWindow) { WindowPtr TaskProgressWindowWP = GetMyWindowWindowPtr (TaskProgressWindow); CollapseWindow(TaskProgressWindowWP, false); UpdateMyWindow(TaskProgressWindowWP); } if (!InBG) SysBeep(1); // else nm??? // NewError = false; } /************************************************************************ * GetNextCheckTime - ************************************************************************/ UPtr GetNextCheckTime (UPtr item) { uLong checkTicks = PersCheckTicks(); item[0] = 0; if (checkTicks) { if (!AutoCheckOK()) GetRString(item,TP_NEVER); else { checkTicks = MAX(checkTicks,TickCount()+3600); TimeString((LocalDateTime()-TickCount()/60)+checkTicks/60,False,item,nil); } } else GetRString(item,TP_NOT_SCHEDULED); return(item); } /************************************************************************ * GetLastCheckTime - ************************************************************************/ UPtr GetLastCheckTime (UPtr item) { item[0] = 0; if (CheckThreadRunning) GetRString(item,TP_CHECKING_NOW); else if (LastCheckTime) TimeString(LastCheckTime,False,item,nil); else GetRString(item,TP_NEVER); return(item); } /************************************************************************ * TPDoUpdate - draw the window ************************************************************************/ static void TPDoUpdate(MyWindowPtr win) { WindowPtr winWP = GetMyWindowWindowPtr(win); Rect rView; ControlHandle cntl, listPaneCntl; RgnHandle rgn = NewRgn(); ASSERT(win && (win==TaskProgressWindow)); // list box frame InfiniteClip(GetWindowPort(winWP)); rView = (*TaskListHandle)->rView; rView.right+=GROW_SIZE; DrawThemeListBoxFrame(&rView,kThemeStateActive); // update all controls outside of listpane TaskProgressRefresh(); listPaneCntl=FindControlByRefCon(TaskProgressWindow,kListPaneRefCon); ASSERT(listPaneCntl); if (!listPaneCntl) return; SetControlVisibility(listPaneCntl,false,false); if (!GetRootControl(winWP,&cntl)) Update1Control(cntl,MyGetPortVisibleRegion(GetWindowPort(winWP))); // now update all controls inside listpane PositionAllCells(); SetControlVisibility(listPaneCntl,true,false); rView = (*TaskListHandle)->rView; SET_COLORS; EraseRect(&rView); RectRgn(rgn,&rView); SectRgn(rgn,MyGetPortVisibleRegion(GetWindowPort(winWP)),rgn); rView.right+=GROW_SIZE; ClipRect(&rView); LUpdate(rgn,TaskListHandle); if (rgn) DisposeRgn(rgn); } /************************************************************************ * TPDoActivate - activate/deactivate the window ************************************************************************/ static void TPDoActivate(MyWindowPtr win) { WindowPtr winWP = GetMyWindowWindowPtr (win); ControlHandle listPaneCntl, rootCntl, cntl, parent, tabCntl=nil; Rect rView = (*TaskListHandle)->rView; if (win->isActive) NewError = false; InfiniteClip(GetWindowPort(winWP)); listPaneCntl=FindControlByRefCon(TaskProgressWindow,kListPaneRefCon); ASSERT(listPaneCntl); if (!listPaneCntl) return; // activate all controls outside of listpane SetControlVisibility(listPaneCntl,false,false); if (!GetRootControl(winWP,&rootCntl)) { for (cntl=GetControlList(winWP);cntl;cntl=GetNextControl(cntl)) if (cntl!=listPaneCntl && !IsWazooEmbedderCntl(cntl)) { if (IsWazooTabCntl(cntl)) tabCntl = cntl; else { GetSuperControl(cntl,&parent); if (parent==rootCntl) { ActivateMyControl(cntl,win->isActive); Draw1Control(cntl); } } } if (tabCntl) { ActivateMyControl(tabCntl,win->isActive); Draw1Control(tabCntl); } } // activate all controls inside listpane SetControlVisibility(listPaneCntl,true,false); ClipRect(&rView); // if (win->isActive) ActivateControl(listPaneCntl); // else DeactivateControl(listPaneCntl); for (cntl=GetControlList(winWP);cntl;cntl=GetNextControl(cntl)) { GetSuperControl(cntl,&parent); if (parent==listPaneCntl) { ActivateMyControl(cntl,win->isActive); Draw1Control(cntl); } } LActivate(win->isActive, TaskListHandle); } /************************************************************************ * TaskProgressRefresh - update the task progress window top margin ************************************************************************/ void TaskProgressRefresh(void) { Str255 scratch; Str63 timeString; ControlHandle cntl; if (TaskProgressWindow) { if (cntl=FindControlByRefCon(TaskProgressWindow,kNextTimeRefCon)) { SetTextControlText(cntl,ComposeRString(scratch,TP_NEXT_CHECK,GetNextCheckTime(timeString)),nil); } if (cntl=FindControlByRefCon(TaskProgressWindow,kLastTimeRefCon)) { #if 0 if (NewError) { RGBColor oldColor, newColor; GetForeColor(&oldColor); ForeColor(redColor); GetForeColor(&newColor); SetBevelColor(cntl,&newColor); RGBForeColor(&oldColor); } #endif SetTextControlText(cntl,ComposeRString(scratch,TP_LAST_CHECK,GetLastCheckTime(timeString)),nil); } if (cntl=FindControlByRefCon(TaskProgressWindow,kNetworkRefCon)) { MenuHandle menu = nil; if (!GetControlData(cntl,kControlMenuPart,kControlBevelButtonMenuHandleTag,sizeof(menu),(Ptr)&menu,nil) && menu) { SetItemMark(menu,NETWORK_NO_CONNECTION,PrefIsSet(PREF_PPP_NOAUTO) ? checkMark : noMark); SetItemMark(menu,NETWORK_NO_BATTERIES,PrefIsSet(PREF_NO_BATT_CHECK) ? checkMark : noMark); SetItemMark(menu,NETWORK_GO_OFFLINE,PrefIsSet(PREF_OFFLINE) ? checkMark : noMark); } } } } /************************************************************************ * TPDoDidResize - resize the window ************************************************************************/ static void TPDoDidResize(MyWindowPtr win, Rect *oldContR) { ControlHandle cntl; Rect rView = win->contR; Point cSize; short listBottom = win->contR.bottom-GROW_SIZE-kListInset; short wi, midPoint; if (cntl=FindControlByRefCon(win,kListPaneRefCon)) MoveMyCntl(cntl,0,0,win->contR.right,listBottom + 2); if (cntl=FindControlByRefCon(win,kFooterRefCon)) MoveMyCntl(cntl,0,listBottom + 2,win->contR.right,win->contR.bottom - listBottom - 2); if (cntl=FindControlByRefCon(win,kNetworkRefCon)) MoveMyCntl(cntl,kListInset,listBottom+(win->contR.bottom-listBottom-kNetworkHeight)/2+1,kNetworkWidth,kNetworkHeight); // list if (TaskListHandle) { cSize.h = win->contR.right - GROW_SIZE - 1; cSize.v = PROG_TOTAL_HI; SetRect(&rView,win->contR.left+kListInset,win->topMargin+kListInset,win->contR.right-GROW_SIZE-kListInset,listBottom); ResizeList(TaskListHandle,&rView,cSize); } midPoint = (rView.left + rView.right)/2 + kNetworkWidth; wi = (rView.right - rView.left - kNetworkWidth)/2 - INSET; if (cntl=FindControlByRefCon(win,kLastTimeRefCon)) MoveMyCntl(cntl,kListInset+kNetworkWidth+1,listBottom+8,wi,ONE_LINE_HI(win)); if (cntl=FindControlByRefCon(win,kNextTimeRefCon)) MoveMyCntl(cntl,midPoint,listBottom+8,wi-INSET,ONE_LINE_HI(win)); InvalContent(win); } /************************************************************************ * TPDoZoomSize - zoom to only the maximum size of list ************************************************************************/ static void TPDoZoomSize(MyWindowPtr win,Rect *zoom) { int numCells; // = (*TaskListHandle)->dataBounds.bottom; <-- doesn't work when auto-opening tp taskErrHandle taskErrs; short zoomHi = zoom->bottom-zoom->top; short zoomWi = zoom->right-zoom->left; short hi, wi; #ifdef BATCH_DELIVERY_ON numCells = CheckThreadRunning + SendThreadRunning; #else numCells = CheckThreadRunning + SendThreadRunning + NeedToFilterIn; #endif for(taskErrs=TaskErrorList;taskErrs;taskErrs=(*taskErrs)->next) numCells++; numCells = MAX(numCells,1); hi = win->topMargin + GROW_SIZE + kListInset + (numCells * (*TaskListHandle)->cellSize.v); if (numCells) hi += kListInset; wi = PROG_WI; wi = MIN(wi,zoomWi); wi = MAX(wi,win->minSize.h); hi = MIN(hi,zoomHi); hi = MAX(hi,win->minSize.v); zoom->right = zoom->left+wi; zoom->bottom = zoom->top+hi; } /************************************************************************ * TPDoClose - close the window ************************************************************************/ static Boolean TPDoClose(MyWindowPtr win) { #pragma unused(win) threadDataHandle threadData; ProgressBHandle prbl; taskErrHandle taskErrs; FilterButton = nil; for(threadData=gThreadData;threadData;threadData=(*threadData)->next) { (*threadData)->stopButton=nil; for(prbl=(*threadData)->prbl;prbl;prbl=(*prbl)->next) (*prbl)->bar=nil; } for(taskErrs=TaskErrorList;taskErrs;taskErrs=(*taskErrs)->next) { if ((*taskErrs)->helpButton) { DisposeControl((*taskErrs)->helpButton); (*taskErrs)->helpButton = nil; } } LDispose(TaskListHandle); TaskListHandle = nil; if (TaskProgressWindow==ProgWindow) ProgWindow = nil; // only nil if same win TaskProgressWindow = nil; gTaskProgressInitied = false; return(True); } /************************************************************************ * TPDoKey - key stroke ************************************************************************/ static Boolean TPDoKey(MyWindowPtr win, EventRecord *event) { Byte c = event->message&charCodeMask; if ((event->modifiers&cmdKey) && IsCmdChar(event,'.') || (c==escChar) && (((event->message&keyCodeMask)>>8)==escKey)) { threadDataHandle threadData; Rect rView; if (!gThreadData) return (false); #ifdef SPEECH_ENABLED if (CancelSpeech ()) return (false); #endif rView = (*TaskListHandle)->rView; ClipRect(&rView); for(threadData=gThreadData;threadData;threadData=(*threadData)->next) if ((*threadData)->stopButton) // HiliteControl((*threadData)->stopButton,1); ActivateControl((*threadData)->stopButton); // am doc says to do this Pause(20L); for(threadData=gThreadData;threadData;threadData=(*threadData)->next) { ClipRect(&rView); if ((*threadData)->stopButton) HiliteControl((*threadData)->stopButton,0); SetThreadGlobalCommandPeriod ((*threadData)->threadID, true); } ClipRect(&win->contR); return (true); } else if ((c==returnKey || c==enterKey) && IsControlVisible(FilterButton) && IsControlActive(FilterButton)) { HiliteControl(FilterButton,1); TPDoButton(win,FilterButton,event->modifiers,1); } else if (!(event->modifiers&cmdKey)) SysBeep(1); return (false); } /************************************************************************ * TPPosition - ************************************************************************/ static Boolean TPPosition(Boolean save, MyWindowPtr win) { Str31 title; MyGetItem(GetMHandle(WINDOW_MENU),WIN_TASKS_ITEM,title); SetWTitle_(GetMyWindowWindowPtr(win),title); return(PositionPrefsTitle(save,win)); } /************************************************************************ * TPDoButton ************************************************************************/ static void TPDoButton(MyWindowPtr win,ControlHandle button,long modifiers,short part) { #pragma unused(win,modifiers) threadDataHandle threadData; long controlId; taskErrHandle taskErrs; if (button==FindControlByRefCon(win,kNetworkRefCon)) { SInt16 value=0; MenuHandle menu = nil; short markChar=0; if (!GetControlData(button,part,kControlBevelButtonMenuValueTag,sizeof(SInt16),(Ptr)&value,nil) && !GetControlData(button,part,kControlBevelButtonMenuHandleTag,sizeof(menu),(Ptr)&menu,nil) && menu) { controlId = kNetworkPopup; GetItemMark(menu,value,&markChar); switch(value) { case NETWORK_NO_CONNECTION: SetPref(PREF_PPP_NOAUTO,(markChar==checkMark) ? YesStr : NoStr); break; case NETWORK_NO_BATTERIES: SetPref(PREF_NO_BATT_CHECK,(markChar==checkMark) ? YesStr : NoStr); break; case NETWORK_GO_OFFLINE: SetPref(PREF_OFFLINE,(markChar==checkMark) ? YesStr : NoStr); break; } InvalContent(win); } } else if (button==FilterButton) { controlId = kFilterButton; FilterXferMessages(); goto done; } for(threadData=gThreadData;threadData;threadData=(*threadData)->next) if (button == (*threadData)->stopButton) { controlId = kStopButton; SetThreadGlobalCommandPeriod ((*threadData)->threadID, true); goto done; } for(taskErrs=TaskErrorList;taskErrs;taskErrs=(*taskErrs)->next) if (button == (*taskErrs)->helpButton) { Str255 err, expl; GoGetHelp(PCopy(err,(*taskErrs)->errMess),PCopy(expl,(*taskErrs)->errExplanation)); controlId = kHelpButton; goto done; } done: AuditHit((modifiers&shiftKey)!=0, (modifiers&controlKey)!=0, (modifiers&optionKey)!=0, (modifiers&cmdKey)!=0, false, GetWindowKind(GetMyWindowWindowPtr(win)),AUDITCONTROLID(GetWindowKind(GetMyWindowWindowPtr(win)),controlId),mouseDown); } /************************************************************************ * TPDoClick ************************************************************************/ static void TPDoClick(MyWindowPtr win,EventRecord *event) { Point pt = event->where; Rect rCntl; GlobalToLocal(&pt); if (PtInRect(pt,GetControlBounds((*TaskListHandle)->vScroll,&rCntl))) LClick(pt, CurrentModifiers(), TaskListHandle); else { Rect rView = (*TaskListHandle)->rView; if (PtInRect(pt,&rView)) { ClipRect(&rView); HandleControl(pt,win); ClipRect(&win->contR); } else HandleControl(pt,win); // <--- what if we click on a part of the cntrl that's sticking out of rView???? } } /************************************************************************ * TPDoCursor - set the cursor properly for the window ************************************************************************/ static void TPDoCursor(Point mouse) { if (!PeteCursorList(TaskProgressWindow->pteList,mouse)) SetMyCursor(arrowCursor); } /************************************************************************ * TPDoShowHelp - provide help for the window ************************************************************************/ static void TPDoShowHelp(MyWindowPtr win,Point mouse) { #pragma unused(win,mouse) } /************************************************************************ * AddProgressTask - ************************************************************************/ OSErr AddProgressTask(threadDataHandle threadData) { OSErr err=noErr; if (TaskProgressWindow) { err = AddListItemEntry(0, DrawTPProgress, (Handle)threadData,TaskListHandle); SetTPWTitle(); } return err; } /************************************************************************ * RemoveProgressTask - ************************************************************************/ void RemoveProgressTask(threadDataHandle threadData) { if (TaskProgressWindow) { RemoveListItemEntry((Handle)threadData,TaskListHandle); SetTPWTitle(); } } #ifndef BATCH_DELIVERY_ON /************************************************************************ * AddFilterTask - ************************************************************************/ OSErr AddFilterTask(void) { if (TaskProgressWindow && NeedToFilterIn) { RemoveListItemEntry((Handle)FilterButton,TaskListHandle); // just in case return(AddListItemEntry(SendThreadRunning, DrawTPFilter, (Handle)FilterButton,TaskListHandle)); } return noErr; } /************************************************************************ * RemoveFilterTask - ************************************************************************/ void RemoveFilterTask(void) { if (TaskProgressWindow) { RemoveListItemEntry((Handle)FilterButton,TaskListHandle); HideControl(FilterButton); } } #endif /************************************************************************ * AddTaskErrorsString ************************************************************************/ OSErr AddTaskErrorsS(StringPtr error, StringPtr explanation, TaskKindEnum taskKind, long persId) { OSErr err = noErr; taskErrHandle taskErrs; Str255 name; PersHandle pers; RemoveTaskErrors(taskKind,persId); ComposeLogS(LOG_ALRT,nil,"\pÒ%pÓ Ò%pÓ",error,explanation); NewError = true; if (!(taskErrs = NuHandleClear(sizeof(taskErrData)))) { err = MemError(); CommandPeriod = true; if (taskKind==CheckingTask) CheckThreadError = err; else if (taskKind==SendingTask) SendThreadError = err; return err; } (*taskErrs)->taskKind = taskKind; (*taskErrs)->persId = persId; PSCopy((*taskErrs)->errMess,error); if ((*taskErrs)->errMess[0]==255) (*taskErrs)->errMess[255]='É'; PSCopy((*taskErrs)->errExplanation,explanation); if ((*taskErrs)->errExplanation[0]==255) (*taskErrs)->errExplanation[255]='É'; for(pers=PersList;pers;pers=(*pers)->next) if ((*pers)->persId==persId) break; if (pers) PSCopy(name,(*pers)->name); else GetRString(name,TP_UNKNOWN_PERS); LDRef(taskErrs); switch(taskKind) { case CheckingTask: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_CHECKING_MAIL,name); break; case SendingTask: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_SENDING_MAIL,name); break; case IMAPResyncTask: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_RESYNCING,name); break; case IMAPFetchingTask: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_FETCHING,name); break; case IMAPDeleteTask: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_DELETING,name); break; case IMAPUndeleteTask: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_UNDELETING,name); break; case IMAPTransferTask: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_TRANSFERRING,name); break; case IMAPExpungeTask: case IMAPMultExpungeTask: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_EXPUNGING,name); break; case IMAPAttachmentFetch: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_ATTACHMENT_FETCH,name); break; case IMAPSearchTask: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_SEARCH,name); break; case IMAPMultResyncTask: case IMAPPollingTask: GetRString((*taskErrs)->taskDesc,ERR_MULT_RESYNCING); break; case IMAPUploadTask: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_TRANSFERRING,name); break; case IMAPAlertTask: ComposeRString((*taskErrs)->taskDesc,ERR_IMAP_ALERT,name); break; case IMAPFilterTask: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_FILTERING,name); break; default: ComposeRString((*taskErrs)->taskDesc,ERR_PERS_UNKNOWN_TASK,name); break; } UL(taskErrs); LL_Queue(TaskErrorList,taskErrs,(taskErrHandle)); if (TaskProgressWindow) { TPAddHelpButton(taskErrs); if (err = AddListItemEntry((*TaskListHandle)->dataBounds.bottom, DrawTPError, (Handle)taskErrs,TaskListHandle)) { CommandPeriod=true; if (taskKind==CheckingTask) CheckThreadError = err; else if (taskKind==SendingTask) SendThreadError = err; } } return (err); } /************************************************************************ * SetTPWTitle ************************************************************************/ static void SetTPWTitle(void) { WindowPtr TaskProgressWindowWP = GetMyWindowWindowPtr(TaskProgressWindow); Str31 title; Str255 winTitle; if (TaskProgressWindow && GetWindowKind(TaskProgressWindowWP)==TASKS_WIN) { MyGetItem(GetMHandle(WINDOW_MENU),WIN_TASKS_ITEM,title); PCopy(winTitle,title); if (SendThreadRunning || CheckThreadRunning) { if (CheckThreadRunning) { if (SendThreadRunning) ComposeRString(winTitle,TP_DUAL_FMT,title,TP_CHECKING,TP_SENDING); else ComposeRString(winTitle,TP_SINGLE_FMT,title,TP_CHECKING); } else if (SendThreadRunning) ComposeRString(winTitle,TP_SINGLE_FMT,title,TP_SENDING); } SetWTitle_(TaskProgressWindowWP,winTitle); } } /************************************************************************ * RemoveTaskErrors ************************************************************************/ void RemoveTaskErrors(TaskKindEnum taskKind,long persId) { taskErrHandle current, last, temp; for(last=current=TaskErrorList;current;) { temp=current; current=(*current)->next; if (((*temp)->taskKind==taskKind) && (((*temp)->persId==persId) || (persId==-1))) { if(temp==TaskErrorList) TaskErrorList=(*temp)->next; else (*last)->next=(*temp)->next; if (TaskProgressWindow) { RemoveListItemEntry((Handle)temp,TaskListHandle); if ((*temp)->helpButton) { DisposeControl((*temp)->helpButton); (*temp)->helpButton = nil; } } DisposeHandle((Handle)temp); } else last=temp; } if (!TaskErrorList) NewError=false; } /************************************************************************ * TPIdle - idle time handler for the Task Progress window ************************************************************************/ void TPIdle(MyWindowPtr win) { // Update the TP window if the connection method has changed. // We're watching the connection method in ActiveUserIdleTasks(). if (NeedToUpdateTP()) InvalContent(win); } /* Task Progress: To do/bug list: -tp control for toolbar -hitting cancel and cmd-. sometimes doesn't cancel stdalert -insert errors at top of error list -composestdalert should deactivate frontmost window -append   to button to mean hit this button when alert times out -Aborting mail send-- can't edit open comp window without closing it first -next mail check time sometimes off a minute -"One of the addresses is too long..." should be a per-message error -"There was an error opening an attachment..." should be a per-message error done: -don't auto-hide tp window until filtered -inset tp list for wazooability -offline control -decouple in/out filtering -don't put up filter pane for outgoing mail, change menu -don't show filter pane if can't be done -flickering scroll bar -if cell is scrolled out of view and cell in view goes away, out of view cell not accessible until window resized -report error from main thread if error reporting error -add #of messages to filter pane */