This is a package which provides a library of useful functions for the Rex Addin programmer. This library is used by some of my other software and it may be required to make use of those other programs.
Copyright (C) 2002 Graham R. Cobb. The package is distributed under the GPL (see the copyright notices and the COPYING file).
GRCLIB For Rex 6000 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
GRCLIB For Rex 6000 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
The GRCLIB distribution contains four main files in the top level directory (as well as sources and some informational files):
grclib.h
-- This is the header file for programs using this library.
It must be copied to a suitable "include" directory
(e.g. rexdk/include/rex/
).
grclib.lib
-- This is the self-contained precompiled library file.
It must be copied to rexdk/lib/clibs/
and can be linked using
-lgrclib
on the zcc command line.
grclib-so.lib
-- This is a precompiled library file using the shareable library version
of GRCLIB. It should be copied to rexdk/lib/clibs/
and linked using
-lgrclib-so
on the zcc command line.
This library uses the Rexdk shareable library support and must
be used in conjunction with the Rex addin described below.
grclib1.rex
-- This is a Rex addin which contains the GRCLIB library routines and can
be accessed using the shareable library version of the GRCLIB library.
This addin must be loaded on the Rex before a program which uses the GRCLIB shareable
library can run.
The addin programmer has a choice of two forms of the library to use:
grclib.lib
, any required library routines are included
in the addin and no extra programs are required to run it.
grclib-so.lib
, a minimum amount of code
is included in to the addin and the library routines themselves are accessed from the
grclib1.rex
shareable library addin.
The package also contains the sources for the two forms of the library and the shareable library addin and also for two versions of a test addin: one linked with the self-contained library and one linked with the shareable library.
For GRCLIB Version 1.4.
grc_ltoh
grc_ltoh_nox
grc_utoh
grc_utoh_nox
grc_btoh
grc_btoh_nox
These six routines all work similarly. They format a numeric value as a hex string in a supplied buffer.
The grc_ltoh
and grc_ltoh_nox
versions take an unsigned long
value.
The grc_utoh
and grc_utoh_nox
versions take an unsigned short
value.
The grc_btoh
and grc_btoh_nox
versions take an unsigned char
value.
The ...toh_nox
versions do not prefix the values with
Here is the more detailed documentation for grc_ltoh
, the others are similar.
unsigned char *grc_ltoh (unsigned char *str, unsigned long n)
unsigned char *str
-- address of buffer in which to format the value
unsigned long n
-- 32-bit unsigned value to display
Start address of buffer. The buffer will contain
grc_htol
grc_htou
grc_htob
These three routines all work similarly. They parse a hex string in a supplied buffer to create a value.
The grc_htol
version creates a longword (32-bit) result.
The grc_htou
version creates a word (16-bit) result.
The grc_htob
version creates a byte (8-bit) result.
Here is the more detailed documentation for grc_htol
, the others are similar.
unsigned char *grc_htol (unsigned char *str, unsigned long *p_n)
unsigned char *str
-- address of start of hex string
unsigned long *p_n
-- address of 32-bit unsigned value in which to provide result
Success: Remainder of buffer. This is a pointer to the first byte which is not part of the hex string.
Error: NULL. If the leading part of the buffer does not contain at least a single hex digit or if the hex string is too long for the value (i.e. more than 8 digits for a long), an error occurs.
Wait for a key press (actually a key release) or a button touch.
int grc_select(void)
Display a long string (e.g. an "About" string) as a full-screen message, with intelligent line breaks.
void grc_display_message (unsigned char *text)
unsigned char *text
-- address of null-terminated string to display.
String will be broken on newlines (\n
) or at spaces between words.
Text that would be beyond the bottom of the screen is lost.
Waits for a key press before continuing.
Display a message and up to three buttons. Indicate which button was pressed.
int grc_prompt(unsigned char *title, unsigned char *text, unsigned char *positive_text, unsigned char *zero_text, unsigned char *negative_text, int def_value)
unsigned char *title
- Title displayed at top of screen (or NULL for no title)
unsigned char *text
- Text of message.
The message can be up to three lines which will be broken at carriage returns (\r
)
or at blanks.
unsigned char *positive_text
- Text of first button (or NULL if button not used).
Selecting this button will return a positive value.
unsigned char *zero_text
- Text of second button (or NULL if button not used).
Selecting this button will return a zero value.
unsigned char *negative_text
- Text of third button (or NULL if button not used).
Selecting this button will return a negative value
int def_value
- Default value.
Returned if key pressed or a CLOSE event is received.
The macros provide convenient calls for common button combinations. In all cases, the macros specify no title and the caller just provides the text.
grc_prompt_yesno(txt)
-- display text and Yes and No buttons
(default is No) and return true (Yes) or false (No).
grc_prompt_ok(txt)
-- display text and OK button.
grc_prompt_okcancel(txt)
-- display text and OK and Cancel buttons
(default is Cancel) and return true (OK) or false (Cancel).
grc_prompt_yesnocancel(txt)
-- display text and Yes, No and Cancel buttons
(default is Cancel). Return value is positive (Yes), zero (No) or negative (Cancel).
Display debug information on top line of screen and wait for a key to be pressed.
void grc_trace(unsigned short a, unsigned short b, unsigned short c)
void grc_debug(unsigned char *txt, unsigned short b, unsigned short c)
unsigned short a, b, c
-- 16-bit values, displayed in hexadecimal
unsigned char *txt
-- text string, as much as possible is displayed
(usually about 20 characters)
grc_trace
displays the text
grc_debug
displays the text
Both functions wait for a key press before continuing.
Two macros can optionally be defined to make it easy to conditionalise debugging output.
GRCDEBUG
is defined (use -DGRCDEBUG
on
the command line), trace
is defined as a synonym for grc_trace
and
debug
is defined as as synonym for grc_debug
.
GRCNODEBUG
is defined (use -DGRCNODEBUG
on
the command line), trace
and debug
give null expansions.
trace
and debug
are not defined at all.
If you want to use this feature, create your debugging output using trace
and
debug
. For example:
debug("Error writing",return_value,input);
Then compile with -DGRCDEBUG
to enable debugging output and with
-DGRCNODEBUG
to disable it.
Convert a virtual address into a long pointer, as required by DsDialogDisplay.
This is useful for passing the address to a Rex library routine which will map the address using Bank 1.
unsigned long grc_get_long_pointer(void *addr)
void *addr
-- virtual address to convert.
long pointer value: high word is bank number, low word is address.
grc_get_bank_and_offset
(which are designed to be
convenient for code which will map addresses using Bank 2).
Provide the bank number and offset for a virtual address.
This is useful for passing the address to another addin (e.g. a subroutine library) which will map the address using Bank 2.
unsigned short grc_get_bank_and_offset(void *addr, unsigned short *bank, unsigned short *offset)
void *addr
-- virtual address
unsigned short *bank
-- pointer to unsigned short to receive bank number
unsigned short *offset
-- pointer to unsigned short to receive offset from
start of bank
Bank number (a copy of the value returned in *bank).
grc_get_long_pointer
(which match those used
by DsDialogWindow and are designed to be convenient for code which will map the
address using Bank 1).
Map a memory bank and return the adjusted virtual address.
This is the inverse of grc_get_bank_and_offset
.
This is useful when receiving a bank and offset from another add-in..
void *grc_map_bank_and_offset(unsigned short bank, unsigned short offset)
unsigned short bank
-- bank number or zero
unsigned short offset
-- offset from start of bank
void *address
-- mapped virtual address.
Copy a string (e.g. input to a library routine) to a buffer (e.g. on the stack). The advantage of this routine over strncpy is that the copy is always properly terminated and that NULL input parameters are handled.
unsigned char *grc_copy_string(unsigned char *in_string, unsigned char *buffer, unsigned short length)
unsigned char *in_string
-- address of string to copy or NULL
unsigned char *buffer
-- address of buffer
unsigned short length
-- length of buffer
Address of buffer or NULL
If in_string
is NULL
, buffer
will be set up to be an empty string
(i.e. buffer[0]=0
) but NULL
(not buffer
) will be returned.
This is the only case where the routine returns anything other than
the address of the buffer.
Allow the user to select an existing Memo from the database.
int grc_choose_memo(unsigned char *title, unsigned char *buffer, unsigned short length, unsigned char *memo_name)
unsigned char *title
-- title for selection dialogue
unsigned char *buffer
-- buffer to store selected memo name
unsigned short length
-- length of buffer
unsigned char *memo_name
-- name of current memo, or NULL
GRC_ERR_CANCEL
or GRC_ERR_EXIT
, respectively).
Return array of IDs of memos, in alphabetical order.
int grc_list_memos(unsigned long *p_id_array, unsigned short max_ids)
unsigned long *p_id_array
-- pointer to array of longwords to contain IDs
unsigned short max_ids
-- size of id_array (in longwords)
Get the name of a memo from the ID.
int grc_memo_id_to_name(unsigned long id, unsigned char *buffer, unsigned short max_length)
unsigned long id
-- memo ID
unsigned char *buffer
-- buffer to store memo name
unsigned short max_length
-- length of buffer
Find the page number for a library addin. If the library is missing, an error message is displayed and, once the user presses a button, the caller addin exits.
int grc_find_library(char *signature, char *library)
char *signature
- Addin signature (e.g. GRC)
char *library
- Addin name (e.g. GRCLIB), used in error message
Page number for library call.
For obvious reasons, this routine should only be called directly, not in a library.
This is not a library routine but a header file.
This header file implements a generic LibMain procedure to dispatch library functions based on a dispatch table.
The header file is designed to be included at the start of the library LibMain function. If the function ID code is not found in the dispatch table this code will fall through. The programmer can then decide how to handle the error.
The dispatch table itself must be called LibEntryPoints and must be an array of
grclibentry_t structures (defined in grclib.h
),
terminated by an entry in which the function address is NULL.
grclibentry_t LibEntryPoints[] = {
{ID1, func1},
{ID2, func2},
...
{0, NULL}
};
void LibMain(void)
{
#include <grclibmain.h>
... code to handle invalid ID code ...
}
Add grclibmain.h.
Add grc_find_library
Release for new Rexdk library mechanism