#include <stdlib.h>
#include <string.h>
#include "StringGadget.h"
#include "StringGadgetClass.h"
#include "minmax.h"
#include "EmbossedGadgetClass.h"
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include "amigamem.h"



void StringGadget_CleanUp( StringGadget *self )
{
   struct StringInfo *stringinfo;

   stringinfo = (struct StringInfo *) self->g.SpecialInfo;

   if (stringinfo)
   {
      self->g.SpecialInfo = NULL;
      Afree( stringinfo->Buffer );
      Afree( stringinfo );
   }
   
   Afree( self->BoxBorder );
   self->BoxBorder = NULL;
}


#define BORDERWIDTH_X 4
#define BORDERWIDTH_Y 2

Point StringGadget_SetLocation( StringGadget *self,
                                 PIXELS        LeftEdge,
                                 PIXELS        TopEdge )
{
   Forbid(); /* Don't want Intuition looking at these while we modify em. */
   self->Location.x = LeftEdge;
   self->Location.y = TopEdge;
   self->g.LeftEdge = LeftEdge + BORDERWIDTH_X;
   self->g.TopEdge  = TopEdge  + BORDERWIDTH_Y;
   Permit();
/*
   printf("Location=(%d,%d) (%d,%d), LineWidth=(%d,%d)\n",
      self->Location.x, self->Location.y,
      self->g.LeftEdge, self->g.TopEdge,
      LineWidth.x, LineWidth.y );
*/
   return self->Location;
}

#define FONT_HEIGHT 8

Point StringGadget_AskSize( StringGadget *self,
                             PIXELS        Width,
                             PIXELS        Height )
{
   Point size;

   size.x = MAX( Width,  6 + BORDERWIDTH_X*2 );
   size.y = FONT_HEIGHT + BORDERWIDTH_Y*2;

   return size;
}

Point StringGadget_SetSize( StringGadget *self,
                            PIXELS        Width,
                            PIXELS        Height )
{

   pcg_3DBevel *bevel;
   Point        size;

   bevel = (pcg_3DBevel *) self->BoxBorder;
   size  = AskSize( self, Width, Height );

   Forbid(); /* Don't want Intuition looking at these while we modify em. */
   self->Size       = size;
   self->g.Width    = size.x - BORDERWIDTH_X*2;
   self->g.Height   = size.y - BORDERWIDTH_Y*2;

   pcg_Init3DBevel( (pcg_3DBevel *) self->BoxBorder,
                    -BORDERWIDTH_X, -BORDERWIDTH_Y, size.x, size.y, 0,
                    self->Pens.BrightPen,  self->Pens.DarkPen, NULL );
   Permit();
   return size;
}




USHORT StringGadget_ClaimEvent( StringGadget *self,
                                IntuiMessage *event )
{
   USHORT response = 0;

   switch (event->Class)
   {
      case REFRESHWINDOW:
         response = RESPONDED;
         break;

      case GADGETDOWN:
         if (event->IAddress == (void*) &self->g)
         {
            response = RESPONDED | CONSUMED_EVENT | CHANGED_STATE;
         }
         break;

      case GADGETUP:
         if (event->IAddress == (void*) &self->g)
         {
            response = RESPONDED | CONSUMED_EVENT | CHANGED_STATE | DEACTIVATED;
         }
         break;
   }

   return response;
}


void StringGadget_Refresh( StringGadget *self )
{
   pcgWindow *window;

   if (window = InteractorWindow(self))
   {
      EmbossedGadget_Refresh( self );

      if (self->LabelText.IText)
         PrintIText( RPort(window), &self->LabelText,
                     self->Location.x, self->Location.y );
   }
}

void StringGadget_Render( StringGadget *self, RastPort *RPort )
{

   EmbossedGadget_Render( self, RPort );

   if (self->LabelText.IText)
      PrintIText( RPort, &self->LabelText,
                  self->Location.x, self->Location.y );
}




BOOL StringGadget_Activate( StringGadget *self )
{
   pcgWindow *pw;
   Window *w;

   if (isEnabled(self))
      if (pw = InteractorWindow(self))
         if (w = iWindow(pw))
         {
            ActivateGadget( FirstGadget(self), w, NULL );
            return TRUE;
         }
   return FALSE;
}

char *StringGadget_Value( StringGadget *self )
{
   struct StringInfo *stringinfo;

   stringinfo = (StringInfo *) self->g.SpecialInfo;

   if (stringinfo->NumChars > 0)
      return (char*) stringinfo->Buffer;
   else return NULL;
}

