/*
 * !tpluslib.flex.h - Toolbox version of flex with dynamic areas
 *
 * Library is  Risc User 1996, the original flex code
 * is  Acorn Computers Ltd 1992 and has modifications which are
 *  Andy Armstrong 1994 and  Tony Howat 1996
 *
 * The TPlus library is *not* freeware and should not be distributed by
 * anyone other than Risc User. Those with an official copy of TPlus
 * (on a Risc User Magazine Disc, Special Disc, CD-ROM etc)
 * have an unlimited licence to link the library with their own progams.
 */

/*
 * Title  : flex.h
 * Purpose: provide memory allocation for interactive programs requiring
 *          large chunks of store. Such programs must respond to memory
 *          full errors.
 *
 */

#ifndef __flex_h
#define __flex_h
#ifdef __cplusplus
extern "C" {
#endif
typedef void **flex_ptr;


#define flex_CALLBACK

/* ----------------------------- flex_alloc -------------------------------
 * Description:   Allocates n bytes of store, obtained from the Wimp.
 *
 * Parameters:    flex_ptr anchor -- to be used to access allocated store
 *                int n -- number of bytes to be allocated
 * Returns:       0 == failure, 1 == success
 * Other Info:    You should pass the & of a pointer variable as the first
 *                parameter. The allocated store MUST then be accessed
 *                indirectly, through this, ie. (*anchor)[0] ..(*anchor)[n]
 *                This is important since  the allocated store may later be
 *                moved (it's a shifting heap!!). If there's not enough
 *                store returns zero leaving anchor unchanged.
 *
 */

int flex_alloc(flex_ptr anchor, int n);


/* ------------------------------ flex_free -------------------------------
 * Description:   Frees the previously allocated store.
 *
 * Parameters:    flex_ptr anchor -- pointer to allocated store
 * Returns:       void.
 * Other Info:    *anchor will be set to 0.
 *
 */

void flex_free(flex_ptr anchor);


/* ------------------------------- flex_size ------------------------------
 * Description:   Informs caller of the number of bytes allocated
 *
 * Parameters:    flex_ptr -- pointer to allocated store
 * Returns:       number of allocated bytes.
 * Other Info:    None.
 *
 */

int flex_size(flex_ptr);


/* --------------------------- flex_extend --------------------------------
 * Description:   Extend ot truncate the store area to have a new size.
 *
 * Parameters:    flex_ptr -- pointer to allocated store
 *                int newsize -- new size of store
 * Returns:       0 == failure, 1 == success.
 * Other Info:    None.
 *
 */

int flex_extend(flex_ptr, int newsize);


/* --------------------------- flex_midextend -----------------------------
 * Description:   Extend or truncate store, at any point.
 *
 * Parameters:    flex_ptr -- pointer to allocated store
 *                int at -- location within the allocated store
 *                int by -- extent
 * Returns:       0 == failure, 1 == success
 * Other Info:    If by is +ve, then store is extended, and locations above
 *                "at" are copied up by "by".
 *                If by is -ve, then store is reduced, and any bytes beyond
 *                "at" are copied down to "at"+"by".
 *
 */

int flex_midextend(flex_ptr, int at, int by);

#ifdef flex_CALLBACK

#ifndef BOOL
#define BOOL int
#define FALSE (0)
#define TRUE  (1)
#endif

/* AA: 30.9.94 */

/* --------------------------- flex_cbfunc --------------------------------
 * A function of this type may be registered for each flex block so that
 * the owner of the block can be notified when the block moves
 */

typedef void (*flex_cbfunc)(BOOL b4, void *handle);

/* --------------------------- flex_register -------------------------------
 * Register the function to be called when a block of moves
 */

void flex_register(flex_ptr anchor, flex_cbfunc cb, void *handle);

#endif


/* ---------------------------- flex_budge --------------------------------
 * Description:    Function to move flex store, when the C library needs
 *                 to extend the heap.
 *
 * Parameters:     int n -- number of bytes needed by C library
 *                 void **a -- address of acquired store.
 * Returns:        amount of store acquired.
 * Other Info:     Don't call this function directly, but register it
 *                 with the C library via:
 *                    _kernel_register_slotextend(flex_budge);
 *                 This will cause flex store to be moved up if the C
 *                 library needs to extend the heap.  Note that in this
 *                 state, you can only rely on pointers into flex blocks
 *                 across function calls which do not extend the stack and
 *                 do not call malloc.
 *                 The default state is flex_dont_budge, so, if required,
 *                 this function should be registered AFTER calling
 *                 flex_init().
 *
 */

extern int flex_budge(int n, void **a);


/* -------------------------- flex_dont_budge -----------------------------
 * Description:   Function to refuse to move flex store, when the C library
 *                needs to extend the heap.
 *
 * Parameters:    int n -- number of bytes needed by C library
 *                void **a -- address of acquired store.
 * Returns:       amount of store acquired (always 0).
 * Other Info:    Don't call this function directly, but register it
 *                with the C library via:
 *                   _kernel_register_slotextend(flex_dont_budge);
 *                If the C library needs to extend the heap, flex will
 *                refuse to move. This means that you can rely on pointers
 *                into flex blocks across function calls.
 *                This is the DEFAULT state after flex_init().
 *
 */

extern int flex_dont_budge(int n, void **a);

/* ---------------------------- flex_init ---------------------------------
 * Description:   Initialise store allocation module.
 *
 * Parameters:    void.
 * Returns:       void.
 * Other Info:    Either flex_init or flex_init_dynamic must be called
 *                before any other functions in this module.
 *
 */

extern void flex_init(void);

/* ------------------------- flex_init_dynamic ---------------------------
 * Description:   Initialise store allocation module, attempting to use
 *                dynamic areas if they are available.
 *
 * Parameters:    void.
 * Returns:       void.
 * Other Info:    Either flex_init or flex_init_dynamic must be called
 *                before any other functions in this module.
 *
 */

extern void flex_init_dynamic(void);

/* ------------------------- flex_isdynamic -------------------------------
 * Description:   Checks to see if flex is running in dynamic area mode
 *
 * Parameters:    void.
 * Returns:       non-zero if using dynamic area.
 * Other Info:    This is an extra routine to the normal RISCOSLib version
 *
 */

extern int flex_isdynamic(void);

#ifdef __cplusplus
}
#endif
#endif

/* end flex.h */
