/*
 * AUTHOR: Andrew Lister <lister@syd.net.au>
 *
 * Simple example of the draw cell, write cell routines
 *
 * $Id: draw.c,v 1.1 1999/08/04 21:24:08 danny Exp $
 */

#ifdef HAVE_CONFIG_H
#include <XbaeConfig.h>
#endif

#include <Xbae/Matrix.h>
#include <Xm/Text.h>
#include <Xm/Form.h>
#include <stdio.h>
#if defined(HAVE_XPM_H)
#include <xpm.h>
#else  /* !HAVE_XPM_H */
#ifdef HAVE_X11_XPM_H
#include <X11/xpm.h>
#endif /* HAVE_X11_XPM_H */
#endif /* HAVE_XPM_H */

#define ROWS 10000
#define COLUMNS 20
#define WIDTH 8

static char cells[ ROWS ][ COLUMNS ][ WIDTH ];
static Pixmap pixmap = 0, mask;
static Widget text;
static int lastRow = -1;

static void DrawCB(), WriteCB(), EnterCB(), LeaveCB();
static void LoadMatrix();

#if defined(HAVE_XPM_H) || defined(HAVE_X11_XPM_H)
/* XPM */
static char * xbae_xpm[] =
{
    "48 16 5 1",
    " 	s mask	c None",
    ".	c Red",
    "X	c Blue",
    "o	c Green",
    "O	c Yellow",
    "....           .                                ",
    " ....          .                                ",
    "  ....        .                                 ",
    "   ....      .   XXXXX   oooo  OOOOO            ",
    "   ....     .    XX  XX oo  oo OO               ",
    "    ....   .     XX  XX oo  oo OO               ",
    "     ....  .     XX  XX oo  oo OO               ",
    "      ... .      XXXXX  oooooo OOOO             ",
    "      .. .       XX  XX oo  oo OO               ",
    "      . ...      XX  XX oo  oo OO               ",
    "     .  ....     XX  XX oo  oo OO               ",
    "     .   ....    XX  XX oo  oo OO               ",
    "    .    ....    XXXXX  oo  oo OOOOO            ",
    "   .      ....                                  ",
    "  .        ....                                 ",
    " .          ....                                "
};
#endif

#define xbae_width 48
#define xbae_height 16
static unsigned char xbae_bits[] = {
   0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x80, 0x00, 0x00, 0x00, 0x00,
   0x3c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x78, 0x20, 0x3e, 0x9e, 0x0f, 0x00,
   0x78, 0x10, 0x66, 0xb3, 0x01, 0x00, 0xf0, 0x08, 0x66, 0xb3, 0x01, 0x00,
   0xe0, 0x09, 0x66, 0xb3, 0x01, 0x00, 0xc0, 0x05, 0x3e, 0xbf, 0x07, 0x00,
   0xc0, 0x02, 0x66, 0xb3, 0x01, 0x00, 0x40, 0x07, 0x66, 0xb3, 0x01, 0x00,
   0x20, 0x0f, 0x66, 0xb3, 0x01, 0x00, 0x20, 0x1e, 0x66, 0xb3, 0x01, 0x00,
   0x10, 0x1e, 0x3e, 0xb3, 0x0f, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x00, 0x00,
   0x04, 0x78, 0x00, 0x00, 0x00, 0x00, 0x02, 0xf0, 0x00, 0x00, 0x00, 0x00
};

static void
LoadMatrix()
{
    int i, j;

    for( i = 0; i < ROWS; i++ )
	for( j = 0; j < COLUMNS; j++ )
	    ( void )sprintf( cells[ i ][ j ], "%d %d", i, j );
}

static void
DrawCB( w, cd, cbs )
Widget w;
XtPointer cd;
XbaeMatrixDrawCellCallbackStruct *cbs;
{
    if( cbs->column == 2 )
    {
    if( !pixmap )
    {
#if defined(HAVE_XPM_H) || defined(HAVE_X11_XPM_H)
	XpmAttributes attributes;

	attributes.valuemask = 0;
	attributes.valuemask |= XpmReturnInfos;
	attributes.valuemask |= XpmReturnAllocPixels;
	attributes.valuemask |= XpmReturnExtensions;
	
	if( XpmCreatePixmapFromData(
	    XtDisplay(w), XtWindow(w), xbae_xpm, &pixmap, &mask,
	    &attributes) != XpmSuccess )
	    
	    /* Use a bitmap instead */
	    pixmap = XCreateBitmapFromData(
		XtDisplay( w ), RootWindowOfScreen( XtScreen( w ) ),
		( char * )xbae_bits, xbae_width, xbae_height );
	
	XpmFreeAttributes( &attributes );
#else    
	pixmap = XCreateBitmapFromData(
	    XtDisplay( w ), RootWindowOfScreen( XtScreen( w ) ),
	    ( char * )xbae_bits, xbae_width, xbae_height );
#endif
    }

	/* Assign it a pixmap */
	cbs->type = XbaePixmap;
	cbs->pixmap = pixmap;
	cbs->mask = mask;

	/* Set height and width to that of the bitmap's to ensure correct
	   positioning and drawing */

	/* This is no longer necessary as it is calculated on the fly.
	   However, providing the values improves efficiency */
 	cbs->height = xbae_height;
 	cbs->width = xbae_width;
#if defined(HAVE_XPM_H) || defined(HAVE_X11_XPM_H)
	cbs->depth = 8;
#else
	cbs->depth = 1;
#endif
    }
    else
    {
	cbs->type = XbaeString;
	cbs->string = cells[ cbs->row ][ cbs->column ];
    }
    return;
}

