NotificationMon.ƒ/Source/NotificationMon.c

#include "NotificationMon.h"
#include <GestaltTalk.h>
#include "Event.h"
 
short GetSleepTime()
{
    if(InBackGround)
        return MainView->prefs.backTime;
    else
        return MainView->prefs.foreTime;
}
 
Boolean IsNotificationDoc(WindowPeek wp)
{
    return (wp->windowKind == notifyKind);
}
 
void InitNotificationDoc(notificationDoc *nmd)
{
    Handle      emptyMessage;
    GrafPtr     savePort;
    FontInfo    fi;
    
    nmd->ncount = 0;
    nmd->nHead = nil;
    nmd->nTail = nil;
    nmd->vScroll = nil;
    nmd->nSelection = 0;
 
    GetPort(&savePort);
    SetPort(&nmd->nWin);
    GetFontInfo(&fi);
    nmd->lineHt = fi.ascent + fi.descent + fi.leading;
    emptyMessage = GetResource('STR ',128);
    HLock(emptyMessage);
    nmd->longestLine = StringWidth(*emptyMessage) + RIGHT_MARGIN;
    HUnlock(emptyMessage);
    SetPort(savePort);
}
 
void    RegisterNotificationMonitor()
{
    GestaltTalkPB       gPB;
    OSErr               err;
    ProcessSerialNumber psn;
    
    if(!MainView) return;
     
    err = GetCurrentProcess(&psn);
    if(err) {
        DebugStr("\pError in GetCurrentProcess");
    }
    
    gPB.command = gregister;
    gPB.datalength = sizeof(ProcessSerialNumber);
    gPB.data = &psn;
    gPB.gtData = nil;
    
    err = GestaltTalk(&gPB);
    if(err) {
        DebugStr("\p GestaltTalk register failed.");
    }
}
 
void    UnregisterNotificationMonitor()
{
    GestaltTalkPB       gPB;
    OSErr               err;
    
    if(!MainView) return;
     
    gPB.command = gunregister;
    gPB.datalength = 0;
    gPB.data = nil;
    gPB.gtData = nil;
    
    err = GestaltTalk(&gPB);
    if(err) {
        DebugStr("\p GestaltTalk UNregister failed.");
    }
}
 
notificationDoc *NewNotificationDoc(short wID)
{
    notificationDoc *nmd;
    
    nmd = NewPtr(sizeof(notificationDoc));
    if(!nmd) {
        DebugStr("\pMemory Allocation Fail. in NewNotficationDoc");
    }
    
    (void) GetNewWindow(wID,&nmd->nWin,(WindowPtr)-1);
    nmd->nWin.windowKind = notifyKind;
 
    InitNotificationDoc(nmd);
    InitNotificationPrefs(nmd);
    InitNotificationWindow(nmd);
    
    ShowWindow(&nmd->nWin);
    return nmd;
}
 
void AddNotification(Str255 notification, notificationDoc *nmd)
{
    Handle      icon = nil, sound = nil, message = nil;
    short       err = 0;
    Size        msgLen = 0;
    nnH         nCurs;
    GrafPtr     savePort;
    short       msgPixLen;
    Rect        content;
    
    msgLen = notification[0] +1;
    message = NewHandle(msgLen);
    if(!message) {
        DebugStr("\pNewHandle fail in AddNotification[1]");
        return;
    }
    BlockMove(notification, *message, msgLen);
    
    nCurs = NewHandle(sizeof(neoNotification));
    if(!nCurs) {
        DebugStr("\pNewHandle fail in AddNotification[2]");
        return;
    }
    (**nCurs).icon = icon;
    (**nCurs).sound = sound;
    (**nCurs).message = message;
    (**nCurs).next = nil;
 
    if(nmd->nHead == nil) {
        nmd->nHead = nmd->nTail = nCurs;
    }
    else {
        (**(nmd->nTail)).next = nCurs;
        nmd->nTail = nCurs;
    }
    nmd->ncount++;
    
    GetPort(&savePort);
    SetPort(&nmd->nWin);
    msgPixLen = StringWidth(notification) + RIGHT_MARGIN;
    if(msgPixLen > nmd->longestLine)
        nmd->longestLine = msgPixLen;
 
    UpdateScrollMax(nmd);
    NotificationCheckScrollVis();
 
    content = nmd->nWin.port.portRect;
    content.right -= 16;
    InvalRect(&content);
 
    SetPort(savePort);
}
 
