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:
- Messages appear from the
SFLMSGRCDrow down, one per line in the order they were sent, with the text starting in column 2. - At most
SFLPAGmessages are shown; the rest stay queued. - A message subfile overlays the message lines on the display already shown: the
underlying format's image, its input-capable fields, and its function keys all
survive the
WRITE, so the program canREADthat format next. - Every
SND-MSGmessage type except*ESCAPEis queued and the program continues; an*ESCAPEmessage is queued and then ends the routine. - Messages stay queued until something removes them. Each program instance has its own queue - one program never sees another's messages.
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.