/* select.c handles choosing which database to start up.
 * The code for the system find function is here too.
 */

/* Includes required */
#include <Common.h>
#include <System/SysAll.h>
#include <UI/UIAll.h>
#include "listrc.h"
#include "list.h"

/* private globals because I'm lazy and don't want to malloc */
static Handle selectDBList;
static char selectNames[12][dmDBNameLength];
static LocalID selectDbID[12];
static UInt selectCardNo[12];

/*
SelectFormEventHandler
*/

Boolean SelectFormEventHandlerV10(EventPtr event)
{
	FormPtr form;
	Boolean handled = false;
	TablePtr table;
	Word i;
	CALLBACK_PROLOGUE;   /* Work around PilotGCC 0.5.0 bug */

	switch( event->eType )
	{
		case frmOpenEvent:
			form = FrmGetActiveForm();

	/* Initialize the table */
			table = FrmGetObjectPtr( form, FrmGetObjectIndex( form, idSelectTable ));
			for( i = 0; i < selectTableRows; i++ ) {
				TblSetItemStyle( table, i, 0, customTableItem );
				TblSetRowUsable( table, i, false );
			}

			TblSetColumnUsable( table, 0, true );

	/* Set the callback routine that will draw the records */
			TblSetCustomDrawProcedure( table, 0, &SelectTableDrawRecord );

			SelectLoadTable();

			FrmDrawForm( form );

			handled = true;
			break;

		case tblSelectEvent:

	/* Open the database with the name that is at that row */
			CurrentDB = DmOpenDatabase( selectCardNo[event->data.tblSelect.row], 
										selectDbID[event->data.tblSelect.row], dmModeReadWrite );

			ReadDatabaseInfo();

			FrmGotoForm( idMainForm );
			handled = true;
			break;

		case appStopEvent:
	/* if we try to switch out apps here, choose the first database */
			CurrentDB = DmOpenDatabase( selectCardNo[0], selectDbID[0], dmModeReadWrite );
			ReadDatabaseInfo();
			break;

	}
	CALLBACK_EPILOGUE; /* Work around PilotGCC 0.5.0 bug */
	return( handled );
}

Boolean SelectFormEventHandlerV20(EventPtr event)
{
	FormPtr form;
	Boolean handled = false;
	ListPtr selectList;
	SysDBListItemType *ptrSelectList;
	Word dbCount, i;
	CALLBACK_PROLOGUE;   /* Work around PilotGCC 0.5.0 bug */

	switch( event->eType )
	{
		case frmOpenEvent:
			form = FrmGetActiveForm();

	/* Initialize the selection database list */
			SysCreateDataBaseList( ListType, ListCreator, &dbCount, &selectDBList, true );
			selectList = FrmGetObjectPtr( form, FrmGetObjectIndex( form, idSelectList ));
			LstSetListChoices( selectList, NULL, dbCount );
			LstSetSelection( selectList, -1 );
			LstSetDrawFunction( selectList, SelectListDrawItem );

			FrmDrawForm( form );

			handled = true;
			break;

		case lstSelectEvent:

			/* Open the database with the name that is at that row */
			ptrSelectList = MemHandleLock( (VoidHand)selectDBList );
			CurrentDB = DmOpenDatabase( ptrSelectList[event->data.lstSelect.selection].cardNo,
										ptrSelectList[event->data.lstSelect.selection].dbID,
										dmModeReadWrite );
			MemHandleUnlock( (VoidHand)selectDBList );
			ReadDatabaseInfo();

			FrmGotoForm( idMainForm );
			handled = true;
			break;

		case keyDownEvent:
			form = FrmGetActiveForm();
			selectList = FrmGetObjectPtr( form, FrmGetObjectIndex( form, idSelectList ));
			switch( event->data.keyDown.chr ) {
				case pageUpChr:
					LstScrollList( selectList, up, 11 );
					break;
				case pageDownChr:
					LstScrollList( selectList, down, 11 );
					break;
			}
			handled = true;
			break;

		case appStopEvent:
			/* if we try to switch out apps here, choose the first database */
			ptrSelectList = MemHandleLock( (VoidHand)selectDBList );
			CurrentDB = DmOpenDatabase( ptrSelectList[0].cardNo, ptrSelectList[0].dbID,	dmModeReadWrite );
			MemHandleUnlock( (VoidHand)selectDBList );
			ReadDatabaseInfo();
			break;

	}
	CALLBACK_EPILOGUE; /* Work around PilotGCC 0.5.0 bug */
	return( handled );
}

/* 
 *  We will only ever handle a single "page" of databases (12)
 */
void SelectTableDrawRecord(VoidPtr table, Word row, Word column, RectanglePtr bounds )
{
	CharPtr string;
	Word length = 0;
	CALLBACK_PROLOGUE;   /* Work around PilotGCC 0.5.0 bug */

	FntSetFont( stdFont );
	length = StrLen( selectNames[row] );
	WinDrawChars( selectNames[row], length, bounds->topLeft.x + 20, bounds->topLeft.y );

	CALLBACK_EPILOGUE; /* Work around PilotGCC 0.5.0 bug */
}

