Newsgroups: comp.sys.amiga.programmer
Subject: Boopsi custom gadget problem
From: cree@elec.canterbury.ac.nz (Michael Cree)
Date: 31 Aug 92 13:44:41 +1200
Organization: Electrical Engineering, University of Canterbury, New Zealand
Keywords: Boopsi, custom gadget.
Summary: Having problems implementing custom gadget. Require help.
X-Newsreader: Tin 1.1 PL5

I am having a problem implementing a string gadget as a subclass of
'strgclass'. The idea is to to have a longint gadget that limits the
input value to be within minimun and maximun values. On a go inactive
command it checks the value and if not in range calls DoSuperMethod on
the superclass with the command OM_SET to put it back in range.

This, in fact, works from the viewpoint of the user running the code,
however a check of memory afterwards finds 8 bytes not freed. I then
run mungwall which illuminates the problem further. It reports a
mismatched FreeMem of 15 bytes when it should be 20 bytes (hence the
lost 8 bytes) and then causes the programme to crash with a CPU trap
(think it was illegal address violation). This all happens when the
programme is exiting and deallocating the string gadget class I
implemented. Using the owner command on the address from which the
FreeMem was called reports that it occured somewhere in the intuition
library ROM code, but doesn't identify which routine.

I am at complete loss as to understanding why this is happening. Any
help would be appreciated. The code implementing the custom gadget
follows. It, at present, assumes the calling programme passes the tag
STRINGA_LongInt as part of the taglist when allocating an object.
Also, MSTRINGA_MinVal (MSTRINGA_MaxVal) is defined as one(two) plus the
user tag identifier. This was run on a basic A500+ (thus version 37
ROMS) with 1MB of chip, no fast memory  and a DataFlyer IDE hard drive.

Michael

-----------------------Code folows----->

/* For mstrgclass */

struct nlimits {                /* Structure to hold min and max values. */
   LONG min,max;
};

int GadgAct;                   /* These are flags for testing purposes. */
int GadgWhy;


Class *
initMStrGClass()
{
   ULONG hookEntry();
   Class *cl;
   Class *MakeClass();

   if ( cl =  MakeClass( NULL, "strgclass", NULL, sizeof(struct nlimits), 0 )) {
      cl->cl_Dispatcher.h_Entry = hookEntry;
      cl->cl_Dispatcher.h_SubEntry = dispatchMStrG;
      cl->cl_Dispatcher.h_Data = (VOID *) 0xFACE;
      GadgAct = 0;
   }
   return ( cl );
}



BOOL freeMStrGClass( cl )
Class *cl;
{
   return ( FreeClass( cl )  );
}



ULONG dispatchMStrG( cl, o, msg )
Class   *cl;
Object  *o;
Msg     msg;
{
   struct gpGoInactive *gpg;
   Object *no;
   struct nlimits *nl;
   struct opSet *ops;
   struct TagItem *ti;
   struct StringInfo *si;
   struct TagItem taglist[2];

   geta4();
   switch ( msg->MethodID ) {
   case OM_NEW:
      D(bug("Hit OM_NEW in gadget\n"));
      if (no = (Object *)DoSuperMethodA(cl,o,msg)) {
         D(bug( "  Got object at 0x%lx", no));
         nl = INST_DATA(cl, no);
         D(bug( " My data is at 0x%lx and of length %ld.\n",nl,cl->cl_InstSize));
         ops = (struct opSet *)msg;
         D(bug( "  Doing tagitems\n" ));
         if (ti = FindTagItem(MSTRINGA_MinVal,ops->ops_AttrList))
            nl->min = ti->ti_Data;
         else
            nl->min = 0x80000000;
         if (ti = FindTagItem(MSTRINGA_MaxVal,ops->ops_AttrList))
            nl->max = ti->ti_Data;
         else
            nl->max = 0x7fffffff;
      }
      D(bug("...Done\n"));
      return (ULONG)no;
   case OM_SET:
      D(bug( "Doing OM_SET ...\n"));
      nl = INST_DATA(cl, o);
      D(bug("  My data is at 0x%lx.\n",nl));
      ops = (struct opSet *)msg;
      if (ti = FindTagItem(MSTRINGA_MinVal,ops->ops_AttrList)) {
         D(bug( "   MSTRINGA_MinVal present.\n" ));
         nl->min = ti->ti_Data;
      }
      if (ti = FindTagItem(MSTRINGA_MaxVal,ops->ops_AttrList)) {
         D(bug( "   MSTRINGA_MaxVal present.\n" ));
         nl->max = ti->ti_Data;
      }
      if (ti = FindTagItem(STRINGA_LongVal,ops->ops_AttrList)) {
         if (ti->ti_Data < nl->min) ti->ti_Data = nl->min;
         if (ti->ti_Data > nl->max) ti->ti_Data = nl->max;
      }
      D(bug("...Done\n"));
      return ( (ULONG) DoSuperMethodA( cl, o, msg ) );
   case GM_GOINACTIVE:
      D(bug( "Doing GM_GOINACTIVE\n"));
      gpg = (struct gpGoInactive *)msg;
      GadgWhy = gpg->gpgi_Abort;
      nl = INST_DATA(cl, o);
      D(bug("  My data is at 0x%lx.\n",nl));
      si = ((struct Gadget *)o)->SpecialInfo;
      taglist[0].ti_Tag = STRINGA_LongVal;
      taglist[1].ti_Tag = TAG_DONE;
      if (si->LongInt < nl->min) {
         taglist[0].ti_Data = nl->min;
         DoSuperMethod(cl,o,OM_SET,taglist,gpg->gpgi_GInfo);
      }
      if (si->LongInt > nl->max) {
         taglist[0].ti_Data = nl->max;
         DoSuperMethod(cl,o,OM_SET,taglist,gpg->gpgi_GInfo);
      }
      D(bug( " Falling through now...\n"));
   case GM_GOACTIVE:
      GadgAct = (msg->MethodID == GM_GOACTIVE);
      D(bug("...Done\n"));
   default:
      return ( (ULONG) DoSuperMethodA( cl, o, msg ) );
   }

   return FALSE;
}

-----------------------------------------------------------------------------
Michael Cree                              Gold there is
cree@elec.canterbury.ac.nz                 and rubies in abundance;
                                          But lips that speak knowledge
                                           are a rare jewel. (Prov 20:15)
------------------------------------------------------------------------------
Xref: sparky comp.sys.amiga.programmer:12739 comp.sys.amiga.misc:13129