PageRenderTime 21ms CodeModel.GetById 11ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/build45/harbour/contrib/libnf/ontick.c

#
C | 139 lines | 57 code | 23 blank | 59 comment | 10 complexity | 82eac70d606d421f7d32eb9b46c51a36 MD5 | raw file
  1/*
  2 * File......: ONTICK.C
  3 * Author....: Ted Means
  4 * CIS ID....: 73067,3332
  5 *
  6 * This function is an original work by Ted Means and is placed in the
  7 * public domain.
  8 *
  9 * Modification history:
 10 * ---------------------
 11 *
 12 *    Rev 1.0   01 Jan 1995 03:01:00   TED
 13 * Initial release
 14 */
 15
 16
 17/*  $DOC$
 18 *  $FUNCNAME$
 19 *     FT_OnTick()
 20 *  $CATEGORY$
 21 *     Event
 22 *  $ONELINER$
 23 *     Evaluate a designated code block at a designated interval.
 24 *  $SYNTAX$
 25 *     FT_OnTick( bCode, nInterval )
 26 *  $ARGUMENTS$
 27 *     <bCode> is the code block to evaluate.
 28 *     <nInterval> is the number of clock ticks to wait between
 29 *                 evaluations of the code block.
 30 *  $RETURNS$
 31 *     NIL
 32 *  $DESCRIPTION$
 33 *     This function effectively allows you to run tasks in the background
 34 *     by transparently and periodically calling a designated routine.
 35 *
 36 *     To halt the execution of the background function, call FT_OnTick()
 37 *     with no arguments.
 38 *
 39 *     This function makes heavy use of several undocumented internal
 40 *     routines.  If this fact makes you uncomfortable then don't use
 41 *     this function, you quivering sack of cowardly slime.
 42 *  $EXAMPLES$
 43 *
 44 *     // Set up a self-updating on-screen clock
 45 *
 46 *     FT_OnTick( "CLOCK", 9 )
 47 *
 48 *     procedure Clock
 49 *
 50 *     local nRow := Row()
 51 *     local nCol := Col()
 52 *
 53 *     @ 0, 0 say Time()
 54 *
 55 *     SetPos( nRow, nCol )
 56 *
 57 *     return
 58 *
 59 *  $SEEALSO$
 60 *  $END$
 61 */
 62
 63#include <extend.api>
 64#include <item.api>
 65#include <cpmi.h>
 66
 67typedef union
 68{
 69   long far * Address;
 70   struct
 71   {
 72      unsigned int Offset;
 73      unsigned int Segment;
 74   } Pointer;
 75} LONGPTR;
 76
 77void cdecl _evLow( unsigned int, void *, unsigned int );
 78void cdecl _bcopy( void *, void *, unsigned int );
 79
 80static long far Ticks = 0;
 81static long far Interval = 1;
 82static ITEM far codeBlock;
 83static char inProgress = 0;
 84
 85static void cdecl TickTock( void )
 86{
 87   auto unsigned int ProtMode = cpmiIsProtected();
 88   auto LONGPTR Timer;
 89   auto EVALINFO eval;
 90
 91   if ( inProgress ) return;
 92
 93   inProgress = 1;
 94
 95   if ( ProtMode )
 96   {
 97      Timer.Pointer.Segment = cpmiProtectedPtr( ( long * ) ( 0x0000046C ), sizeof( long ) );
 98      Timer.Pointer.Offset  = 0;
 99
100      if ( Timer.Pointer.Segment == 0 ) goto Exit;
101   }
102   else
103      Timer.Address = ( long * ) ( 0x0000046C );
104
105   if ( *Timer.Address >= ( Ticks + Interval ) ||
106      ( *Timer.Address < Ticks ) )
107   {
108      Ticks = *Timer.Address;
109
110      _evalNew( &eval, codeBlock );
111
112      _itemRelease( _evalLaunch( &eval ) );
113   }
114
115   if ( ProtMode ) cpmiFreeSelector( Timer.Pointer.Segment );
116
117   Exit: inProgress = 0;
118
119   return;
120}
121
122
123CLIPPER FT_OnTick( void )
124{
125   if ( _itemType( codeBlock ) == BLOCK ) _itemRelease( codeBlock );
126
127   codeBlock = _itemParam( 1 );
128
129   if ( _itemType( codeBlock ) == BLOCK )
130   {
131      Interval = _parnl( 2 );
132
133      _evLow( 5, TickTock, TRUE );
134   }
135   else
136      _evLow( 5, TickTock, FALSE );
137
138   return;
139}