# RMSG - Macro implementation of Kermit REMOTE MESSAGE
#
# The REMOTE MESSAGE command sends a short text message to a Kermit
# server for display.  This command is found in MS-DOS Kermit but
# not in C-Kermit or Kermit 95.  The following macros implement it.
# C-Kermit 8.0 or later or Kermit 95 2.0 or later are required, and
# a connection to a Kermit server must already exist.  TAKE this file
# to define the needed macros, or add the definitions to your K95
# or C-Kermit customization file.  Usage:
#
#   rmsg "This is a message"
#
# Sends the quoted text (quotes required if message includes spaces) in a
# Kermit Message packet.  Message should not include control characters.
# Waits for acknowledgement.  Tries up to five times.  Default timeout is
# four seconds; adjust as necessary by redefining \%t.
#
# F. da Cruz, Columbia University, May 2004.
#
local \%t                               # Local variables
.\%t = 4                                # INPUT timeout (change if necessary)

def CHK1 {                              # Construct Type 1 Block Check
    local s                             # Local variable
    .s := \fchecksum(\fcontents(\%1))   # Arithmetic checksum
    (+ (& (+ (/ (& s 192) 64) s) 63) 32)  # Return Kermit block check
}
def MPKT {                              # Construct Message Packet
    local t n p                         # Local vars
    .t := \fcontents(\%1)               # Message text
    .t := \freplace(\m(t),\v(p_ctl),\v(p_ctl)\v(p_ctl)) # Escape special chars
    .t := \freplace(\m(t),\v(p_rpt),\v(p_ctl)\v(p_rpt))
    if def \v(p_8bit) .t := \freplace(\m(t),\v(p_8bit),\v(p_ctl)\v(p_8bit))
    .n := \flength(\m(t))               # Length of message
    if ( > n 90 ) stop 1 "TOO LONG"     # Long packets not allowed
    .p := "\fchar(n+37)\{32}GM\fchar(n+32)\m(t)" # Make Message packet
    chk1 "\m(p)"                        # Get its checksum
    return \{1}\m(p)\fchar(\v(return))  # Return the complete packet
}
def RMSG {                              # Send Message Packet to Kermit server
    local spkt i                        # Local variables
    mpkt "\fcontents(\%1)"              # Encapsulate message in packet
    .spkt := \v(return)                 # Save the packet
    clear input                         # Clear the INPUT buffer
    for ( i 1 5 1 ) {                   # Try five times
        output \m(spkt)\13              # Send the M-packet
        if fail stop 1 "I/O Error"      # Check for I/O error
        input \%t "\{1}#\{32}Y>"        # Wait up to \%t seconds for ACK
        if success break                # Got it
    }
    if ( > i 5 ) end 1 "MESSAGE FAILED" # Return and print status
    end 0 "MESSAGE OK"
}
