/* ID = gtkhelp.c
   Some help options for GTK+
   Trent Weddington &
   Maciek Fijalkowski 2001 - 2002 */

#include "tools.h"

/* `draw_area' is a pointer to a GtkDrawingArea widget, which we will
 * use to display the contents of our Allegro bitmap.  We will use
 * `screen' here, but you can use anything you want.  */

/* These bank switching functions get called when a line gets selected
 * for writing.  This saves us from redrawing the entire `draw_area'
 * widget, as in the previous program.  */

static int last_line = -1;

#ifndef ALLEGRO_NO_ASM
unsigned long _screen_write_line_asm (BITMAP *bmp, int line);
unsigned long _screen_unwrite_line_asm (BITMAP *bmp, int line);
#endif

static inline void
update_draw_area_line ( BITMAP *bmp, int y)
{
  GtkWidget *draw_area;

  draw_area = (GtkWidget*)(bmp -> extra);
  gdk_draw_rgb_32_image (draw_area->window, draw_area->style->black_gc,
			 0, y, bmp->w, 1, GDK_RGB_DITHER_NONE,
			 bmp->line[y], bmp->w * 4 );
}

unsigned long
_screen_write_line ( BITMAP *bmp, int line)
{
    int new_line = line + bmp->y_ofs;
    if ((new_line != last_line) && (last_line >= 0))
	update_draw_area_line ( bmp, last_line);
    last_line = new_line;
    return (unsigned long) (bmp->line[line]);
}

void
_screen_unwrite_line ( BITMAP *bmp)
{
    if (last_line >= 0)
	update_draw_area_line ( bmp, last_line);
    last_line = -1;
}


/* The "configure" event is sent whenever the widget is resized
 * (including when it is created).  You may decide to resize the
 * screen bitmap here, for example.  */

static gboolean
draw_area_configure_event ( GtkWidget *widget , GdkEventConfigure *event , BITMAP *bmp )
{
    /* Set write bank switching functions.  We do this here because if
     * the bank switching functions were called before `draw_area' was
     * properly constructed, that would be bad.  */    
#ifdef ALLEGRO_NO_ASM
  bmp->write_bank = _screen_write_line;
  bmp->vtable->unwrite_bank = _screen_unwrite_line;
#else
  bmp->write_bank = _screen_write_line_asm;
  bmp->vtable->unwrite_bank = _screen_unwrite_line_asm;
#endif
    
    /* The new width and height of the widget may be found in
     * widget->allocation.width and widget->allocation.height.  */

    return TRUE;
}


/* The "expose" event is sent when some part of the widget on screen
 * requires redrawing (e.g. it was previously overlapped).  */

static gboolean
draw_area_expose_event (GtkWidget *widget, GdkEventExpose *event,
			BITMAP *bmp )
{
  int x0,y0,xk,yk,sx,sy;

    /* Look in `/usr/include/gdk/gdkrgb.h' for other functions if
     * you're not using a 32 bit bitmap.  */
  gdk_window_get_size ( event -> window , &sx , &sy );
  xk = MIN ( event -> area.x + event -> area.width , (bmp -> w + sx) / 2 );
  yk = MIN ( event -> area.y + event -> area.height , (bmp -> h + sy) / 2 );
  x0 = MAX ( event -> area.x , (sx - bmp -> w) / 2 );
  y0 = MAX ( event -> area.y , (sy - bmp -> h) / 2 );
  sx = MAX ( event -> area.x - (sx - bmp -> w) / 2 , 0 );
  sy = MAX ( event -> area.y - (sy - bmp -> h) / 2 , 0 );
  if (( xk - x0 < 0 ) || ( yk - y0 < 0 ))
    return ( FALSE );
  gdk_draw_rgb_32_image (widget->window, widget->style->black_gc,
			 x0 , y0 , xk - x0 , yk - y0 ,
			 GDK_RGB_DITHER_NONE,
			 bmp->line[sy] + sx * 4 , bmp -> w * 4 );
  
  return FALSE;
}

GtkWidget *make_drawing_area ( BITMAP *bitmap )
{
  GtkWidget *drawing_area;

  drawing_area = gtk_drawing_area_new ();
  gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area),
  			 bitmap -> w , bitmap -> h );
  bitmap -> extra = drawing_area;
  gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
  		      GTK_SIGNAL_FUNC (draw_area_expose_event), bitmap);
  gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
  	      GTK_SIGNAL_FUNC (draw_area_configure_event), bitmap);
  gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK);
  return ( drawing_area );
}