char *StringGadget_SetValue( StringGadget *self, char *selection )
{
   struct StringInfo *stringinfo;

   stringinfo = (StringInfo *) self->g.SpecialInfo;
   Forbid();

   if (selection)
      strncpy( stringinfo->Buffer, selection, stringinfo->MaxChars );
   else
      stringinfo->Buffer[0] = '\0';

   Permit();

   return selection;
}

#ifdef BUILDER
#include "BuilderMethods.h"
#include "GraphicObject_Builder.h"
#include "StringGadget_coder.h"
#include "StringGadget_Builder.h"

StringGadget *StringGadget_New( StringGadget *self )
{
   StringGadget *new_gadget;
   struct StringInfo *stringinfo;

   if (new_gadget = (StringGadget *) Amalloc( sizeof(StringGadget) ))
   {
      stringinfo = (struct StringInfo *) self->g.SpecialInfo;

       StringGadget_Init( new_gadget,
          self->Location.x, self->Location.y,
          self->Size.x, stringinfo->MaxChars-1,
          self->Pens,   Title(self) );
       new_gadget->g.Flags      = self->g.Flags;
       GiveItAName( new_gadget );
       SetStringValue( new_gadget, StringValue(self) );
   }
   return new_gadget;
}


struct BuilderMethods StringGadget_bm;

#endif


BOOL StringGadget_elaborated = FALSE;

struct ValuatorClass StringGadget_Class;

void StringGadgetClass_Init( struct ValuatorClass *class )
{
   ValuatorClass_Init( class );
   EmbossedGadgetClass_Init( class );
   class->isa         = ValuatorClass();
   class->ClassName   = "StringGadget";
   class->CleanUp     = StringGadget_CleanUp;
   class->SetLocation = StringGadget_SetLocation;
   class->SetSize     = StringGadget_SetSize;
   class->AskSize     = StringGadget_AskSize;
   class->SizeFlags   = GraphicObject_SizeFlagsX; /* X axis only */
   class->Render      = StringGadget_Render;
   class->ClaimEvent  = StringGadget_ClaimEvent;
   class->Respond     = StringGadget_ClaimEvent;
   class->Refresh     = StringGadget_Refresh;
   class->Activate    = StringGadget_Activate;
   class->isActive    = NULL;
   class->Value       = StringGadget_Value;
   class->SetValue    = StringGadget_SetValue;

#ifdef BUILDER
   class->BuilderMethods = &StringGadget_bm;
   go_InitBuilderMethods( &StringGadget_bm );
   StringGadget_bm.New       = StringGadget_New;
   StringGadget_bm.WriteCode = StringGadget_WriteCode;
   StringGadget_bm.PropEdit  = StringGadget_PropEdit;
#endif
}


struct ValuatorClass *StringGadgetClass( void )
{
   if (! StringGadget_elaborated)
   {
      StringGadgetClass_Init( &StringGadget_Class );
      StringGadget_elaborated = TRUE;
   }

   return &StringGadget_Class;
}



void StringGadget_Init( StringGadget *self,
                        PIXELS        LeftEdge,
                        PIXELS        TopEdge,
                        PIXELS        Width,
                        USHORT        nChars,
                        pcg_3DPens    Pens,
                        char         *label )
{
   struct StringInfo *stringinfo;
   AlignInfo ainfo;


   EmbossedGadget_Init( self, LeftEdge, TopEdge, Width, 0,
         GADGHCOMP, RELVERIFY, STRGADGET, Pens, NULL );

   self->isa             = StringGadgetClass();
   Afree( self->BoxBorder );
   self->BoxBorder       = (pcg_3DBox *) Acalloc(1, sizeof(pcg_3DBevel));

   SetLocation( self, LeftEdge, TopEdge );
   SetSize( self, Width, 0 );

   ainfo = TextAlignment(self);
   SetTextAlignment( self, tx_OUTSIDE | tx_LEFT | tx_YCENTER,
      ainfo.Xpad, ainfo.Ypad );


   stringinfo = (struct StringInfo *) Acalloc(1, sizeof(struct StringInfo));
   stringinfo->BufferPos  = 0;
   stringinfo->DispPos    = 0;
   stringinfo->MaxChars   = nChars+1;
   stringinfo->Buffer     = Acalloc( 1, nChars+1 );
   stringinfo->UndoBuffer = NULL;

   self->g.GadgetRender  = (APTR) &self->BoxBorder->TopLeft;
   self->g.SelectRender  = NULL;
   self->g.GadgetText    = NULL;
   self->g.MutualExclude = 0L;
   self->g.SpecialInfo   = (APTR) stringinfo;

   SetTitle( self, label );
}

