Maximus BBS

Documentation for Maximus BBS — Next Generation

View on GitHub

Display & I/O

Output, input, file I/O, color, static data, and the utility functions every MEX script needs

This is the kitchen-sink page — the functions that almost every MEX script touches. Printing to the screen, reading keypresses, prompting for input, changing colors, reading and writing files, and the handful of utility functions that don’t fit neatly anywhere else.

All of these live in max.mh, which you’re already including. A few convenience wrappers live in optional headers (input.mh, intpad.mh, rand.mh) — those are noted where they appear.


On This Page


Quick Reference

Output

Function What It Does
print() Print strings, numbers, and characters to the caller
display_file() Display an ANSI/ASCII/MECCA file with paging
vidsync() Flush the output buffer
set_output() Enable/disable local or remote output

Input

Function What It Does
getch() Read a single keypress (no echo)
kbhit() Check if a key is waiting
localkey() Read a local console keypress
input_str() Read a line or word with options
input_ch() Read a character with options
input_list() Read from a list of valid responses

File I/O

Function What It Does
open() Open a file
read() Read bytes from a file
readln() Read a line from a file
write() Write bytes to a file
writeln() Write a line to a file
tell() Get current file position
seek() Move file position
close() Close a file

Filesystem

Function What It Does
fileexists() Check if a file exists
filesize() Get file size in bytes
filedate() Get file modification date
rename() Rename a file
remove() Delete a file
filecopy() Copy a file
filefindfirst() Start a wildcard file search
filefindnext() Continue a wildcard file search
filefindclose() End a wildcard file search

Output

print(…)

The workhorse. print() is variadic — it accepts any number of arguments of any type and outputs them to the caller’s terminal:

print("Hello, ", usr.name, "!\n");
print("You have ", usr.times, " calls on record.\n");
print("Time left: ", timeleft(), " seconds.\n");

Each argument is converted to its display form automatically — strings print as-is, integers print as decimal, characters print as their character.

print() understands AVATAR display codes when you embed the COL_* constants:

print(COL_YELLOW, "Warning: ", COL_GRAY, "disk space is low.\n");

display_file(filename, nonstop)

Display an ANSI, ASCII, or MECCA file with automatic paging:

void display_file(string: filename, ref char: nonstop);
char: nonstop;
nonstop := False;
display_file("welcome.ans", nonstop);

The nonstop flag tracks whether the caller pressed N (continuous scroll) at a “More?” prompt. Pass the same variable across multiple display calls to maintain state.

vidsync()

Flushes the output buffer immediately. Normally Maximus batches output for efficiency — call vidsync() when you need something to appear on screen right now (e.g., before a timed pause):

print("Processing...");
vidsync();
sleep(2);
print(" done!\n");

set_output(where)

Control whether output goes to the remote caller, the local console, both, or neither:

int set_output(int: where);
Constant Value Effect
DISABLE_NONE 0 Output to both (default)
DISABLE_LOCAL 1 Suppress local console output
DISABLE_REMOTE 2 Suppress remote output
DISABLE_BOTH 3 Suppress all output

Returns the previous state so you can restore it:

int: old_state;
old_state := set_output(DISABLE_REMOTE);
print("This only shows on the local console.\n");
set_output(old_state);

Color & Display Codes

MEX provides two ways to set colors: AVATAR inline codes (for use with print()) and pipe codes (for use in displayed files and lang strings).

AVATAR Color Constants

These are string constants that emit AVATAR attribute-change sequences when passed to print():

Constant Color
COL_BLACK Black
COL_BLUE Blue
COL_GREEN Green
COL_CYAN Cyan
COL_RED Red
COL_MAGENTA Magenta
COL_BROWN Brown
COL_GRAY Gray (default)
COL_DKGRAY Dark gray
COL_LBLUE Light blue
COL_LGREEN Light green
COL_LCYAN Light cyan
COL_LRED Light red
COL_LMAGENTA Light magenta
COL_YELLOW Yellow
COL_WHITE White

Combination constants: COL_YELLOWONBLUE, COL_BLACKONGREEN, COL_REDONGREEN, COL_WHITEONGREEN.

AVATAR Control Sequences

Constant Effect
AVATAR_CLS Clear screen
AVATAR_CLEOL Clear to end of line
AVATAR_UP Cursor up one line
AVATAR_DOWN Cursor down one line
AVATAR_LEFT Cursor left one column
AVATAR_RIGHT Cursor right one column
print(AVATAR_CLS);                         // clear screen
print(COL_YELLOW, "Title\n", COL_GRAY);    // yellow heading