static void
WriteCB( w, cd, cbs )
Widget w;
XtPointer cd;
XbaeMatrixWriteCellCallbackStruct *cbs;
{
    char buf[ 128 ];
    
    if( cbs->column == 0 )
	strcpy( buf, "Cells containing Pixmaps cannot change" );
    else
    {
	if( strcmp( cells[ cbs->row ][ cbs->column ], cbs->string ) == 0 )
	    sprintf( buf, "No change made to cell [%d, %d]", cbs->row,
		     cbs->column );
	else
	{
	    sprintf( buf, "Changing value in [%d, %d] from %s to %s",
		     cbs->row, cbs->column, cells[ cbs->row ][ cbs->column ],
		     cbs->string );

	    strcpy( cells[ cbs->row ][ cbs->column ], cbs->string );
	}
    }
    XmTextSetString( text, buf );
}

static void
EnterCB( w, cd, cbs )
Widget w;
XtPointer cd;
XbaeMatrixEnterCellCallbackStruct *cbs;
{
    if( lastRow == cbs->row )
	return;

    if( lastRow >= 0 )
	XbaeMatrixUnhighlightRow( w, lastRow );

    XbaeMatrixHighlightRow( w, cbs->row );

    lastRow = cbs->row;
}

static void
LeaveCB( w, cd, cbs )
Widget w;
XtPointer cd;
XbaeMatrixLeaveCellCallbackStruct *cbs;
{
	printf("Leave\n");
}

int
main(argc, argv)
int argc;
char *argv[];
{
    Widget toplevel, mw, form;
    XtAppContext app;
    int i;
#ifdef USE_EDITRES
    extern void _XEditResCheckMessages();
#endif
    short widths[ COLUMNS ];
    char buf[ 128 ];

    LoadMatrix();
    
    toplevel = XtVaAppInitialize(&app, "Draw",
				 NULL, 0,
				 &argc, argv,
				 NULL,
				 NULL);
#ifdef USE_EDITRES
    XtAddEventHandler( toplevel, (EventMask)0, True,
                       _XEditResCheckMessages, NULL);
#endif

    for( i = 0; i < COLUMNS; i++ )
	widths[ i ] = WIDTH;
    
    form = XtVaCreateManagedWidget(
	"form", xmFormWidgetClass, toplevel,
	NULL );
    
    mw = XtVaCreateManagedWidget(
	"mw", xbaeMatrixWidgetClass, form,
	XmNrows, ROWS,
	XmNcolumns, COLUMNS,
	XmNcolumnWidths, widths,
	XmNvisibleRows, 8,
	XmNvisibleColumns, 10,
	XmNleftAttachment, XmATTACH_FORM,
	XmNrightAttachment, XmATTACH_FORM,
	XmNtopAttachment, XmATTACH_FORM,
	NULL);
    XtAddCallback( mw, XmNdrawCellCallback, DrawCB, NULL );
    XtAddCallback( mw, XmNwriteCellCallback, WriteCB, NULL );
    XtAddCallback( mw, XmNenterCellCallback, EnterCB, NULL );
    XtAddCallback( mw, XmNleaveCellCallback, LeaveCB, NULL );

    sprintf( buf,
	     "A matrix widget with %d rows and %d columns - That's %d cells!",
	     ROWS, COLUMNS, ROWS * COLUMNS );
    
    text = XtVaCreateManagedWidget(
	"text", xmTextWidgetClass, form,
	XmNeditable, False,
	XmNcursorPositionVisible, False,
	XmNtopAttachment, XmATTACH_WIDGET,
	XmNtopWidget, mw,
	XmNleftAttachment, XmATTACH_FORM,
	XmNrightAttachment, XmATTACH_FORM,
	XmNbottomAttachment, XmATTACH_FORM,
	XmNvalue, buf,
	NULL );
	
    XtRealizeWidget(toplevel);
    XtAppMainLoop(app);
    
    /*NOTREACHED*/
    return 0;
}

