/*  call-seq:
 *     update()
 *     update(rect)
 *     update(x,y,w,h)
 *
 *  Updates (refreshes) all or part of the Rubygame window, revealing to the 
 *  user any changes that have been made since the last update. If you're using
 *  a double-buffered display (see Display.set_mode), you should use
 *  Screen#flip instead.
 *
 *  This method takes these arguments:
 *  rect:: a Rubygame::Rect representing the area of the screen to update.
 *         Can also be an length-4 Array, or given as 4 separate arguments.
 *         If omitted or nil, the entire screen is updated.
 */
VALUE rbgm_screen_update(int argc, VALUE *argv, VALUE self)
{
  int x,y,w,h;
  SDL_Surface *screen;
  Data_Get_Struct(self,SDL_Surface,screen);
        VALUE vx, vy, vw, vh;

        rb_scan_args(argc, argv, "04", &vx, &vy, &vw, &vh);

        x = y = w = h = 0;

        if( RTEST(vx) )
        {
                switch( TYPE(vx) ) {
                        case T_ARRAY: {
                                if( RARRAY(vx)->len < 4 )
                                {
                                        rb_raise(rb_eArgError,"Array is too short to be a Rect (%s for 4)",
                                                                         RARRAY(vx)->len);
                                }
                                x = NUM2INT(rb_ary_entry(vx,0));
                                y = NUM2INT(rb_ary_entry(vx,1));
                                w = NUM2INT(rb_ary_entry(vx,2));
                                h = NUM2INT(rb_ary_entry(vx,3));
                                break;
                        }
                        case T_FLOAT:
                        case T_BIGNUM:
                        case T_FIXNUM: {
                                x = NUM2INT(vx);
                                y = NUM2INT(vy);
                                w = NUM2INT(vw);
                                h = NUM2INT(vh);
                                break;
                        }
                        default: {
                                rb_raise(rb_eTypeError,"Unrecognized type for x (wanted Array or Numeric).");
                                break;
                        }
                }
        }

        Sint16 left,top,right,bottom;

        left   = min( max( 0,    x    ), screen->w );
        top    = min( max( 0,    y    ), screen->h );
        right  = min( max( left, x + w), screen->w );
        bottom = min( max( top,  y + h), screen->h );

        x = left;
        y = top;
        w = right - left;
        h = bottom - top;

  SDL_UpdateRect(screen,x,y,w,h);
  return self;
}