For full-screen positioning and attribute control, use the UI Primitives (ui_goto, ui_set_attr, etc.).


Input

getch()

Read a single character from the caller. Blocks until a key is pressed. No echo — the character is not displayed:

char getch();
char: ch;
print("Press any key...");
ch := getch();

kbhit()

Check if a keypress is waiting in the input buffer. Returns the character if one is available, or 0 if not. Non-blocking:

char kbhit();
if (kbhit())
  print("Key is waiting.\n");

localkey()

Read a keypress from the local console (sysop keyboard), not the remote caller. Useful for sysop-only controls:

char localkey();

input_str(s, type, ch, max, prompt)

The full-featured line input function. Reads a string from the caller with configurable behavior:

int input_str(ref string: s, int: type, char: ch, int: max, string: prompt);
Parameter Purpose
s Output: the string entered by the caller
type INPUT_* flags ORed together
ch Echo character (used with INPUT_ECHO), or 0
max Maximum input length
prompt Prompt string (displayed before input)

Type flags (pick one base mode):

Flag What It Does
INPUT_LB_LINE Input a line, allowing stacked input
INPUT_NLB_LINE Input a line, not allowing stacked input
INPUT_WORD Input a word (stops at space)

Modifier flags (OR with base mode):

Flag What It Does
INPUT_ECHO Echo ch instead of actual character (for passwords)
INPUT_NOECHO Disable all echo
INPUT_NOLF Don’t send linefeed at end
INPUT_DEFAULT Pre-fill with current contents of s
INPUT_SCAN Allow scan codes in string
INPUT_NOCTRLC Don’t allow Ctrl+C to redisplay prompt
string: name;
input_str(name, INPUT_NLB_LINE, 0, 30, "Enter your name: ");
// Password input (echo asterisks)
string: pwd;
input_str(pwd, INPUT_NLB_LINE | INPUT_ECHO, '*', 20, "Password: ");

input_ch(type, options)

Read a single character with options:

int input_ch(int: type, string: options);

The type parameter uses CINPUT_* flags. The options string serves as either a prompt (with CINPUT_PROMPT) or a list of acceptable characters (with CINPUT_ACCEPTABLE).

int: ch;
ch := input_ch(CINPUT_PROMPT | CINPUT_ACCEPTABLE, "YyNn");

input_list(list, type, help_file, invalid_response, prompt)

Present a list of valid choices and loop until the caller picks one:

int input_list(string: list, int: type, string: help_file,
               string: invalid_response, string: prompt);
int: choice;
choice := input_list("ABCQ", CINPUT_PROMPT, "",
                      "Invalid choice.", "[A,B,C,Q]? ");

input.mh Helpers

The optional input.mh header provides two convenience functions:

#include <input.mh>

string: s;
readstr(s);

More Prompt

reset_more(nonstop)

Reset the line counter for “More?” prompting:

void reset_more(ref char: nonstop);

do_more(nonstop, colour)

Check if a “More [Y,n,=]?” prompt should be displayed. Returns 0 if the caller said “No” (stop output), non-zero to continue:

int do_more(ref char: nonstop, string: colour);
char: nonstop;
int: i;

nonstop := False;
reset_more(nonstop);

for (i := 1; i <= 100; i := i + 1)
{
  print("Line " + itostr(i) + "\n");
  if (do_more(nonstop, COL_CYAN) = 0)
    return;   // caller said "no more"
}

File I/O

MEX provides C-style file I/O with integer file descriptors.

open(name, mode)

Open a file. Returns a file descriptor (positive integer), or -1 on error:

int open(string: name, int: mode);
Flag Value Purpose
IOPEN_CREATE 0x01 Create the file if it doesn’t exist
IOPEN_READ 0x02 Open for reading
IOPEN_WRITE 0x04 Open for writing
IOPEN_RW 0x06 Open for reading and writing
IOPEN_APPEND 0x08 Append to end of file
IOPEN_BINARY 0x80 Binary mode (no CR/LF translation)

OR flags together:

int: fd;
fd := open("guestbook.txt", IOPEN_CREATE | IOPEN_APPEND);
if (fd = -1)
{
  print("Cannot open file!\n");
  return;
}

read(fd, s, len)

Read up to len bytes from a file into string s. Returns the number of bytes actually read:

int read(int: fd, ref string: s, int: len);

readln(fd, s)