void SelectListDrawItem(UInt index, RectanglePtr bounds, CharPtr *data )
{
	SysDBListItemType *ptrDBList;
	CALLBACK_PROLOGUE;   /* Work around PilotGCC 0.5.0 bug */

	ptrDBList = MemHandleLock( (VoidHand)selectDBList );
	FntSetFont( stdFont );
	WinDrawChars( ptrDBList[index].name, StrLen( ptrDBList[index].name ),
				  bounds->topLeft.x + 15, bounds->topLeft.y );
	MemHandleUnlock( (VoidHand)selectDBList );

	CALLBACK_EPILOGUE; /* Work around PilotGCC 0.5.0 bug */
}


/* This routine is used to update the main form table.  It is used when:
   - intializing the table
   - scrolling
*/
void SelectLoadTable()
{
  FormPtr form;
  TablePtr table;
  LocalID dbID;
  UInt cardNo; 
  DmSearchStateType dbState;
  Word i;

  form = FrmGetActiveForm();
  table = FrmGetObjectPtr( form, FrmGetObjectIndex( form, idSelectTable ));

  /* we know there is at least one database */
  DmGetNextDatabaseByTypeCreator( true, &dbState, ListType, ListCreator, false,
				  &cardNo, &dbID );

  /* fill in the selection table */
  for( i = 0; i < selectTableRows; i++ ) {

    /* fill in the first name */
    DmDatabaseInfo( cardNo, dbID, selectNames[i], NULL, NULL, NULL, NULL, NULL, NULL,
		    NULL, NULL, NULL, NULL );

    selectCardNo[i] = cardNo;
    selectDbID[i] = dbID;

    /* Make the row usable */
    TblSetRowUsable( table, i, true );

    /* Mark it invalid so it will be redrawn */
    TblMarkRowInvalid( table, i );

    /* Grab the next database, if there are no more, break out */
    if( DmGetNextDatabaseByTypeCreator( false, &dbState, ListType, ListCreator, false,
					&cardNo, &dbID ) != 0) break;

    }
  MultipleLists = i >= 1;
  TblUnhighlightSelection( table );
}



void ListDrawEntry( ListDBHeader *record, RectanglePtr bounds, Byte displayStyle )
{
  CharPtr string;
  SWord x;
  ULong length;
  Boolean needDots = false;
  Boolean done = false;
  Int remaining, newLength;
  Word columnWidth;

  FntSetFont( stdFont );
  
  columnWidth = bounds->extent.x;

  if( displayStyle == 0 ) {
    if( record->field1 != 0 ) {
      string = (CharPtr)record + record->field1;
    } else {
      string = emptyRecordLabel;
    }
  } else {
    if( record->field2 != 0 ) {
      string = (CharPtr)record + record->field2;
    } else {
      string = emptyRecordLabel;
    }
  }

  x = bounds->topLeft.x;
  length = (ULong) StrChr( string, (Int)'\n' );
  if( length == 0 ) {
    length = StrLen( string );
  } else {
    length -= (ULong) string;
  }

  /* Restrict the first field to a maximum of 110 pixels */
  if( FntCharsWidth( string, length ) > 110 ) {
	  remaining = 110;
	  newLength = length;
	  FntCharsInWidth( string, &remaining, &newLength, &needDots );
	  length = newLength;
	  needDots = true;
  }
  WinDrawChars( string, length, x, bounds->topLeft.y );
  
  /* If We truncated the string at all, put some dots */
  x += FntCharsWidth( string, length );
  if( needDots ) {
    WinDrawChars( "..", 2, x, bounds->topLeft.y );
    x += FntCharsWidth( "..", 2 );
    needDots = false;
  }
  
  if( displayStyle == 0 ) {
    done = record->field2 == 0;
  } else {
    done = record->field1 == 0;
  }
  if( !done ) {    
    /* Calculate the amount of room remaining for the second field.
       This is the minimum X value we can use for the next field */
    remaining = (columnWidth - 4) - x; /* note: fudge factor of 4 pixels */
    
    if( displayStyle == 0 ) {      
      string = (CharPtr)record + record->field2;
    } else {
      string = (CharPtr)record + record->field1;
    }
    length = (ULong) StrChr( string, (Int)'\n' );
    if( length == 0 ) {
      length = StrLen( string );
    } else {
      length -= (ULong) string;
    }
    
    /* Restrict the second field to the remaining pixel size */
	if((x = FntCharsWidth( string, length )) > remaining ) {
      remaining -= FntCharsWidth( "..", 2 );

	  newLength = length;
	  FntCharsInWidth( string, &remaining, &newLength, &needDots );
	  length = newLength;
	  needDots = true;
	  x = FntCharsWidth( string, length );
    }
    x = columnWidth - x; 
    
    if( needDots ) {
      x -= FntCharsWidth( "..", 2 );
    }
    
    WinDrawChars( string, length, x, bounds->topLeft.y );
    if( needDots ) {
      x += FntCharsWidth( string, length );
      WinDrawChars( "..", 2, x, bounds->topLeft.y );
    }
  }
}