void KillNotifications(notificationDoc *nmd)
{
    nnH         nCurs;
    GrafPtr     savePort;
    
    if(!nmd->ncount) return;
    
    while(nmd->ncount--) {
        nCurs = nmd->nHead;
        if((**nCurs).icon)
            DisposHandle((**nCurs).icon);
        if((**nCurs).sound)
            DisposHandle((**nCurs).sound);
        if((**nCurs).message)
            DisposHandle((**nCurs).message);
        nmd->nHead = (**nCurs).next;
        DisposHandle(nCurs);
    }
 
    nmd->ncount = 0;
    nmd->nHead = nil;
    nmd->nTail = nil;
    
    GetPort(&savePort);
    SetPort(&nmd->nWin);
    InvalRect(&nmd->nWin.port.portRect);
    SetPort(savePort);
    
}
 
nnH GetNotificationEntryByNumber(notificationDoc *nmd, short num)
{
    short   count;
    nnH     target;
 
    if(num > nmd->ncount)   return nmd->nTail;
    if(num < 1)             return nmd->nHead;
    
    target = nmd->nHead;
    while(--num) {
        target = (**target).next;
    }
    
    return target;
}
 
void DrawNotification(nnH n)
{
    if(!n) {
        DebugStr("\p n was nil in DrawNotification");
        return;
    }
    HLock((Handle)(**n).message);
    DrawString(*(**n).message);
    HUnlock((Handle)(**n).message);
}
 
void UpdateNotifications(notificationDoc *nmd, short first)
{
    nnH         nCurs;
    short       numToDraw;
    FontInfo    fi;
    short       i;
    GrafPtr     savePort;
    Handle      emptyMessage;
    Rect        clip, selRect;
    
    GetPort(&savePort); 
    SetPort(&nmd->nWin.port);
 
    clip = nmd->nWin.port.portRect;
    clip.right -= 16;   
    ClipRect(&clip);
 
    EraseRect(&clip);
 
    if(!nmd->ncount) {
        MoveTo(4,nmd->lineHt);
        emptyMessage = GetResource('STR ',128);
        HLock(emptyMessage);
        DrawString(*emptyMessage);
        HUnlock(emptyMessage);
        return;
    }
 
    nCurs = GetNotificationEntryByNumber(nmd,first);
    
    for(i = 0; i <= nmd->ncount - first; i++) {
        if(nmd->nSelection && (i == nmd->nSelection) ) {
            selRect = nmd->nWin.port.portRect;
            selRect.right -= 16;
            selRect.bottom = selRect.top + nmd->lineHt;
            if(nmd->nSelection > 1)
                OffsetRect(&selRect, 0, nmd->lineHt * nmd->nSelection);
            FillRect(&selRect,black);
            MoveTo(4,(i+1)*nmd->lineHt);
            TextMode(srcXor);
            DrawNotification(nCurs);
            TextMode(srcOr);
        } else {
            MoveTo(4,(i+1)*nmd->lineHt);
            DrawNotification(nCurs);
        }
        nCurs = (**nCurs).next;
        if(!nCurs) break;
    }
    
    
    ClipRect(&nmd->nWin.port.portRect);
    SetPort(savePort);
}
 
 
void CheckNotifications()
{
    GestaltTalkPB   gPB;
    OSErr           err;
    Str255          message;
    
    if(!MainView) return;
     
    gPB.command = gstatus;
    gPB.datalength = 0;
    gPB.data = nil;
    gPB.gtData = nil;
    
    err = GestaltTalk(&gPB);
    
    if(err) {
        error("\p CheckNotification failed.",err);
        return;
    }
 
    if(!gPB.datalength) return;
 
    gPB.command = gread;
    /* using datalength returned from status call */
    gPB.data = message;
    gPB.gtData = nil;
    
    err = GestaltTalk(&gPB);
 
    if(err) {
        error("\p CheckNotifications read error. ",err);
    }
 
    AddNotification(message, MainView);
    PostNotificationIcon();
 
}