Read a line (up to the next newline) from a file. Returns 0 on success, non-zero at end of file:

int readln(int: fd, ref string: s);
string: line;
while (readln(fd, line) = 0)
  print(line + "\n");

write(fd, s, len)

Write len bytes from string s to a file:

int write(int: fd, ref string: s, int: len);

writeln(fd, s)

Write a string followed by a newline to a file:

int writeln(int: fd, string: s);
writeln(fd, usr.name + " was here!");

tell(fd)

Returns the current file position as a long:

long tell(int: fd);

seek(fd, pos, where)

Move the file position:

long seek(int: fd, long: pos, int: where);
Constant Value Meaning
SEEK_SET 0 From beginning of file
SEEK_CUR 1 From current position
SEEK_END 2 From end of file

close(fd)

Close an open file. Always close your files — open file descriptors are a limited resource:

int close(int: fd);

Complete File I/O Example

// Append a guestbook entry
int: fd;
fd := open("guestbook.txt", IOPEN_CREATE | IOPEN_APPEND);
if (fd <> -1)
{
  writeln(fd, usr.name + " - " + stamp_string(usr.ludate));
  close(fd);
}

Filesystem

fileexists(filename)

Returns non-zero if the file exists:

int fileexists(string: filename);

filesize(filename)

Returns the file size in bytes, or -1 if the file doesn’t exist:

long filesize(string: filename);

filedate(filename, stamp)

Gets the modification date of a file:

int filedate(string: filename, ref struct _stamp: filedate);

rename(oldname, newname)

int rename(string: oldname, string: newname);

remove(filename)

int remove(string: filename);

filecopy(from, to)

int filecopy(string: fromname, string: toname);

File Search (filefindfirst / filefindnext / filefindclose)

Wildcard file search using the _ffind struct:

int filefindfirst(ref struct _ffind: ff, string: filename, int: attribs);
int filefindnext(ref struct _ffind: ff);
void filefindclose(ref struct _ffind: ff);
struct _ffind: ff;
if (filefindfirst(ff, "*.txt", FA_NORMAL) = 0)
{
  do
  {
    print(ff.filename + "  " + ultostr(ff.filesize) + " bytes\n");
  }
  while (filefindnext(ff) = 0);
  filefindclose(ff);
}

The attribs parameter uses FA_* constants (FA_NORMAL, FA_HIDDEN, FA_SUBDIR, etc.).


Static Data

Static data persists across script invocations within the same session. Use it for caching, counters, or passing data between scripts.

Static Strings

int create_static_string(string: key);
int get_static_string(string: key, ref string: data);
int set_static_string(string: key, string: data);
int destroy_static_string(string: key);
// First run: create and set
create_static_string("last_area");
set_static_string("last_area", marea.name);

// Later: retrieve
string: saved_area;
if (get_static_string("last_area", saved_area) = 0)
  print("You were last in: " + saved_area + "\n");

Static Data (Binary)

For structs and raw data:

int create_static_data(string: key, long: size);
int get_static_data(string: key, ref void: data);
int set_static_data(string: key, ref void: data);
int destroy_static_data(string: key);

All functions return 0 on success.


Random Numbers

Include rand.mh for pseudo-random number generation:

#include <rand.mh>

srand(time());                    // seed with current time
int: roll;
roll := (rand() % 6) + 1;        // random 1-6
print("You rolled a " + itostr(roll) + "!\n");
Function What It Does
srand(int: seed) Set the random seed
rand() Returns a random integer 0–32767

Always call srand() once before using rand(). Use time() as a convenient seed value.


Miscellaneous

System & Session

Function Signature What It Does
shell() int shell(int: method, string: cmd) Run an external command
sleep() void sleep(int: duration) Pause for duration seconds
log() void log(string: s) Write a message to the system log
carrier() int carrier() Returns non-zero if carrier is present
ansi_detect() int ansi_detect() Detect ANSI terminal capability
rip_detect() int rip_detect() Detect RIP graphics capability

Keyboard State

Function What It Does
keyboard(int: state) Enable (1) or disable (0) local keyboard
iskeyboard() Returns current keyboard state
snoop(int: state) Enable (1) or disable (0) local snoop display
issnoop() Returns current snoop state

Terminal Dimensions

Function Returns
term_length() Caller’s terminal height in rows
term_width() Caller’s terminal width in columns
screen_length() Physical screen height
screen_width() Physical screen width

System Path

string prm_string(int: stringnum);

Returns system path strings. prm_string(0) returns the BBS system name.


See Also