Supported RPG Features

A message subfile displays the messages a program has sent to its own message queue rather than records the program wrote. Its record format carries SFLMSGRCD(nn) - the display line the first message occupies - plus a SFLMSGKEY field and a SFLPGMQ field naming the queue. Both are hidden: they occupy no display position and are never painted.

     A          R MSGSFL                    SFL
     A                                      SFLMSGRCD(22)
     A            MSGKEY                    SFLMSGKEY
     A            PGMQ                      SFLPGMQ(10)
     A          R MSGCTL                    SFLCTL(MSGSFL)
     A                                      OVERLAY
     A  50                                  SFLDSP
     A                                      SFLINZ
     A                                      SFLSIZ(0010)
     A                                      SFLPAG(0002)
     A            PGMQ                      SFLPGMQ(10)

Messages reach the queue through SND-MSG, and a WRITE to the subfile-control format displays them:

**FREE
DCL-F MSGPRB WORKSTN;
PGMQ = '*';
SND-MSG *INFO 'First message.';
SND-MSG *INFO 'Second message.';
*IN50 = *ON;
WRITE SCREEN1;
WRITE MSGCTL;
READ SCREEN1;

Behavior:

Sending and removing messages from either format

SND-MSG is a free-format opcode. Both formats can instead reach the queue through the message-handling APIs, which the runtime services directly - a CALL 'QMHSNDPM' works with no compiled program of that name on the classpath, exactly as the data queue APIs do:

API Purpose
QMHSNDPM Send a message to the program message queue
QMHRMVPM Remove messages from it

QMHSNDPM takes its nine required parameters: message identifier Char(7), qualified message file Char(20), message data or immediate text Char(*), length of that data Binary(4), message type Char(10), call stack entry Char(*), call stack counter Binary(4), message key Char(4) (output), and error code Char(*).

     C                   CALL      'QMHSNDPM'
     C                   PARM                    MSGID
     C                   PARM                    MSGF
     C                   PARM                    MSGDTA
     C                   PARM                    MSGLEN
     C                   PARM                    MSGTYP
     C                   PARM                    STKE
     C                   PARM                    STKCNT
     C                   PARM                    MSGKY
     C                   PARM                    ERRC0

A blank message identifier means the message data is immediate text, and exactly the declared number of bytes of it is sent. A non-blank identifier is rendered as msgId: replacement-data, the same way SND-MSG's %MSG form renders it, since message files are not available. Message types are the SND-MSG set with a leading asterisk - *INFO, *COMP, *DIAG, *STATUS, *NOTIFY, *ESCAPE. *INQ and *RQS are rejected: they need a reply source or a request processor, which are job facilities with no JVM equivalent.

QMHRMVPM takes five: call stack entry Char(*), call stack counter Binary(4), message key Char(4), messages to remove Char(10), and error code Char(*). Removal is selective:

Messages to remove Effect
*ALL Every message on the queue
*BYKEY Only the message whose key is passed - the key QMHSNDPM wrote back. A key that matches no message on the queue is an error, not a no-op: it reports CPF2410. Supply an error-code structure with a non-zero bytes provided to read that identifier and continue; leave bytes provided zero (or omit the parameter) and the call raises an escape, which ends the program unless a MONITOR catches it. The usual way to hit this is keeping a key across a *ALL removal and then removing by it - the key is stale at that point.
*KEEPRQS Everything; a compiled program never queues a request message
*NEW Every message - nothing on a program message queue is marked old
*OLD Nothing, for the same reason
*INFO, *COMP, *DIAG, *ESCAPE, *STATUS, *NOTIFY Every message sent as that type

Any other value is rejected rather than treated as a clear.