revampage de rotatecursor

git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@2491 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
master
Damien Doligez 1999-11-08 17:11:23 +00:00
parent 43240c1150
commit 8ccb0ebe94
2 changed files with 97 additions and 31 deletions

View File

@ -11,29 +11,35 @@
/* $Id$ */
/* Cursor rotation for MPW tools (ocamlrun and ocamlyacc) */
/* Rotatecursor library, written by Damien Doligez
This file is in the public domain.
version 1.7
See rotatecursor.h for documentation.
*/
#include <CursorCtl.h>
#include <MacTypes.h>
#include <stdlib.h>
#include <Timer.h>
#include <Types.h>
#include "rotatecursor.h"
int volatile have_to_interact;
typedef struct {
TMTask t;
int volatile *p1;
int volatile *p2;
} Xtmtask;
static Xtmtask mytmtask;
int volatile rotatecursor_flag = 1;
static int rotatecursor_inited = 0;
static int rotatecursor_period = 50;
static Xtmtask rotatecursor_tmtask;
#if GENERATINGCFM
static void mytimerproc (Xtmtask *p)
static void rotatecursor_timerproc (Xtmtask *p)
{
if (p->p1 != NULL && *(p->p1) == 0) *(p->p1) = 1;
if (p->p2 != NULL && *(p->p2) == 0) *(p->p2) = 1;
@ -43,38 +49,59 @@ static void mytimerproc (Xtmtask *p)
extern Xtmtask *getparam() ONEWORDINLINE(0x2009); /* MOVE.L A1, D0 */
static void mytimerproc (void)
static void rotatecursor_timerproc (void)
{
register Xtmtask *p = getparam ();
if (p->p1 != NULL) *(p->p1) = 1;
if (p->p2 != NULL) *(p->p2) = 1;
if (p->p1 != NULL && *(p->p1) == 0) *(p->p1) = 1;
if (p->p2 != NULL && *(p->p2) == 0) *(p->p2) = 1;
}
#endif /* GENERATINGCFM */
static void remove_task (void)
static void rotatecursor_remove_task (void)
{
RmvTime ((QElemPtr) &mytmtask);
RmvTime ((QElemPtr) &rotatecursor_tmtask);
}
void rotatecursor_init (int volatile *p1)
static void rotatecursor_init (void)
{
if (rotatecursor_inited) return;
InitCursorCtl (NULL);
mytmtask.t.tmAddr = NewTimerProc (mytimerproc);
mytmtask.t.tmWakeUp = 0;
mytmtask.t.tmReserved = 0;
mytmtask.p1 = p1;
mytmtask.p2 = &have_to_interact;
InsTime ((QElemPtr) &mytmtask);
PrimeTime ((QElemPtr) &mytmtask, 1);
atexit (remove_task);
rotatecursor_tmtask.t.tmAddr = NewTimerProc (rotatecursor_timerproc);
rotatecursor_tmtask.t.tmWakeUp = 0;
rotatecursor_tmtask.t.tmReserved = 0;
rotatecursor_tmtask.p1 = NULL;
rotatecursor_tmtask.p2 = &rotatecursor_flag;
InsTime ((QElemPtr) &rotatecursor_tmtask);
PrimeTime ((QElemPtr) &rotatecursor_tmtask, 1);
atexit (rotatecursor_remove_task);
rotatecursor_inited = 1;
}
void rotatecursor_options (int volatile *p1, int period)
{
if (!rotatecursor_inited) rotatecursor_init ();
rotatecursor_tmtask.p1 = p1;
rotatecursor_period = period;
}
int rotatecursor_action (int reverse)
{
PrimeTime ((QElemPtr) &mytmtask, 50); /* 20 Hz */
if (!rotatecursor_inited) rotatecursor_init ();
rotatecursor_flag = 0;
PrimeTime ((QElemPtr) &rotatecursor_tmtask, rotatecursor_period);
RotateCursor (reverse ? -32 : 32);
return 0;
}

View File

@ -5,29 +5,68 @@
/* Damien Doligez, projet Para, INRIA Rocquencourt */
/* */
/* Copyright 1996 Institut National de Recherche en Informatique et */
/* Automatique. Distributed only by permission. */
/* en Automatique. Distributed only by permission. */
/* */
/***********************************************************************/
/* $Id$ */
/* Cursor rotation for MPW tools (ocamlrun and ocamlyacc) */
/* Rotatecursor library, written by Damien Doligez
This file is in the public domain.
version 1.7
The goal of this library is to help implement cooperative multitasking
for MPW tools: to make sure that your program calls RotateCursor often
enough (about 20 times per second) but not too often (to avoid a big
slowdown). It can also be used in applications as soon as you have
an implementation of InitCursorCtl and RotateCursor (which is not hard
to do).
Simplified usage:
1. #include this file where appropriate
2. Insert the following line in the inner loop(s) of your program:
ROTATECURSOR_MAGIC ();
The overhead of this macro is only a few CPU cycles, so it can be
used without problem even in a tight loop.
*/
#ifndef _rotatecursor_
#define _rotatecursor_
/* [have_to_interact] will be magically set to 1 when the time comes to
call [rotatecursor_action]. */
extern int volatile have_to_interact;
/* [*p1] and [have_to_interact] will be set to 1 when the time comes to
call [rotatecursor_action]. If p1 is not used, pass it as NULL.
/* [rotatecursor_flag] will be automagically set to 1 when the time comes
to call [rotatecursor_action].
*/
void rotatecursor_init (int volatile *p1);
extern int volatile rotatecursor_flag;
/* Use [rotatecursor_options] to set advanced parameters:
1. [p1] is a pointer to another variable that will be set to 1 when
the time is up, unless it is already nonzero. Typical use is when
you already have a variable in your program that is set
asynchronously for something else, and you want to avoid testing
two different variables in your inner loop. Pass NULL if you don't
need this feature.
2. [period] is the interval (in milliseconds) between calls to
RotateCursor. Reasonable values are between 10 and 200;
the default is 50.
*/
void rotatecursor_options (int volatile *p1, int period);
/* [reverse] is 0 to rotate the cursor clockwise, anything else to
rotate counterclockwise. This function always returns 0.
rotate counterclockwise. This function resets [rotatecursor_flag]
to 0.
This function always returns 0. It returns an int so you can use
it in an expression as well as a statement. Useful for some macros.
*/
int rotatecursor_action (int reverse);
/* Simple interface to [rotatecursor_flag] and [rotatecursor_action].
Can be used as a statement (followed by a semicolon) or in an
expression (followed by a comma).
*/
#define ROTATECURSOR_MAGIC() (rotatecursor_flag ? rotatecursor_action (0) : 0)
#endif /* _rotatecursor_ */