PoliteNotification.ƒ/ShowInitIcon.c

/*
    ShowInitIcon.c : Shows the icon during the init loading time
*/
 
/*
    Note: This code is roughly based on an assembly language routine by
        Paul Mercer, Darin Adler, and Paul Snively from an idea by Steve Capps.
        We use this method to be compatible with other Mac INITs.
        
        It was converted to Think C by Eric Shapiro.
            10/6/91     ebs     Added HNoPurge call just to be extra safe.
            4/26/91     ebs     Added wrap-to-next-line support from James W. Walker
            3/29/91     ebs     Changed function name, added CIconHandle typecasts
            12/12/89    ebs     Called ClosePort() to release port memory
*/
 
    /* The low memory CurApName is a convenient place to store
        four bytes of information so the next INIT doesn't
        overwrite our ICON.  We store into my_h the horizontal
        pixel location where the next INIT should go.  We checksum
        the value and store the checksum in the next two bytes,
        so that INITs can determine whether they're the 1st one loaded.
    */
    
#define CurApName 0x910
 
extern  short       my_h : CurApName+32-4;  
extern  short       my_check : CurApName+32-2;
 
#ifndef NULL
#define NULL ( (void *)0 )
#endif
 
#define ICON_HEIGHT     32
#define ICON_WIDTH      32
#define FIRST_X         8           /* don't change this */
#define BOTTOM_MARGIN   8
#define DEF_MOVE_X_BY   40
#define CHECKSUM_CONST  0x1021
#define MIN_BIT_DEPTH   4           /* if 16 colors or more, use color icon */
 
 
/*
    ShowInitIcon: Shows the icon specified in the correct place during startup
    
        NOTE:
            If Color QDraw is present and the main device has at least MIN_BIT_DEPTH
            set, we'll look for a color icon ('cicn' resource) first. If we can't
            find one, we'll look for the 'ICN#' resource.
 
        Passed:
            short   icon_num;       'ICN#' or 'cicn' resource id
            short   move_x_by;      Pass -1 for default
            
        Returns:
            int     0=No error, <0=Error number
*/
OSErr ShowInitIcon( short icon_num, short move_x_by)
{
    short       err;
    Handle      icon_h=NULL;        /* handle to 'ICN#' or 'cicn' resource */
    Boolean     in_color=FALSE;     /* TRUE='cicn' resource, else 'ICN#' */
    GrafPtr     oldport;
    GrafPort    newport;            /* Entire GrafPort structure */
    Rect        r;                  /* where to put the icon */
    SysEnvRec   sys_rec;
    short       screen_width;
 
        /* check for color quickdraw. If present, check bit depth of mainscreen.
            if >= MIN_BIT_DEPTH, then try to use color icon.
        */
    if ( err = SysEnvirons(1, &sys_rec) )
        return(err);
    if ( sys_rec.hasColorQD )       /* a Mac II or later... */
    {
        GDHandle gdev = GetGDevice();   /* get main screen */
        if ( (*(*gdev)->gdPMap)->pixelSize >= MIN_BIT_DEPTH )
            icon_h = (Handle)GetCIcon(icon_num);
        if ( icon_h != NULL )
            in_color = TRUE;
    }
    
    if ( icon_h == NULL )       /* no icon yet, try a B&W one */
        icon_h = Get1Resource('ICN#', icon_num);
    if ( icon_h == NULL )
        return(resNotFound);    /* we're SOL here */
    HNoPurge( icon_h );
 
    GetPort(&oldport);      /* save old GrafPort for later restoring */
 
        /* open a port so we can draw directly to screen. WindowMgrPort
            may not be initialized at this time.
        */
    OpenPort(&newport);
    SetPort(&newport);
    
        /* do a checksum on low memory to see if we're the 1st icon */
        /* if we are, then set x location. ^=XOR. */
    if ( ((my_h <<1) ^ CHECKSUM_CONST) != my_check )
        my_h = FIRST_X;
 
#ifdef OLD_VERSION
        /* now plot the icon */
    r = newport.portRect;
    r.top = newport.portRect.bottom - (BOTTOM_MARGIN+ICON_HEIGHT);
    r.bottom = newport.portRect.bottom - BOTTOM_MARGIN;
    r.left = my_h;
    r.right = r.left + ICON_WIDTH;
#endif
        /* now plot the icon  4/26/91 updated */
    screen_width = newport.portRect.right - newport.portRect.left;
    screen_width -= screen_width % DEF_MOVE_X_BY;   /* in case screen isn't multiple of 40 */
    r.left = my_h % screen_width;
    r.right = r.left + ICON_WIDTH;
    r.top = newport.portRect.bottom - ((BOTTOM_MARGIN+ICON_HEIGHT) * (1 + my_h / screen_width));
    r.bottom = r.top + ICON_HEIGHT;
    
    if ( in_color )
        PlotCIcon(&r, (CIconHandle)icon_h);     /* Toolbox's plot routine */
    else
        plot_icn(&r, icon_h);                   /* our routine */
    
        /* now offset the low memory location by move_x_by pixels */
    if ( move_x_by == -1 )
        move_x_by = DEF_MOVE_X_BY;
 
    my_h += move_x_by;
    my_check = (my_h<<1) ^ CHECKSUM_CONST;
 
        /* release the icon, restore the port */
    if ( in_color )
        DisposCIcon((CIconHandle)icon_h);
    else
        ReleaseResource(icon_h);
    SetPort(oldport);
    ClosePort(&newport);                        /* ebs 12/12/89 */
    return(0);
}
 
 
/*
    plot_icn : Plots an ICN# (ICON+mask) just the the Finder.
*/
plot_icn(r, icn_handle)
    Rect    *r;
    Handle  icn_handle;
{
    BitMap      bm;
    char        flags;
    GrafPtr     cur_port;
    
    flags = HGetState(icn_handle);
    HLock(icn_handle);
    GetPort(&cur_port);
    
        /* we have to set up a BitMap structure to pass to CopyBits. We
            might be able to use CopyMask() call instead, but this should
            work on all Macs and CopyMask is only Mac+ or later. The 1st
            BitMap we use has baseAddr pointing 128 bytes into the ICN#,
            at the 1st bit of the mask. The 2nd BitMap points to the ICON.
        */
    bm.baseAddr = *icn_handle + ICON_WIDTH*ICON_HEIGHT/8;   /* points to mask */
    bm.rowBytes = ICON_WIDTH / 8;           /* ICON_WIDTH/8 must be power of 2 */
    SetRect(&bm.bounds, 0, 0, ICON_WIDTH, ICON_HEIGHT);
 
        /* punch a hole in the Desktop using bit-clear mode and the mask */
    CopyBits(&bm, &cur_port->portBits, &bm.bounds, r, srcBic, NULL);
 
        /* now copy the icon into the punched hole */
    bm.baseAddr = *icn_handle;      /* points to ICON */
    CopyBits(&bm, &cur_port->portBits, &bm.bounds, r, srcOr, NULL);
    
    HSetState(icn_handle, flags);
}