This is a list of all the functions that can be used to interface with ProBoard.
Several types have been defined in the file PB_SDK.H
bool : a boolean value that can have the values TRUE or FALSE byte : an unsigned character (8 bits) word : an unsigned short integer (16 bits) dword : an unsigned long integer (32 bits) KEY : used for key scan codes (for sysopkey handlers and the ScanKey() function).
Adds 'min' minutes to the user's time left. If 'min' is negative, the number of minutes will be subtracted from the time left.
Examples:
AddTime( 10 ); /* Adds 10 minutes */ AddTime( -5 ); /* Subtracts 5 minutes */
Returns the time left in minutes for the current user.
Returns the time in minutes that the current user is online.
Suspends the online-timer for the current user. No time will be subtracted until RestartTimer() is called.
Restarts the timer after a call to SuspendTimer().
Call this function if you changed the user's level. This recalculates all limits (time,download,…).
Fires up the internal message editor or the fullscreen editor, depending on the settings of the user. The message will be stored in the file MSGTMP in the current directory. If a message is aborted, the file MSGTMP will be deleted by the message editor. If you create a MSGTMP file before invoking the message editor, this file will be used as a 'quote' message.
Posts a message to a user.
from = Name of the sender to = Name of the user you're sending the message to subject = Subject of the message area = Message area number where the message has to be posted in pvt = Private status (TRUE=private, FALSE=public)
No checking is performed on any of the parameters!
Return value: -1 on error 0 if ok
Posts a netmail message.
from = Name of the sender to = Name of the user you're sending the message to subject = Subject of the message area = Message area number where the message has to be posted in address = Destination node number of this message. attach = TRUE for a file attach message crash = TRUE if this message is a crashmail message kill = TRUE if the message has to be deleted after it is sent
FIDO_NODE is a structure with the following fields:
struct { unsigned zone; /* Zone number */ unsigned net; /* Net number */ unsigned node; /* Node number */ unsigned point; /* Point number */ }
No checking is performed on any of the parameters!
Return value: -1 on error 0 if ok
Reads data about a message area.
area = Message area number (1-200) ma = Pointer to a MSGAREA structure to be filled
Check the file PB_SDK.H for details about the MSGAREA structure definition.
Return value: 6 FALSE if not defined TRUE if read ok
Reads message id <msgid> from area numer <areanum> into the MESSAGE structure. To access the text of the message, use the function CreateMessageText(). See the file PB_SDK.H for a description of the MESSAGE structure.
Return value: FALSE if the message does not exists TRUE if the message is read ok
Writes the string <text> to the file MSGTMP. The file is always recreated when using this function. To append text to MSGTMP, use the function AppendMSGTMP(). You have to insert your own CR/LF pairs in the text if you want to force a newline. Lines can be longer than 80 characters. The message processing functions will do a word-wrap if necessary. Do NOT insert a single CR or LF in the text. (\r or \n).
Same as WriteMSGTMP(), but adds text to an EXISTING file.
Shows the message <msg> to the user, including header and message text.
See the file PB_SDK.H for an description of the MESSAGE structure.
Reads the text that belongs to message <msg>, and stores it in a file called MSGTMP in the current directory. This file can then be accessed as an ordinary textfile.
Reads the text that belongs to message <msg>, and stores it in the string <text>. The text will be terminated by a '\0' character. You have to specify a maximum number of characters that can be stored in <text>.
These functions are used to read messages in forward or reverse order. To start scanning messages, you have to call the FirstMessage() function first, and the NextMessage() function to read more messages.
msg = MESSAGE structure where the message has to be stored. area = area number to read messages in order = 1 for forward order, -1 for reverse order first = message to start reading from. This message does NOT need to exist. The first non-deleted message following this message will be read first.
See the file PB_SDK.H for an description of the MESSAGE structure.
Return value: FALSE No more messages found. TRUE Message was found and read ok.
This is an example on how to use these functions:
result = FirstMessage( msg, 5, +1, 1 ); while ( result == TRUE ) { /* Do something with the message */ result = NextMessage( msg, 5, +1 ); }
Deletes message <msg>.
Marks message <msgid> for later retrieval. Up to 200 messages can be marked.
Shows all marked messages to the user, with the option to wait after each message. If the user selected to wait after each message, the standard message options menu will be shown to the user. (Next,Prev,Stop,…).
In fact, this function is identical to menu function “Read Messages”, with the user selecting “Marked”.
Is similar to ReadMarkedMessages(), but this function acts as a “QuickScan Messages” with the user selecting “Marked”.
Unmarks all messages that were previously marked. You have to call this function before marking any messages, because the list of marked messages is remembered until a user logs off.
Returns the highest message area number that is not empty.
Reads / Sets the lastread pointer for a specific user and message area. If GetLastRead() returns -1, an error occurred.
<areanum> ..... The area number (1-10000) <user_recno> .. The record number of the user (0 - ...) <msgid> ....... The id of the message you want to set the lastread pointer to.
Performs a fuzzy search for <string> in <text>. <degree> is the percentage of the characters in <string> that have to match.
Return value: -1 if not found >0 percentage of characters matched
All functions starting with IO_ are low-level functions to access the serial port directly. Do NOT use these functions for ordinary I/O operations. They are intended for writing file transfer protocols. See the file PB_SDK.H for the prototypes of these functions.
Waits for a character to be read from the modem or local keyboard.
Return value: the character read.
Waits for any character specified in <keylist>.
Return value: the key from the list that was pressed (converted to uppercase if the key is a letter).
Example:
c = WaitKeys( "ABC\r\x1b" ); /* Waits for A,B,C,<Enter> or <Esc> */
Asks for a string from the user. The string is stored in <buf>, and the user will not be allowed to enter more than <len> characters.
<readmode> : INPUT_ALL : All characters are allowed INPUT_UPFIRST : First character of each word is converted to uppercase. INPUT_UPALL : All characters are converted to uppercase. INPUT_DIGITS : Only digits are accepted. INPUT_NOFIELD : OR together with any of the previous modes if you don't want an input- field background to be displayed.
Asks for a Yes or No response from the user. Pressing 'Y' returns TRUE and outputs “Yes”. Pressing 'N' returns FALSE and sends “No” to the user. Pressing <Enter> returns <default>, and sends “Yes” or “No”, depending on <default>.
Checks if a character is available in the input buffer, and returns that character if there is.
Return value: 0 if no character available != 0 the character read (key pressed by user)
Changes the current output color. All text that is output after this function is called will be displayed in the specified color. This function does nothing when the user does not have ANSI or AVATAR enabled.
<color> can be one of the following:
BLACK, RED, GREEN, YELLOW, MAGENTA, BLUE, CYAN, WHITE
Changes the current foreground & background color. The color code is an IBM-type screen color code. This function does nothing when the user does not have ANSI or AVATAR enabled.
Some examples:
0x1E : Bright yellow on dark blue background. 0x87 : Blinking white on a black background.
Moves the cursor to position (x,y). The upper left corner of the screen is (1,1). This function does nothing when the user does not have ANSI or AVATAR enabled.
Clears from the current cursor position to the end of the line. This function does nothing when the user does not have ANSI or AVATAR enabled.
Enables stopping of output by pressing 'S'. When enabled, a user can press 'S' to stop incoming text. When this happens, any string output function will immediately return to the caller, en the function Stopped() will return TRUE to indicate that the user requested to stop output.
EnableStop() Enables this feature and sets the "stopped" status to FALSE . DisableStop() Disables the stop feature. Stopped() Returns the "stopped" flag (TRUE or FALSE).
Example:
EnableStop(); for ( i = 0; i < 100; i++ ) { printf( "...something..." ); if ( Stopped() ) { break; } }
Shows the file <filename> to the user, and watches for incoming keys that are specified in <hotkeys>. If one of these keys is detected, the function stops output, and returns the hotkey. The “stop” feature will be enabled when sending the file.
Return value: 0 : File sent completely and no hotkeys pressed. 1 : 'S' pressed (output stopped) 2 : File not found !=2 : Hotkey detected
This function is identical to ShowKotkeyFile(), except for the fact that no extension and path can be specified. Depending on the setting of the user, <filename>.ANS/ASC in the textfiles directory will be sent. If no .ANS file is found, it will try to send the .ASC file. If that fails too, 2 will be returned.
Return value: 0 : File sent completely and no hotkeys pressed. 1 : 'S' pressed (output stopped) 2 : File not found !=2 : Hotkey detected
These functions are used to support page pausing (“More Y/N”). Calling InitLineCounter() initializes the line counter to 0. Every time you call LineCounter(), the line counter is incremented by one. If the counter reaches the screen length, the user will be asked if he wants to continue reading. If he selects “No”, the LineCounter() function will return FALSE.
Example:
InitLineCounter(); for ( ; ; ) { printf( "...something...\n" ); if ( ! LineCounter() ) { break; } }
Returns TRUE when the last character that was read through any of the input routings originated from the remote keyboard (ie. the sysop did not type it).
Reads user record number <recnr> (0-…) from the user file and stores it in <rec>.
Return value: -1 if record does not exist. 0 if record is read ok.
Writes user record <rec> to the user file. The record number is stored in the USER_REC structure. If you want to write a user record to a different position in the user file, you have to change the 'record' field in the USER_REC structure.
Sets the internal ProBoard user record to record number <recnr>. This function should ONLY be called from _LOGIN.PEX !!
Return value: TRUE on success FALSE on error
Plays a .MUS file. The file has to be located in the ProBoard system directory. Do not include a path and extension in <filename>. The music can be stopped if the sysop presses one of the keys specified in <hotkeys>. ^^^^^
Return value: 0 Music file played till the end 1 Music file not found >1 The hotkey pressed by the SYSOP ^^^^^
Does exactly the same as the POSTINFO statement in a .Q-A file. No path and extension is allowed in <filename>. The file where the information will be written to will have the extension .ASW and will be placed in the ProBoard system directory.
Reads information about file area number <areanum> in the <fa> structure.
Check the file PB_SDK.H for details about the FILEAREA structure.
Return value: -1 File area does not exist 0 Ok
Executes menu function <function> with <data>. For details, see the menu functions description in this file.
There are named constants declared for each function in the file PB_SDK.H. It is recommended that you use these constants instead of numbers.
With this function you can write information to the ProBoard logfile. The log entry will be written if the user has a loglevel that is greater than <loglevel> .
<loglevel> can be one of the following:
LOG_FRIEND, LOG_NORMAL, LOG_SUSPICIOUS, LOG_DANGEROUS
If you want a log entry to be written regardless of the user's loglevel, use LOG_FRIEND.
The Log() function works like the printf function: you can use format specifiers in the <fmt> string, and pass extra parameters.
Example:
Log(LOG_NORMAL,"User's name = %s",CurUser->name);
Hangs up the phone, logging off the user. It is exactly the same as pressing Alt-H.
Checks if the current user can access something that requires <level> and <flags>. Returns TRUE if the user has access, FALSE if not.
Checks the LOCAL keyboard for a key, and returns the scan code for that key. If no key is available, 0 will be returned.
For a list of defined values for scan codes, check the file PB_SDK.H.
Access flags are stored in a long integer (32 bits). You have 3 macros at your disposal to manipulate access flags:
GetFlag : Returns TRUE if flag <flagchar> is set SetFlag : Turns flag <flagchar> on ClearFlag : Turns flag <flagchar> off
<flagchar> must be a value from 1 to 32. 1-26 correspond to A-Z, while 27-32 are the same as 1-6.
Returns the errorlevel of the last executed shell command (Through MenuFunction(MENU_SHELL,…))
These functions can be used to read and write to .INI files. These files are similar to the files used by MS Windows. They can be used to store settings for your application (PEX). An example of a .INI file:
DataPath = C:\PB\PEX\MYPEX\DATA ProgPath = C:\PB\PEX\MYPEX MaxUsers = 10
This is a standard ASCII file, with each line in the form:
<varname> = <value>
The value of a specific variable can be read by calling the function GetIniVar(). Setting a variable (writing to the .INI file or createing it if it doesn't exist yet) can be done by calling SetIniVar().
The parameters for the functions are:
<fname> Name of the .INI file. The extension of the file will always be changed to .INI by ProBoard. <varname> Name of the variable (case INsensitive) <value> For GetIniVar() : a pointer to a buffer where the variable's contents will be stored. For SetIniVar() : a pointer to the value of the variable. <max> Maximum number of characters that can be copied in <value> (including trailing '\0')
Return value: FALSE if the file could not be opened or the variable does not exist.
Exits the current pex-program, and unloads it from memory.
Exits the current pex-program, and leaves it resident. This has some important implications:
This is probably the most advanced and complicated function in the ProBoard SDK. With this function you can set up a “handler” for a specific action. Right now, only two types of handlers are supported: a replacement for the sysopkey-handler and a handler to intercept loss of carrier. This way you can create your own sysopkeys, or change the behaviour of existing sysopkeys. You could create a handler that intercepts the Alt-J key, and write your own flavor. In future versions you will be able to set up handlers for low-level I/O operations. So you could replace all I/O routines by your own functions. This way you can support your own exotic hardware or something like that. Anything goes!
handler : Handler type. At this time, only HANDLER_SYSOPKEY and HANDLER_HANGUP are supported. function : A pointer to the handler function you created.
You can install as many handlers as you want. When the PEX is removed from memory (when the PEX exits), all handlers that were installed will be removed by ProBoard.
The handler function is a function that returns an integer. The parameters depend on the type of handler you are creating.
For HANDLER_SYSOPKEY the handler function has to be declared like this:
int sysopkeyhandler( KEY k ) { ... }
A sysopkey handler intercepts any special key that is pressed by the sysop. (like F1,Alt-H,…). You can redefine any key, or add your own.
For HANDLER_HANGUP, the handler functions has to be declared like this:
int hanguphandler( void ) { ... }
The hangup handler works a little different: it is called whenever ProBoard exits (carrier lost, sysop hung up,…). It can be used to perform some cleanup for your running PEX file (like closing files, writing data, etc..). You can install the handler at the start of your program and remove it before the program is finished.
If a handler function decides to do anything, it has to return HANDLED. If the handler wants to leave it up to ProBoard, it must return NOT_HANDLED.
This asks for an example I suppose:
int keyhandler( KEY k ) { if ( k == KEY_ALTJ ) { printf( "\7\rHang on %s! I'm shelling to DOS...", UserFirstName ); MenuFunction( MENU_SHELL, "*N*Q*X*!" ); printf( "I'm back!!\n" ); return HANDLED; } else { return NOT_HANDLED; } } main( int argc, char *argv[] ) { InstallHandler( HANDLER_SYSOPKEY, keyhandler ); ExitTSR(); /* IMPORTANT */ }
So what does it do? It intercepts the sysopkey-function, and checks if the key pressed is Alt-J. If it is, it shells to DOS with swapping ON, and it writes its own messages to the screen. When the sysop returns, the handler returns HANDLED to let ProBoard know that it does not have to process the key. You could use this example in an INIT.PEX file. Is this powerful or what?
Removes handler number <handler> which has been installed by InstallHandler(). <function> is the pointer to the handler that should be removed.
Returns the message number for message 'id', in area 'area'. For Hudson and *.MSG, this is identical to the message id (but DO NOT rely on that). Returns a value < 1 if there is no message number for 'id'.
Returns the message id for message number 'n', in area 'area'. For Hudson and *.MSG, this is identical to the message number (but DO NOT rely on that). Returns a value < 1 if there is no message number 'n'.
Returns the message id of the last message in the given area. Note: if the lastread pointer is higher than what this function returns, DO NOT use FirstMessage()! The FirstMessage() function does not support reading past the end of the area. (if you know what I mean
Returns the total number of active messages in the given area.
Enables/Disables local echo of text. A parameter of TRUE means “enable local display”. FALSE means “disable local display”. See _GRAPH.CPP for an example.
Enables/Disables remote echo of text. A parameter of TRUE means “enable remote display”. FALSE means “disable remote display”. See _GRAPH.CPP for an example.
Returns TRUE if RIP was detected and enabled. FALSE if not...
This will send a RIP file located in the RIP directory. No file extension should be given. (.RIP is assumed) The file will not be shown on the local screen.
Resets the internal inactivity timeout counter. This function can be used when returning from a shell or after a time-consuming function has been called. It will prevent the user from being logged off because of inactivity.
Adds a file to the internal list of tagged files.
Returns TRUE if the was successfully added. FALSE if the file was already tagged.
Removes a file from the internal list of tagged files. Returns TRUE if the tagged file was found and deleted from the list, or FALSE if the tagged file was not in the list.
Clears the internal list of tagged files (all tags are removed).
Returns TRUE if the given file is in the internal list of tagged files, FALSE if not.
Fills the given array <tagarray> with all the files in the internal list of tagged files (up to a maximum of <maxitems>). This function returns the number of tagged files copied to the array <tagarray> (⇐ maxitems).
Fills the internal list of tagged files with the files in the given array <tagarray>. <nitems> is the number of items in the array.
Returns TRUE on success FALSE on error
You have access to some important ProBoard system variables through global variables defined in PB_SDK.H.
The version number of ProBoard. The high byte is the major version number (eg. 1). The low byte is the minor version number in hex (eg. 0x30). So if you're using ProBoard v1.30, PBVersion will be set to 0x0130 .
The beta version number of ProBoard. If this number is 0xFFFF, it means that the release version is running. Beta numbers start from 1.
For example, when running ProBoard 1.40 Beta/19, PBVersion will be set to 0x0140, and Beta will be set to 19.
The current bps rate of the caller. 0 means local.
Pointer to the current user record. You can change any of the field values in the record, but this will not result in any immediate action by ProBoard. For example, if you change the user's level, ProBoard will not know that you changed it, so you will have to tell it by calling AdjustTime();
Check the file PB_SDK.H for a description of the USER_REC structure.
The record number of the current user's record in the file USERS.BBS, starting from 0. This value cannot be changed.
The number of user levels defined in ProCFG. You can access the limit-values through the global array 'Limits'. This value cannot be changed.
Is an array of all user levels defined, with download and time limits. Check the file PB_SDK.H for information on the LIMIT structure.
You are not allowed to change any values! (A good compiler should generate an error or warning if you try to do so)
This is the login date & time of the current user.
LoginDate[0] : Day portion of login date LoginDate[1] : Month portion of login date LoginDate[2] : Year portion of login date (00-99) LoginTime[0] : Hour portion of login time LoginTime[1] : Minute portion of login time LoginTime[2] : Second portion of login time
These READ-ONLY variables tell you if netmail and/or echomail has been entered during this session.
This READ-ONLY variable is the number of users currently available in the file USERS.BBS.
This READ-ONLY variable is the current node number.
CurMenu : Current menu name UserFirstName : First name of current user PrevUser : Name of previous user StartupPath : Name of the directory where ProBoard was started from (with trailing '\') SysPath : Name of the ProBoard system directory (with trailing '\') PageReason : Reason for paging the sysop (as entered by the user)
These are READ-ONLY strings! (except PageReason)
POINTER to the number of sysop pages done by the user. This value can be changed by changing the unsigned integer pointed to by 'PageCount'.
A pointer to the current ProBoard configuration structure. See the file PB_SDK.H for a description of the CONFIG structure.
Several pex-files will be loaded automatically (if present). They perform certain actions like edit a message, set up handlers, etc.
INIT.PEX : Will be loaded and executed before any I/O has been done. Use this to set up any handlers (sysopkey handlers, ...) INIT_1.PEX - INIT_9.PEX : Is the same as INIT.PEX, but will be loaded in the order of the numbers. So you can have up to 10 initialization pex-files. _LOGIN.PEX : Is run instead of the normal login procedure. See the section explaining this PEX for more information LOGIN.PEX : No longer supported! BIRTHDAY.PEX : Is run after showing NEWS.ANS/ASC if today is the user's birthday. NEWUSER.PEX : Is run before the file NEWUSER.A?? is shown. NEWUSER1.PEX : Is run before the file NEWUSER1.A?? is shown. NEWUSER2.PEX : Is run before the file NEWUSER2.ANS/ASC is shown. WELCOME.PEX : Is run before the file WELCOME.ANS/ASC is shown WELCOMEx.PEX : Is run before the file WELCOMEx.ANS/ASC is shown (x = 1 to 9) SECxx.PEX : Executed when a user with security level xx logs in. Is run before SECxx.ANS/ASC is shown. EXPIRED.PEX : Is run before EXPIRED.ANS/ASC is shown, and after a user's level is lowered because the subscription date was reached. ProBoard will send one parameter to this PEX: the original level, before it was changed by ProBoard. GOODBYE.PEX : Is run before GOODBYE.ANS is displayed. GOODBYE2.PEX : Is run after GOODBYE.ANS is displayed. MSGED.PEX : Is a replacement of the built-in message editor. It will be executed with no parameters. The message that you create has to be written to a file called MSGTMP. ProBoard will then read this file and create a message from it. To let ProBoard know that the user has aborted a message, delete MSGTMP. FSED.PEX : Is similar to MSGED.PEX, but will be executed if the user has selected the fullsrceen editor. It works the same way as MSGED.PEX, but ProBoard will create a MSGTMP file with the original message if a user is replying to a message.
By writing a _LOGIN.PEX, ProBoard allows you to replace the normal login procedure (not including the new user procedure) with your own. It is the PEX's responsibility to check for validity of the name entered and to do password checking!
Once you determined the record number of the user, you have to call the function SetUser() with the record number as parameter, and exit the PEX immediately.
If the user is not in the user database yet, you should exit without calling SetUser(), and set the name that was entered by the user in a memory region supplied by ProBoard to your PEX as the only parameter. This parameter is a 'dword' in decimal form, so you have to convert it to a pointer using the following procedure:
/*----------------------------*/ char *pName; dword dwName = 0; char *s; for ( s = argv[ 1 ]; *s; s++ ) { dwName = l_mul( dwName, 10L ) + (dword) ( *s - '0' ); } pName = (char *) dwName; /*----------------------------*/