Trailing-Edge
-
PDP-10 Archives
-
walsh_goodStuff_1600
-
more-uns/dpy.mem
There are no other files named dpy.mem in the archive.
DPY - A Video Terminal Update Package
-------------------------------------
This file briefly describes how to use the DPY module to do
continuously updating screen displays. The best way is to show an
actual program, and explain how it interacts with the DPY module. This
example program will show some of the users of the system in a simple
display:
TITLE JOBS PROGRAM TO DISPLAY JOBS IN USE
SUBTTL IN ORDER TO SHOW HOW DPY IS USED
SEARCH MONSYM,MACSYM ;GET NORMAL DEFINITIONS
SEARCH DPYDEF ;AND THOSE NEEDED TO USE DPY
T1=1 ;TEMPORARY
T2=2
T3=3
T4=4
J=5 ;CURRENT JOB NUMBER
P=17 ;STACK
PDSIZ==20 ;STACK SIZE
BUFSIZ==20 ;TEMPORARY BUFFER SIZE
SLPTIM==^D500 ;SLEEP INTERVAL BETWEEN UPDATES
.JB41==41 ;LUUO DISPATCH ADDRESS
;ACTUAL PROGRAM:
START: RESET ;CLEAR EVERYTHING
MOVE P,[IOWD PDSIZ,PDL] ;SET UP STACK
MOVE T1,[CALL DPYUUO] ;GET CALLING INSTRUCTION
MOVEM T1,.JB41 ;STORE INTO LOCATION 41
INI$ ;INITIALIZE DPY AND CLEAR THE SCREEN
LOOP: STR$ [ASCIZ/Job status as of /] ;START OUTPUT
HRROI T1,BUFF ;POINT TO BUFFER
SETO T2, ;WANT CURRENT TIME
SETZ T3, ;NORMAL STYLE OUTPUT
ODTIM ;STORE TIME INTO BUFFER
STR$ BUFF ;THEN GIVE IT TO DPY
STR$ [ASCIZ/:
Job Line User name
--- ---- ---------
/] ;TYPE THE HEADER LINE
SETOM J ;INITIALIZE FOR LOOP
JOBLOP: AOS T1,J ;GET NEXT JOB
MOVE T2,[-<.JIUNO+1>,,JIBLK] ;POINT TO STORAGE
SETZ T3, ;FROM FIRST WORD
GETJI ;READ INFORMATION
ERJMP NOJOB ;FAILED, GO SEE WHY
CALL TYPJOB ;SHOW INFORMATION ON THIS JOB
JRST JOBLOP ;THEN LOOK AT NEXT ONE
NOJOB: CAIN T1,GTJIX4 ;FAIL BECAUSE OF NO SUCH JOB?
JRST JOBLOP ;YES, GO TRY ANOTHER ONE
DPY$ ;SHOW THE SCREEN
MOVEI T1,SLPTIM ;GET SLEEP TIME
DISMS ;WAIT A BIT
JRST LOOP ;GO BACK TO LOOP
;HERE TO TYPE A LINE ABOUT A JOB:
TYPJOB: MOVE T1,JIBLK+.JIJNO ;GET JOB NUMBER
CALL DECOUT ;OUTPUT IN DECIMAL
CHI$ .CHTAB ;THEN A TAB
SKIPGE T1,JIBLK+.JITNO ;GET TERMINAL NUMBER
STR$ [ASCIZ/Det/] ;DETACHED, SAY SO
SKIPL T1 ;REALLY ON A TERMINAL?
CALL OCTOUT ;YES, GIVE THE NUMBER
CHI$ .CHTAB ;TYPE ANOTHER TAB
SKIPN T2,JIBLK+.JIUNO ;GET JOB'S USER NUMBER IF ANY
STR$ [ASCIZ/Not logged in/] ;IF NONE, SAY LOGGED OUT
JUMPE T2,CRLF ;THEN FINISH WITH A CRLF
HRROI T1,BUFF ;JOB IS LOGGED IN, POINT TO BUFFER
DIRST ;CONVERT USER NUMBER TO STRING
ERJMP CRLF ;FAILED, JUST TYPE CRLF
STR$ BUFF ;TYPE THE USER NAME
CRLF: STR$ [ASCIZ/
/] ;GET A FINAL CRLF
RET ;DONE
;OUTPUT SUBROUTINES:
DECOUT: SKIPA T3,[^D10] ;GET DECIMAL RADIX
OCTOUT: MOVEI T3,^D8 ;OR OCTAL RADIX
NUMOUT: IDIVI T1,(T3) ;GET A DIGIT
JUMPE T1,NUMFIN ;UNWRAP IF GOT THEM ALL
HRLM T2,(P) ;SAVE DIGIT ON STACK
CALL NUMOUT ;RECURSE TO GET ANOTHER ONE
HLRZ T2,(P) ;BRING BACK A DIGIT
NUMFIN: CHI$ "0"(T2) ;TYPE THE DIGIT
RET ;DONE
;DATA STORAGE:
JIBLK: BLOCK .JIUNO+1 ;STORAGE FOR GETJI JSYS
BUFF: BLOCK BUFSIZ ;TEMPORARY STORAGE
PDL: BLOCK PDSIZ ;STACK STORAGE
END START
The DPY module is a .REL file which is loaded with your own
program. There exist two global symbols which your program use to
communicate with DPY. The first one is the location "DPYUUO", and is
used to enter DPY when a function is to be performed. The second one is
"DPYTAB", which is simply the address of an internal table containing
useful information. (DPYTAB is not needed in this example program).
All calls to DPY are done with LUUOs. Whenever an LUUO is
executed, the opcode, accumulator field, and effective address of the
LUUO instruction is stored in location 40, and location 41 is executed.
Location 41 should contain a "CALL DPYUUO" instruction to enter DPY.
DPY will then save all of the ACs, analyze the LUUO to determine what to
do, perform the function, restore the ACs, and return control to the
LUUO instruction plus one. You can see the example program build the
LUUO dispatch instruction in its initialization code.
LUUOs and other useful symbols are defined in the DPYDEF
universal file. By doing a "SEARCH DPYDEF" statement, these definitions
become available to your program. LUUOs used for DPY are recognized by
a three letter mnemonic terminated by a dollar sign. The above program
uses the LUUOs INI$, STR$, CHI$, and DPY$. The functions of these and
other LUUOs will be explained later.
The general use of DPY is as follows. First you must initialize
DPY for use. This is done by using the INI$ LUUO. This will usually
reset all of DPY's internal parameters and clear the screen. This LUUO
must be done before any other LUUO is attempted.
Then the program "outputs" any data it wishes using the LUUOs
STR$, CHR$, and CHI$. These allow a string to be "output", or
characters to be "output" one at a time. This "output" is not
immediately visible on the screen. Instead, the text generated is
compared by DPY against an internal picture of the screen, where
necessary changes are recorded.
After all text has been output by the program, either of the
LUUOs DPY$ or REF$ are executed. At this time DPY does actual output to
the terminal. The screen is changed to display the text as newly
generated by the program. DPY tries to update the screen to the new
display using a minimum of output.
This cycle of outputting text, then displaying the results is
repeated again and again in order to make a continuously updating
display. If you examine the above program, you can see that the main
loop "outputs" some text to DPY, displays it with DPY$, sleeps a little
while, and then jumps back to do it all over again.
That is about all there is to it. DPY was designed for the
"stupid" program that really has minimal control over its output.
Because of this, the program has to "output" the whole screen each time
the display is to be updated, even if only a small section of the data
has changed. When using this module, you therefore trade effecientcy
for ease of use. Those "smart" programs which know that they are only
changing the tenth character of the third line should not be using DPY,
they should be updating the screen themself!
The following is a description of the various LUUOs which are
available, and how they are used. Most of these aren't needed unless
special actions are desired.
INI$ This is the initialization function. If the effective address
of the LUUO is zero, then default actions are taken. That is,
DPY will do a GTJFN for device TTY: for output, the normal
internal data area inside DPY will be used for screen storage,
the default terminal type will be used, and the screen will be
cleared.
If the effective address is nonzero, then that address is the
start of a block of core containing values to initialize with.
Flags can be set, a JFN can be specified for output, another
data area can be selected for use, fatal errors can be trapped,
and terminal types can be specified. The basic format is:
INI$ [ flags,,argument count
argument 1
...
argument n ]
If an argument is not specified or is zero, the default is used.
Otherwise, the given argument is used. Read DPYDEF.MAC to get a
list of flags that can be set, and arguments that can be
specified.
STR$ This is used to "output" an ASCIZ string to DPY. The effective
address of the LUUO is the address where the string begins, and
therefore the string must be word aligned. As an example,
STR$ [ASCIZ/This is stuff to output/]
will "output" the specified string to DPY.
CHR$ This is used to "output" a single character to DPY. The word
contained at the location specified by the effective address of
the LUUO contains the character to be output, in bits 29-25.
This as an example, the instruction
CHR$ ["A"]
will "output" the letter "A" to DPY.
CHI$ This also "outputs" a single character to DPY, but the character
is specified by the effective address itself, not in the
location pointed to by that address. This LUUO is useful since
memory locations don't have to be wasted to hold characters, and
minimal computations can be done in the LUUO instruction itself.
For example, the sequence:
CHI$ "X"
MOVEI T1,5
CHI$ "0"(T1)
will "output" the two character sequence "X5" to DPY.
DPY$ This LUUO is used to tell DPY that all "output" is done, and
that the screen should now be updated to display the new data.
DPY will move the cursor around the screen as necessary, and
change the screen to its new state. After this is completed,
the default action is to home the cursor to the top left of the
screen. But if the flag DP$NOH is specified as the effective
address of the LUUO, the cursor is left where it last updated
the screen, as in
DPY$ DP$NOH
After this function is completed, DPY is ready to accept a new
screenful of "output" for the next update of the screen.
REF$ This is similar to DPY$, except that the whole screen is
updated, so that glitches, system messages, control/t output,
etc. can be erased. This is the way to "refresh" the screen.
There are two ways to refresh the screen. The first way is to
clear the screen and rewrite it. The second way is to leave the
old data on the screen as the cursor overwrites the whole screen
with the correct data. The first method is faster, but the
second method allows all of the data to be seen during the
refresh. The effective address contains flags to decide which
kind of refresh to perform. In addition, just like in the DPY$
function, the cursor can be left where the last change occurred.
Thus the instruction
REF$ RE$CLR!RE$NOH
will refresh the screen by clearing it first, and will leave the
cursor where it last changed the screen.
ADR$ This LUUO is used to position the physical cursor to a desired
location on the screen. Notice that this function has nothing
to do with where the "output" of STR$, CHR$, and CHI$ are going.
This LUUO affects only the terminal itself. This LUUO is used
to position the cursor to a desirable location on the screen,
usually immediately after a DPY$ or REF$ LUUO are performed.
The format of this LUUO is:
ADR$ [ FLAG+LINE,,COLUMN]
where the lines are numbered starting from line zero at the top
of the screen, and columns are numbered from column zero at the
left of the screen. If the flag AD$NOM is set, then DPY will
not actually move the cursor as specified, but will accept the
position given as the actual cursor location. For example, the
instruction:
ADR$ [7,,5]
will position the cursor to column 5 of line 7.
TTY$ This LUUO is used to perform miscelaneous terminal functions,
such as homing up the cursor and erasing the screen. Like ADR$,
this function is independent of STR$, CHR$, CHI$, DPY$, and
REF$. Therefore if the screen is erased a REF$ should be done
in order to restore the data that was on the screen. The
function code is specified by the effective address of the LUUO.
For example, the instruction
TTY$ TT$CLR
will home up and erase the screen. This is very useful when
exiting from display programs.
TAB$ This LUUO is used to specify tab stops for "output" to use. If
this has not been given, or if the effective address is zero,
then normal default tab stops are in effect (one every eight
columns).
If the effective address is nonzero, then that address is the
beginning of a four word block of bits, where the bits specify
the columns where tab stops are in effect. Word 0 is for
columns 0 through 35, word 1 is for columns 36 through 71, etc.
These tab stops are always with respect to the physical screen,
not with any "windowing" which has been set up (see next
section). To make it easier to define the tab stops, the $TABS
macro will accept decimal column position numbers and generate
the four words for you. Thus
TAB$ [ $TABS<3,12,33,55>]
generates tab stops at columns 3, 12, 33, and 55.
SIZ$ This LUUO lets the program "output" to only a small rectangular
section of the display as if the rest of the screen did not
exist. This the physical screen can be broken up into different
pieces, such that each piece doesn't know about the other
pieces. This allows split-screen displays to be implemented
easily, since each side of the display can be a separate piece.
Each piece is called a window. Once a SIZ$ has been executed,
DPY will take "output" and place it in that window starting at
the top left corner, working down line by line, but never
leaving the region. If a SIZ$ is not done to a region of the
screen, or if no output is done to the region, then the window
is unaffected. But if a SIZ$ was done, and any character was
"output", then that window is considered to have been written.
Any DPY$ or REF$ will show all changes accumulated since the
last DPY$ or REF$, so that it is possible to do many SIZ$ LUUOs
before updating the screen. The only restriction is that the
windows cannot overlap. The format of the LUUO is
SIZ$ [ minimum line,,maximum line
minimum column,,maximum column ]
where the minimum and maximum lines and columns specify the
boundary of the window. The value "-1" can be used for the
maximums to indicate the extreme bottom and right edges of the
screen.
If the effective address of the LUUO is zero, the window is
assumed to be the whole screen.
The following describes how to divide the screen into two
windows, one on the left and one on the right. A blank column
is left between them to separate their output some.
SIZ$ [ 0,,-1 ;WANT ALL LINES
0,,^D20] ;BUT ONLY OVER TO COLUMN 20
... ;TYPE DATA FOR THIS WINDOW
SIZ$ [ 0,,-1 ;AGAIN WANT ALL LINES
^D22,,-1] ;BUT NOW ONLY COLUMNS 22 AND ONWARD
... ;TYPE DATA FOR THIS WINDOW TOO
LOC$ This LUUO is used to return the screen location where "output"
given by STR$, CHR$, or CHI$ would next go. Thus the program
can compute how much of the current line or window is filled,
and use that data for further output. The most common use is
for determining if the screen has been filled, so that further
output can be avoided (since it would not be seen). The format
of this LUUO is:
LOC$ address
where address will get the value <line,,column> where "output"
would next be put. If a line has been overflowed so that no
more output would be seen, then column is -1. If the whole
window is overflowed so that no more output could be seen, then
the whole value is -1. Thus the following instructions will
determine if the screen is full of data yet:
LOC$ T1 ;GET "OUTPUT" LOCATION
JUMPL T1,RSKP ;SKIP IF SCREEN IS FULL
RET ;SCREEN NOT YET FULL, NON-SKIP
SET$ This LUUO is used to set various parameters for different
actions than normal. There are two formats in using this LUUO.
They are:
SET$ [ function,,argument]
for setting only one parameter, and
SET$ [ 0,,count
function 1,,argument 1
...
function n,,argument n ]
for setting a multitude of parameters. These can be
distinguished since all the function codes are nonzero. Read
DPYDEF.MAC for a list of possible functions. The most useful
ones are:
SET$ [SE$ACR,,1]
for setting automatic CRLFs. Without this function being done,
when "output" reaches the end of a line, further output is
ignored until a line feed is seen. If this function has been
done, then when the rightmost column of the window has been
reached, an automatic CRLF is performed and further output will
be on the next line.
SET$ [SE$UOK,,1]
for indicating updating of the same location is OK. This allows
windows to overlap without complaining. This is usually
disallowed since unnecessary updating can take place, and
overlapping windows usually indicate a program bug. But
sometimes this is desirable, such as to forcably clear a region
of a screen so a command can be input. A window is set, the
window is filled with "X" characters, the window is reset to the
same location again, and a space is output. Then DPY will have
to update the whole window, thereby clearing it of user input.
SET$ [SE$EAT,,n]
instructs DPY to ignore "output" until n line feeds have been
seen. This allows scrolling of the screen to be possible, since
if this function is set, the desired number of lines will not
be displayed.
The table pointed to by the symbol DPYTAB contains some useful data. If
the data is stagnent, then the offset into DPYTAB is the data itself.
But if the data is variable, then the table entry is the address of the
actual data. Some of the most useful locations in the table are:
DPYTAB+$DPLEN address of word containing length of terminal (minus 1)
DPYTAB+$DPWID address of word containing width of terminal (minus 1)
DPYTAB+$DPTYP address of TBLUK table for terminal types known to DPY
DPYTAB+$DPJFN address of word containing the JFN being used for output
DPYTAB+$DPEAT address of word containing number of lines remaining to "eat"
Random notes:
Most control characters are ignored when "output" is done to DPY
using CHR$, CHI$, and STR$ functions. Only TAB and line feed have
actions. All other control characters are ignored, as are rubouts and
characters too high for the terminal to print.
More, but too tired...
For more information, see David Bell, MR1-2/E37, X6114