home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / text / tex / pastex / source / driver / show / amiga / pgmodel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-07  |  11.0 KB  |  425 lines

  1. /* mymodelclass.c -- :ts=8
  2.  * Example of a simple subclass of "modelclass".
  3.  * It maintains an integer "current value", which
  4.  * it keeps between 0 and some specified maximum.
  5.  */
  6.  
  7. /*
  8. Copyright (c) 1989, 1990 Commodore-Amiga, Inc.
  9.  
  10. Executables based on this information may be used in software
  11. for Commodore Amiga computers. All other rights reserved.
  12. This information is provided "as is"; no warranties are made.
  13. All use is at your own risk, and no liability or responsibility
  14. is assumed.
  15. */
  16.  
  17. #include <stdio.h>
  18. #include <dos.h>
  19.  
  20. #include <exec/types.h>
  21. #include <utility/tagitem.h>
  22. #include <intuition/intuition.h>
  23.  
  24. #include <intuition/classusr.h>
  25. #include <intuition/imageclass.h>
  26. #include <intuition/gadgetclass.h>
  27. #include <intuition/cghooks.h>
  28. #include <intuition/icclass.h>
  29. #include <intuition/classes.h>
  30.  
  31. #include <clib/intuition_protos.h>
  32. #include <clib/utility_protos.h>
  33. #include <pragmas/intuition_pragmas.h>
  34. #include <pragmas/utility_pragmas.h>
  35.  
  36. extern ULONG __stdargs DoSuperMethodA( struct IClass *cl, Object *obj, Msg message );
  37. extern ULONG __stdargs DoMethod( Object *obj, unsigned long MethodID, ... );
  38.  
  39.  
  40. #include "pgmodel.h"        /* attributes are defined there    */
  41.  
  42. extern struct Library   * UtilityBase;
  43. extern struct Library    * IntuitionBase;
  44.  
  45.  
  46.  
  47. #ifdef printf
  48. #undef printf
  49. #endif
  50.  
  51. #define printf kprintf
  52. int kprintf(char * fmt, ...);
  53.  
  54. #define DK(x)    ;
  55. //#define DK(x)    x
  56.  
  57. /* private class    */
  58. #define MYCLASSID    (NULL)
  59. #define SUPERCLASSID    MODELCLASS
  60.  
  61. struct MyModData    {
  62.     long        mmd_RegA4;        /* Register A4 */
  63.     ULONG    mmd_CurrentValue;
  64.     ULONG    mmd_Range;        /* current value <= range-1    */
  65.     ULONG    mmd_LowerBorder;    /* current value >= lower border */
  66.     ULONG    mmd_LastIncSecs;    /* timer tick of last INC operation */
  67.     ULONG    mmd_LastIncMicros;    /* timer tick of last INC operation */
  68. };
  69.  
  70. /*
  71.  * Achtung!!
  72.  *
  73.  * Der Value liegt IMMER im Bereich zwischen 0..range-1 !!
  74.  *
  75.  * Der LowerBorder geht hier nicht ein, der ist nur fuer die ANZEIGE
  76.  * im Integer-Gadget wichtig!
  77.  *
  78.  * Uups..brauch ich ihn ueberhaupt dort...
  79.  *
  80.  * Das Integer-Gadget muss ich noch durch ein eigenes ersetzen, das
  81.  * immer was anderes anzeigt, als es eigentlich soll!
  82.  * Und zwar soll es die Werte immer durch zwei Funktionen jagen...
  83.  * ValueToShow() und ShowToValue().
  84.  *
  85.  * Dort geht dann entweder der LowerBorder ein (sprich es wird immer
  86.  * der LowerBorder fuer die Anzeige addiert) oder aber es wird eine
  87.  * Funktion verwendet, die eine Umwandlung Phy--Real Seitenzahlen macht.
  88.  *
  89.  */
  90.  
  91.  
  92.  
  93. static ULONG __stdargs dispatchMyMod( Class * cl, Object * o, Msg msg );
  94. static int   setMyModAttrs( Class * cl, Object * o, struct opSet * msg );
  95. static ULONG getMyModAttr( Class * cl, Object * o, struct opGet * msg );
  96. static ULONG notifyAttrChanges( Object * o, void * ginfo, ULONG flags, ULONG tag1, ... );
  97. static void  dumpTagList( UBYTE * str, struct TagItem * tags );
  98.  
  99.  
  100. static ULONG __asm hookEntry( register __a0 struct Hook * h, 
  101.                   register __a2 void * o, 
  102.                   register __a1 void * msg )
  103. {
  104.   return ((*(ULONG (* __stdargs)())h->h_SubEntry)(h, o, msg));
  105. }
  106.  
  107.  
  108.  
  109.  
  110. Class    * initMyModClass(void)
  111. {
  112.     Class    *cl;
  113.  
  114.     if ( cl =  MakeClass( MYCLASSID, 
  115.         SUPERCLASSID, NULL,        /* superclass is public      */
  116.          sizeof ( struct MyModData ),
  117.         0 ))
  118.     {
  119.     /* initialize the cl_Dispatcher Hook    */
  120.     cl->cl_Dispatcher.h_Entry = (unsigned long (* )()) hookEntry;
  121.     cl->cl_Dispatcher.h_SubEntry = (ULONG (* )()) dispatchMyMod;
  122.     cl->cl_Dispatcher.h_Data = (VOID *) 0xFACE;    /* unused */
  123.     }
  124.     return ( cl );
  125. }
  126.  
  127. int freeMyModClass( Class * cl )
  128. {
  129.     return ( FreeClass( cl )  );
  130. }
  131.  
  132.  
  133.  
  134.  
  135. static ULONG __stdargs dispatchMyMod( Class * cl, Object * o, Msg msg )
  136. {
  137.     Object    *newobj;
  138.     LONG    oldval;
  139.     ULONG    oldrng;
  140.     LONG    oldlob;
  141.     ULONG    notify_msg_flags = 0;
  142.     ULONG    interim_flag;
  143.  
  144.     struct MyModData    *mmd;
  145.  
  146.     DK( printf("mymodel dispatcher, method ID %lx\n", msg->MethodID ) );
  147.  
  148.     mmd = INST_DATA( cl, o );
  149.  
  150.     switch ( msg->MethodID )
  151.     {
  152.     /* use superclass defaults for everything else */
  153.     case OM_NEW:
  154.     DK( printf("mymodel: OM_NEW\n") );
  155.     if( newobj = (Object *) DoSuperMethodA( cl, o, msg ) )
  156.     {
  157.         DK( printf("new model object at %lx\n", newobj ) );
  158.         /* initialize instance data (they start life as 0)    */
  159.         mmd = INST_DATA( cl, newobj );
  160.         mmd->mmd_RegA4 = getreg(REG_A4);
  161.         setMyModAttrs( cl, newobj, (struct opSet *)msg );
  162.     }
  163.     return ( (ULONG) newobj );
  164.  
  165.     case OM_GET:
  166.         putreg(REG_A4, mmd->mmd_RegA4);
  167.     DK( printf("mymodel: OM_GET\n") );
  168.     return ( (ULONG) getMyModAttr( cl, o, (struct opGet *)msg ) );
  169.  
  170.     case OM_SET:
  171.     case OM_UPDATE:
  172.         putreg(REG_A4, mmd->mmd_RegA4);
  173.     DK( printf("mymod UPDATE/SET\n" ) );
  174.     if ( ! DoSuperMethodA( cl, o, (Msg)ICM_CHECKLOOP ) ) 
  175.     {
  176.         /* let the superclass see whatever it wants from OM_SET,
  177.          * such as ICA_TARGET, ICA_MAP, and so on.  For OM_NOTIFY,
  178.          * however, we control all traffic and issue notification
  179.          * specifically for the attributes we're interested in.
  180.          */
  181.         if ( msg->MethodID == OM_SET )
  182.         {
  183.         DK( printf("mymod update is actually OM_SET\n"));
  184.         DoSuperMethodA( cl, o, msg );
  185.         }
  186.         else
  187.         {
  188.         /* these flags aren't present in the message of OM_SET    */
  189.         notify_msg_flags =  ((struct opUpdate *)msg)->opu_Flags;
  190.         }
  191.  
  192.         /*
  193.          * I'll be wanting to know this is an "interim" message
  194.          * or a final report (which I always want to send, even
  195.          * if the value of mmd_CurrentValue hasn't changed).
  196.          */
  197.         interim_flag =  notify_msg_flags & OPUF_INTERIM;
  198.  
  199.         /* Now set possibly new value of mmd_CurrentVal, and
  200.          * maybe a range change.
  201.          * Only send a notification message along for values of
  202.          * interest that have changed.
  203.          */
  204.  
  205.         /* save 'em    */
  206.         oldval = mmd->mmd_CurrentValue;
  207.         oldrng = mmd->mmd_Range;
  208.         oldlob = mmd->mmd_LowerBorder;
  209.  
  210.         /* change 'em, only if changed (or if
  211.          * a "non-interim" message.
  212.          */
  213.         if ( setMyModAttrs( cl, o, (struct opSet *)msg ) || ! interim_flag )
  214.         {
  215.             Tag    rangetag;
  216.             Tag    currvaltag;
  217.             Tag    lowbtag;
  218.  
  219. /* if condition is false, replace tag with TAG_IGNORE    */
  220. #define XTAG( expr, tagid ) ((expr)? (tagid): TAG_IGNORE)
  221.  
  222.         rangetag = (oldrng!=mmd->mmd_Range)? MYMODA_RANGE: TAG_IGNORE;
  223.         if ( ! interim_flag || (oldval != mmd->mmd_CurrentValue) )
  224.         {
  225.             currvaltag = MYMODA_CURRVAL;
  226.         }
  227.         else
  228.         {
  229.             currvaltag = TAG_IGNORE;
  230.         }
  231.         
  232.         lowbtag = (oldlob!=mmd->mmd_LowerBorder)? MYMODA_LOWERB: TAG_IGNORE;
  233.  
  234.  
  235.         DK( printf("mymod: sending notification\n") );
  236.  
  237.         /* Pass along GInfo, if any, so gadgets can redraw
  238.          * themselves.  Pass along opu_Flags, so that the
  239.          * application will know the difference between
  240.          * and interim message and a final message
  241.          */
  242.         notifyAttrChanges( o, ((struct opSet *)msg)->ops_GInfo,
  243.             interim_flag,
  244.             rangetag,    mmd->mmd_Range,
  245.             currvaltag,    mmd->mmd_CurrentValue,
  246.             lowbtag,    mmd->mmd_LowerBorder,
  247.             TAG_END );
  248.         }
  249.         DK( else printf("setMyModAttrs returnes 'nochange'\n"));
  250.     }
  251.     DK( else printf("Loop Check violation!\n"));
  252.     break;
  253.  
  254.     case OM_NOTIFY:
  255.         putreg(REG_A4, mmd->mmd_RegA4);
  256.         DK( printf("mymod: forwarding OM_NOTIFY to superclass modelclass\n"));
  257.     case OM_DISPOSE:
  258.     default:
  259.         putreg(REG_A4, mmd->mmd_RegA4);
  260.     DK( printf("let superclass handle it\n"));
  261.     return ( (ULONG) DoSuperMethodA( cl, o, msg ) );
  262.     }
  263.     return ( 1 );
  264. }
  265.  
  266. static int setMyModAttrs( Class * cl, Object * o, struct opSet * msg )
  267. {
  268.     struct TagItem    *tags = msg->ops_AttrList;
  269.     struct MyModData    *mmd;
  270.     int            changes = FALSE;
  271.     LONG        newval;
  272.     LONG        newlob;
  273.     ULONG        newrng;
  274.  
  275.     mmd = INST_DATA( cl, o );
  276.  
  277.     DK( printf("setMyModAttrs, object %lx\n", o ) );
  278.     DK( dumpTagList( "mymod attr tags", tags ));
  279.  
  280.     newrng =  GetTagData( MYMODA_RANGE, mmd->mmd_Range, tags );
  281.  
  282.     if ( mmd->mmd_Range != newrng )
  283.     {
  284.     DK( printf( "mymod: range has changed value to %ld\n",
  285.         mmd->mmd_Range ));
  286.     mmd->mmd_Range =  newrng;
  287.     changes = TRUE;
  288.     }
  289.  
  290.     /* validity check    */
  291.     if ( mmd->mmd_Range == 0 )
  292.     {
  293.     mmd->mmd_Range = 1;
  294.     changes = TRUE;
  295.     }
  296.     
  297.  
  298.     newlob = GetTagData( MYMODA_LOWERB, mmd->mmd_LowerBorder, tags );
  299.  
  300.     if ( mmd->mmd_LowerBorder != newlob )
  301.     {
  302.     DK( printf( "mymod: lower border has changed value to %ld\n",
  303.         mmd->mmd_LowerBorder ));
  304.     mmd->mmd_LowerBorder =  newlob;
  305.     changes = TRUE;
  306.     }
  307.  
  308.  
  309.     DK( printf("lower border is %ld, range is %ld\n", mmd->mmd_LowerBorder, mmd->mmd_Range ) );
  310.  
  311.     /* start with original value    */
  312.     newval =  mmd->mmd_CurrentValue;
  313.  
  314.     DK( printf("original currval %ld\n", mmd->mmd_CurrentValue ) );
  315.  
  316.     /* increment/decrement in response to strobes    */
  317.     if ( GetTagData( MYMODA_INCRSTROBE, 0, tags ) > 0 )
  318.     {
  319.         ULONG secs, micros;
  320.         ULONG diff;
  321.  
  322.     CurrentTime(&secs, µs);
  323.     
  324.     diff = (secs - mmd->mmd_LastIncSecs) * 1000000 + micros - mmd->mmd_LastIncMicros;
  325.     
  326.     if (diff > 150000) {
  327.       mmd->mmd_LastIncSecs   = secs;
  328.       mmd->mmd_LastIncMicros = micros;
  329.       newval++;
  330.       DK( printf("strobe increment newval to %ld\n", newval ) );
  331.     }
  332.     }
  333.     if ( GetTagData( MYMODA_DECRSTROBE, FALSE, tags ) > 0 )
  334.     {
  335.         ULONG secs, micros;
  336.         ULONG diff;
  337.  
  338.     CurrentTime(&secs, µs);
  339.     
  340.     diff = (secs - mmd->mmd_LastIncSecs) * 1000000 + micros - mmd->mmd_LastIncMicros;
  341.     
  342.     if (diff > 150000) {
  343.       mmd->mmd_LastIncSecs   = secs;
  344.       mmd->mmd_LastIncMicros = micros;
  345.         if ( newval > 0) newval--;
  346.       DK( printf("strobe decrement newval to %ld\n", newval ) );
  347.     }
  348.     }
  349.  
  350.     /* look at "absolute" setting last    */
  351.     newval = GetTagData( MYMODA_CURRVAL, newval, tags );
  352.  
  353.     DK( printf("unconstrained newval %ld\n", newval ) );
  354.  
  355.     /* limit mmd_CurrentValue to mmd_Range-1    */
  356.     if ( newval < 0 ) newval = 0;
  357.     if ( newval > (mmd->mmd_Range-1) )  newval = mmd->mmd_Range - 1;
  358.  
  359.     DK( printf( "final: new current value %ld\n", newval ));
  360.  
  361.     if ( mmd->mmd_CurrentValue != newval )
  362.     {
  363.         mmd->mmd_CurrentValue = newval;
  364.     DK( printf( "mymod: value has changed to %ld\n",
  365.         mmd->mmd_CurrentValue ));
  366.     changes = TRUE;
  367.     }
  368.  
  369.     return ( changes );
  370. }
  371.  
  372. static ULONG getMyModAttr( Class * cl, Object * o, struct opGet * msg )
  373. {
  374.     struct MyModData    *mmd;
  375.  
  376.     mmd = INST_DATA( cl, o );
  377.  
  378.     switch ( msg->opg_AttrID )
  379.     {
  380.     case MYMODA_CURRVAL:
  381.     *msg->opg_Storage = mmd->mmd_CurrentValue;
  382.     break;
  383.     case MYMODA_RANGE:
  384.     *msg->opg_Storage = mmd->mmd_Range;
  385.     break;
  386.     case MYMODA_LOWERB:
  387.     *msg->opg_Storage = mmd->mmd_LowerBorder;
  388.     break;
  389.     default:
  390.     /* I don't recognize this one, let the superclass try    */
  391.     return ( DoSuperMethodA( cl, o, (Msg)msg ) );
  392.     }
  393.     return ( TRUE );
  394. }
  395.  
  396. /*
  397.  * a convenient way to construct and send an OM_NOTIFY message
  398.  */
  399. static ULONG notifyAttrChanges( Object * o, void * ginfo, ULONG flags, ULONG tag1, ... )
  400. {
  401.     return ( DoMethod( o, OM_NOTIFY, &tag1, ginfo, flags ) );
  402. }
  403.  
  404.  
  405.  
  406. /*
  407.  * DEBUG
  408.  */
  409. static void dumpTagList( UBYTE * str, struct TagItem * tags )
  410. {
  411.     struct TagItem    *ti;
  412.     struct TagItem    *NextTagItem();
  413.  
  414.     printf("\n");
  415.     if ( str ) printf( "%s\n", str );
  416.     printf("tags at %lx, prevtag %08lx - %08lx\n",
  417.         tags, tags[-1].ti_Tag, tags[-1].ti_Data );
  418.  
  419.  
  420.     while ( ti = NextTagItem( &tags ) )
  421.     {
  422.     printf("%08lx - %08lx\n", ti->ti_Tag, ti->ti_Data );
  423.     }
  424. }
  425.