(*************************************************************************

     $RCSfile: BoopsiUtil.mod $
  Description: BOOPSI support routines.
     Requires: ClassFace.obj must be explicitly linked with the program.

   Created by: fjc (Frank Copeland)
    $Revision: 3.2 $
      $Author: fjc $
        $Date: 1994/08/08 16:10:45 $

  Copyright © 1994, Frank Copeland.
  This file is part of the Oberon-A Library.
  See Oberon-A.doc for conditions of use and distribution.

*************************************************************************)

MODULE BoopsiUtil;

(*
** $C- CaseChk       $I- IndexChk  $L+ LongAdr   $N- NilChk
** $P- PortableCode  $R- RangeChk  $S- StackChk  $T- TypeChk
** $V- OvflChk       $Z- ZeroVars
*)

IMPORT E := Exec, U := Utility, I := Intuition, SYS := SYSTEM;

(*
** These procedures are duplicates of the ones found in Module Intuition.
** They are repeated here so that this module can be used in place of
** AmigaOberon's Classface.mod.
*)

(*------------------------------------*)
PROCEDURE InstData* (cl : I.IClassPtr; o : I.ObjectPtr) : E.APTR;
BEGIN
  RETURN SYS.VAL (E.APTR, (SYS.VAL(LONGINT,o) + LONG(cl.instOffset)));
END InstData;

(*------------------------------------*)
PROCEDURE SizeOfInstance* (cl : I.IClassPtr) : LONGINT;
BEGIN
  RETURN cl.instOffset + cl.instSize + SIZE(I.Object);
END SizeOfInstance;

(*------------------------------------*)
PROCEDURE OClass* (o : I.ObjectPtr) : I.IClassPtr;
BEGIN
  o := SYS.VAL (I.ObjectPtr, SYS.VAL (LONGINT, o) - SIZE (I.Object));
  RETURN o.class
END OClass;

(*
** The following declarations are interfaces to procedures in
** ClassFace.obj, created by assembling ClassFace.asm. ClassFace.obj
** must be explicitly linked with the program in order to call these
** procedures. See the "Foreign Code" section in OC.doc.
**
** These procedures are replacements for those in Commodore's
** amiga.lib and small.lib.
**
** Thanks to Albert Weinert for providing the assembly source code.
*)

(*
** DoMethod( o, method_id, param1, param2, ... )
** Invoke upon an object the method function defined by an object's class.
** This function is the only one that you should use unless you are
** implementing a class.
*)

PROCEDURE DoMethodA * ["_a_DoMethodA"]
  ( obj    [10] : I.ObjectPtr;
    VAR msg [9] : I.Msg )
  : E.APTR;

PROCEDURE DoMethod * ["_a_DoMethodA"]
  ( obj [10]  : I.ObjectPtr;
    msg  [9]..: SYS.LONGWORD )
  : E.APTR;

(*
** DoSuperMethod( cl, o, method_id, param1, param2, ... )
** Invoke upon an object the method defined for the superclass
** of the class specified.  In a class implementation, you
** are passed a pointer to the class you are implementing, which
** you pass to this function to send a message to the object
** considered as a member of your superclass.
*)

PROCEDURE DoSuperMethodA * ["_a_DoSuperMethodA"]
  ( cl      [8] : I.IClassPtr;
    obj    [10] : I.ObjectPtr;
    VAR msg [9] : I.Msg )
  : E.APTR;

PROCEDURE DoSuperMethod * ["_a_DoSuperMethodA"]
  ( cl   [8]  : I.IClassPtr;
    obj [10]  : I.ObjectPtr;
    msg  [9]..: SYS.LONGWORD )
  : E.APTR;

(*
** CoerceMethod( cl, o, method_id, param1, param2, ... );
** Invoke upon the given object a method function for whatever
** specified class.  This is sort of the primitive basis behind
** DoMethod and DoSuperMethod.
*)

PROCEDURE CoerceMethodA * ["_a_CoerceMethodA"]
  ( cl      [8] : I.IClassPtr;
    obj    [10] : I.ObjectPtr;
    VAR msg [9] : I.Msg );

PROCEDURE CoerceMethod * ["_a_CoerceMethodA"]
  ( cl   [8]  : I.IClassPtr;
    obj [10]  : I.ObjectPtr;
    msg  [9]..: SYS.LONGWORD );

(*
** SetSuperAttrs( cl, o, tag1, data1, ..., TAG_END );
** A useful varargs conversion to the proper OM_SET method.
*)

PROCEDURE SetSuperAttrsA * ["_a_SetSuperAttrs"]
  ( cl   [8] : I.IClassPtr;
    obj [10] : I.ObjectPtr;
    tags [9] : ARRAY OF U.TagItem )
  : E.APTR;

PROCEDURE SetSuperAttrs * ["_a_SetSuperAttrs"]
  ( cl   [8]  : I.IClassPtr;
    obj [10]  : I.ObjectPtr;
    tags [9]..: U.Tag )
  : E.APTR;

END BoopsiUtil.
