Google
 

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