gs->rgbrow,
output_row(gif_struct *gs){    int width, drow_start, drow_end;        drow_start = drow_end = gs->irow;    /*     * Haeberli-inspired hack for interlaced GIFs: Replicate lines while     * displaying to diminish the "venetian-blind" effect as the image is     * loaded. Adjust pixel vertical positions to avoid the appearance of the     * image crawling up the screen as successive passes are drawn.     */    if (gs->progressive_display && gs->interlaced && (gs->ipass < 4))    {        PRUintn row_dup=0, row_shift=0;        switch (gs->ipass) {        case 1:            row_dup = 7;            row_shift = 3;            break;        case 2:            row_dup = 3;            row_shift = 1;            break;        case 3:                        row_dup = 1;            row_shift = 0;            break;        default:            //ILTRACE(0,("Illegal interlace pass"));            break;        }        drow_start -= row_shift;        drow_end = drow_start + row_dup;        /* Extend if bottom edge isn't covered because of the shift upward. */        if (((gs->height - 1) - drow_end) <= row_shift)            drow_end = gs->height - 1;        /* Clamp first and last rows to upper and lower edge of image. */        if (drow_start < 0)            drow_start = 0;         if ((PRUintn)drow_end >= gs->height)            drow_end = gs->height - 1;    }    /* Check for scanline below edge of logical screen */    if ((gs->y_offset + gs->irow) < gs->screen_height) {        /* XXX: Set this from the GIF data */        gdispose drawmode = DISPOSE_OVERWRITE_PREVIOUS;                /* Clip if right edge of image exceeds limits */        if ((gs->x_offset + gs->width) > gs->screen_width)            width = gs->screen_width - gs->x_offset;        else            width = gs->width;        if (width > 0)          if(gs->GIFCallback_HaveDecodedRow) {            /* Decoded data available callback */            int result = (gs->GIFCallback_HaveDecodedRow)(              gs->clientptr,              gs->rowbuf,                /* Pointer to single scanline temporary buffer */              gs->rgbrow,                /* Pointer to temporary storage for dithering/mapping */              gs->x_offset,              /* x offset with respect to GIF logical screen origin */              width,                     /* Length of the row */              drow_start,                /* Row number */              drow_end - drow_start + 1, /* Number of times to duplicate the row? */              drawmode,                  /* il_draw_mode */              gs->ipass);                /* interlace pass (1-4) */          }    }    gs->rowp = gs->rowbuf;    if(!gs->interlaced)    {        gs->irow++;    }    else    {        do{            switch(gs->ipass)            {                case 1:                    gs->irow += 8;                    if(gs->irow >= gs->height)                    {                        gs->ipass++;                        gs->irow = 4;                    }                    break;                case 2:                    gs->irow += 8;                    if(gs->irow >= gs->height)                    {                        gs->ipass++;                        gs->irow = 2;                    }                    break;                case 3:                    gs->irow += 4;                    if(gs->irow >= gs->height)                    {                        gs->ipass++;                        gs->irow = 1;                    }                    break;                case 4:                    gs->irow += 2;                    if(gs->irow >= gs->height){                        gs->ipass++;                        gs->irow = 0;                    }                    break;                default:                    /* PR_ASSERT(0); */                    break;            }        }while(gs->irow > gs->height - 1);    }}