{Begin SubSec Prettyprint}
{Title Prettyprint}
{Text


{note The {fn PRETTYPRINT} package was written by W. Teitelman.}

The standard way of printing out function definitions (on the terminal or into files) is to use {fn PRETTYPRINT}.

{FnDef {FnName PRETTYPRINT} {FnArgs FNS PRETTYDEFLG {anonarg}}
{Text
{arg FNS} is a list of functions.  If {arg FNS} is atomic, its value is used).  The definitions of the functions are printed in a pretty format on the primary output file using the primary readtable.  For example, if {lisp FACTORIAL} were defined by typing

{lispcode (DEFINEQ (FACTORIAL [LAMBDA (N) (COND ((ZEROP N) 1)
(T (ITIMES N (FACTORIAL (SUB1 N]}

{lisp (PRETTYPRINT '(FACTORIAL))} would print out

{lispcode
(FACTORIAL
  [LAMBDA (N)
    (COND
      ((ZEROP N)
        1)
      (T (ITIMES N (FACTORIAL (SUB1 N])}


{arg PRETTYDEFLG} is {lisp T} when called from {fn PRETTYDEF} (and hence {fn MAKEFILE}).  Among other actions taken when this argument is true, {fn PRETTYPRINT} indicates its progress in writing the current output file: whenever it starts a new function, it prints on the terminal the name of that function if more than 30 seconds (real time) have elapsed since the last time it printed the name of a function.
}}


{fn PRETTYPRINT} operates correctly on functions that are {prop BROKEN}, {prop BROKEN-IN}, {prop ADVISED}, or have been compiled with their definitions saved on their property lists: it prints the original, pristine definition, but does not change the current state of the function.  If a function is not defined but is known to be on one of the files noticed by the file package, {fn PRETTYPRINT} loads in the definition (using {fn LOADFNS}) and prints it (except when called from {fn PRETTYDEF}).  If {fn PRETTYPRINT} is given an atom which is not the name of a function, but has a value, it prettyprints the value.  Otherwise, {fn PRETTYPRINT} attempts spelling correction.  If all fails, {fn PRETTYPRINT} returns {lisp ({arg FN} NOT PRINTABLE)}.

{indexX {Name NOT PRINTABLE}
	{Type (returned by PRETTYPRINT)}
	{Text {lisp ({arg FN} NOT PRINTABLE)} }
}



{FnDef {FnName PP} {FnArgs FN{sub 1} {ellipsis} FN{sub N}}
{Type NOSPREAD NLAMBDA}
{Text
For prettyprinting functions to the terminal.  {fn PP} calls {fn PRETTYPRINT} with the primary output file set to {lisp T} and the primary read table set to {lisp T}.  The primary output file and primary readtable are restored after printing.

{lisp (PP FOO)} is equivalent to {lisp (PRETTYPRINT '(FOO))};
{lisp (PP FOO FIE)} is equivalent to {lisp (PRETTYPRINT '(FOO FIE))}.
}}


As described above, when {fn PRETTYPRINT}, and hence {fn PP}, is called with the name of a function that is not defined, but whose definition is on a file known to the file package, the definition is automatically read in and then prettyprinted.  However, if the user does not intend on editing or running the definition, but simply wants to {it see} the definition, the function {fn PF} described below can be used to simply copy the corresponding characters from the file to the terminal.  This results in a savings in both space and time, since it is not necessary to allocate storage to actually read in the definition, and it is not necessary to re-prettyprint it (since the function is already in prettyprint format on the file).


{FnDef {FnName PF} {FnArgs FN FROMFILES TOFILE}
{Type NOSPREAD NLAMBDA}
{Text
Copies the definition of {arg FN} found on each of the files in {arg FROMFILES} to {arg TOFILE}.  If {arg TOFILE}={lisp NIL}, defaults to {lisp T}.  If {arg FROMFILES}={lisp NIL}, defaults to {lisp (WHEREIS {arg FN} NIL T)} (see {PageRef Fn WHEREIS}).  The typical usage of {fn PF} is simply to type "{lisp PF {arg FN}}".
}}


When printing to the terminal, {fn PF} performs several transformations on the characters in the file that comprise the definition for {arg FN}: (1) font information ({PageRef Tag FontPackage}) is stripped out (except in Interlisp-D, whose display supports multiple fonts); (2) occurrences of the {var CHANGECHAR} ({PageRef Var CHANGECHAR}) are not printed; (3) since functions typically tend to be printed to a file with a larger linelength than when printing to a terminal, the number of leading spaces on each line is cut in half;{foot
Unless {var PFDEFAULT}{Index PFDEFAULT Var} is {lisp T}.  {var PFDEFAULT} is initially {lisp NIL}.
}{comment endfootnote}
and (4) comments are elided, if {var **COMMENT**FLG} is non-{lisp NIL} (see {PageRef Var **COMMENT**FLG}). 

While the function {fn PRETTYPRINT} prints entire function definitions, the function {fn PRINTDEF} can be used to print parts of functions, or arbitrary Interlisp structures:

{FnDef {FnName PRINTDEF} {FnArgs EXPR LEFT DEF TAILFLG FNSLST FILE}
{Text
Prints the expression {arg EXPR} in a pretty format on {arg FILE} using the primary readtable.  {arg LEFT} is the left hand margin{index margins (for PRETTYPRINT)} ({fn LINELENGTH} determines the right hand margin.){foot
{fn PRINTDEF} initially performs {lisp (TAB {arg LEFT} T)}, which means to space to position {arg LEFT}, unless already beyond this position, in which case it does nothing.
}{comment endfootnote}

{arg DEF}={lisp T} means {arg EXPR} is a function definition, or a piece of one.  If {arg DEF}={lisp NIL}, no special action is taken for {lisp LAMBDA}'s, {fn PROG}'s, {fn COND}'s, comments, CLISP, etc.
{arg DEF} is {lisp NIL} when {fn PRETTYDEF} calls {fn PRETTYPRINT} to print variables and property lists, and when {index PRINTDEF FN}{fn PRINTDEF} is called from the editor via the command {index PPV EditCom}{editcom PPV}.

{arg TAILFLG}={lisp T} means {arg EXPR} is interpreted as a tail of a list, to be printed without parentheses.

{arg FNSLST} is for use with the Font package ({PageRef Tag FontPackage}).  {fn PRINTDEF} prints occurrences of any function in the list {arg FNSLST} in a different font, for emphasis.  {fn MAKEFILE} passes as {arg FNSLST} the list of all functions on the file being made.
}}


{Begin SubSec Comment Feature}
{Title Comment Feature}
{Text



{index *BEGIN* comments (in listings)}

{Tag CommentFeature}

A facility for annotating Interlisp functions is provided in {fn PRETTYPRINT}.
Any expression beginning with the atom {index *PRIMARY* * (use in comments)}{lisp *} is interpreted as a comment and printed in the right margin.  Example:


{lispcode
(FACTORIAL
   [LAMBDA (N)                                  (* COMPUTES N!)
        (COND
          ((ZEROP N)                            (* 0!=1)
            1)
          (T                                    (* RECURSIVE DEFINITION:
                                                   N!=N*N-1!)
            (ITIMES N (FACTORIAL (SUB1 N])}


These comments actually form a part of the function definition.  Accordingly, {lisp *} is defined as an nlambda nospread function that returns its argument, similar to {fn QUOTE}.  When running an interpreted function, {lisp *} is entered the same as any other Interlisp function.  Therefore, comments should only be placed where they will not harm the computation, i.e., where a quoted expression could be placed.  For example, writing

{lispcode (ITIMES N (FACTORIAL (SUB1 N)) (* RECURSIVE DEFINITION))}

in the above function would cause an error when {lisp ITIMES} attempted to multiply {lisp N}, {lisp N-1!}, and {lisp RECURSIVE}.



For compilation purposes, {lisp *} is defined as a macro which compiles into no instructions (unless the comment has been placed where it has been used for value, in which case the compiler prints an appropriate error message and compiles {lisp *} as {fn QUOTE}).  Thus, the compiled form of a function with comments does not use the extra atom and list structure storage required by the comments in the source (interpreted) code.  This is the way the comment feature is intended to be used.


A comment of the form {lisp (* E {arg X})} causes {arg X} to be evaluated at prettyprint time, as well as printed as a comment in the usual way.  For example, {lisp (* E (RADIX 8))} as a comment in a function containing octal numbers can be used to change the radix to produce more readable printout.{index E (use in comments)}



The comment character {lisp *} is stored in the variable {var COMMENTFLG}.  The user can set it to some other value, e.g. "{lisp ;}", and use this to indicate comments.

{VarDef {Name COMMENTFLG}
{Text
{index *PRIMARY* COMMENTFLG Var}If {fn CAR} of an expression is {fn EQ} to {var COMMENTFLG}, the expression is treated as a comment by {fn PRETTYPRINT}.  {var COMMENTFLG} is initialized to {lisp *}.{index * (use in comments)}  Note that whatever atom is chosen for {var COMMENTFLG} should also have an appropriate function definition and compiler macro, for example, by copying those of {lisp *}.
}}



Comments are designed mainly for documenting {it listings}.  Therefore, when prettyprinting to the {index terminal}terminal, comments are suppressed and printed as the string {lisp **COMMENT**}.{index **COMMENT** (Printed by System)}  The value of {var **COMMENT**FLG} determines the action.


{VarDef {Name **COMMENT**FLG}
{Text
{index *PRIMARY* **COMMENT**FLG Var}If {var **COMMENT**FLG} is {lisp NIL}, comments are printed.  Otherwise, the value of {var **COMMENT**FLG} is printed.  Initially {lisp " **COMMENT** "}.
}}



The functions {fn PP*} and {fn PF*} are provided to easily print functions, including their comments.

{FnDef {FnName PP*} {FnArgs X}
{Type NOSPREAD NLAMBDA}
{Text
{fn PP*} operates exactly like {fn PP} except it first sets {var **COMMENT**FLG} to {lisp NIL}, so comments are printed in full.
}}

{FnDef {FnName PF*} {FnArgs FN FROMFILES TOFILE}
{Type NOSPREAD NLAMBDA}
{Text
{fn PF*} operates exactly like {fn PF} except it first sets {var **COMMENT**FLG} to {lisp NIL}, so comments are printed in full.
}}

{FnDef {FnName COMMENT1} {FnArgs L {anonarg}}
{Text
Prints the comment {arg L}.  {fn COMMENT1} is a separate function{foot
{fn COMMENT1} is an entry to the {fn PRETTYPRINT} block.  However, it is called internally by {fn PRETTYPRINT} so that advising or redefining it will not affect the action of {fn PRETTYPRINT}.  {fn COMMENT1} should {it not} be called when not under a {fn PRINTDEF}.  {note ???}
}{comment endfootnote}
to permit the user to write prettyprint macros ({PageRef Var PRETTYPRINTMACROS}) that use the regular comment printer.  For example, to cause comments to be printed at a larger than normal linelength, one could put an entry for {lisp *} on {var PRETTYPRINTMACROS}:

{lispcode (* LAMBDA (X) (RESETFORM (LINELENGTH 100) (COMMENT1 X)))}

This macro resets the line length, prints the comment, and then restores the line length.

{fn COMMENT1} expects to be called from within the environment established by {fn PRINTDEF}, so ordinarily the user should call it {it only} from within prettyprint macros.
}}


}{End SubSec Comment Feature}


{Begin SubSec Comment Pointers}
{Title Comment Pointers}
{Text


{Tag CommentPointer}

{index comment pointers}

For a well-commented collection of programs, the list structure, atom, and pname storage required to represent the comments in core can be significant.  If the comments already appear on a file and are not needed for editing, a significant savings in storage can be achieved by simply leaving the text of the comment on the file when the file is loaded, and instead retaining in core only a {it pointer} to the comment.  This feature has been implemented by defining {lisp *} as
a read-macro{index * (as a read-macro)} in {var FILERDTBL} which, instead of reading in the entire text of the comment, constructs an expression containing (1) the name of the file in which the text of the comment is contained, (2) the address of the first character of the comment, (3) the number of characters in the comment,  and (4) a flag indicating whether the comment appeared
at the right hand margin or centered on the page.
For output purposes, {lisp *} is defined on {var PRETTYPRINTMACROS} ({PageRef Var PRETTYPRINTMACROS}){index * (as a prettyprint macro)} so that it prints the comments represented by such pointers by simply copying the corresponding characters from one file to another, or to the terminal.  Normal comments are processed the same as before, and can be intermixed freely with comment pointers.


The comment pointer feature is controlled by the value of {var NORMALCOMMENTSFLG}.

{VarDef {Name NORMALCOMMENTSFLG}
{Text
The comment pointer feature is enabled by setting {var NORMALCOMMENTSFLG} to {lisp NIL}.  {var NORMALCOMMENTSFLG} is initially {lisp T}.

{var NORMALCOMMENTSFLG} can be changed as often as desired.  Thus, some files can be loaded normally, and others with their comments converted to comment pointers.
}}


For convenience of editing selected comments, an edit macro, {editcom GET*}{index GET* EditCom}, is included, which loads in the text of the corresponding comment.  The editor's
{fn PP*} command, in contrast, prints the comment {it without} reading it by simply copying the corresponding characters to the terminal.
{index * (as a read-macro)}
{editcom GET*} is defined in terms of {fn GETCOMMENT}:


{FnDef {FnName GETCOMMENT} {FnArgs X DESTFL {anonarg}}
{Text
If {arg X} is a comment pointer, replaces {arg X} with the actual text of the comment, which it reads from its file.  Returns {arg X} in all cases.  If {arg DESTFL} is non-{lisp NIL}, it is the name of an open file, to which {fn GETCOMMENT} copies the comment; in this case, {arg X} remains a comment pointer, but it has been changed to point to the new file (unless {var NORMALCOMMENTSFLG} = {lisp DONTUPDATE}).
}}

{FnDef {FnName PRINTCOMMENT} {FnArgs X}
{Text
Defined as the prettyprint macro for {lisp *}: copies the comment to the primary output file by using {fn GETCOMMENT}.
}}

{FnDef {FnName READCOMMENT} {FnArgs FL RDTBL LST}
{Text
Defined as the read macro for {lisp *} in {lisp FILERDTBL}: if {var NORMALCOMMENTSFLG} is {lisp NIL}, it constructs a comment pointer.{foot
Unless it believes the expression beginning with {lisp *} is not actually a comment, e.g., if the next atom is "{lisp .}" or {lisp E}.
}{comment endfootnote}
}}


Note that a certain amount of care is required in using the comment pointer feature.  Since the text of the comment resides on the file pointed to by the comment pointer, that file must remain in existence as long as the comment is needed.  {fn GETCOMMENT} helps out by changing the comment pointer to always point at the most recent file that the comment lives on.  However, if the user has been performing repeated {fn MAKEFILE}'s ({PageRef Fn MAKEFILE}) in which differing functions have changed at each invocation of {fn MAKEFILE}, it is possible for the comment pointers in memory to be pointing at several versions of the same file, since a comment pointer is only updated when the function it lives in is prettyprinted, not when the function has been copied verbatim to the new file.  This can be a problem for file systems, such as Tenex and Tops20, that have a built-in limit on the number of versions of a given file that will be made before old versions are expunged.  In such a case, the user should set the version retention count of any directories involved to be infinite.  {fn GETCOMMENT} prints an error message if the file that the comment pointer points at has disappeared.

Similarly, one should be cognizant of comment pointers in {lisp SYSOUT}s, and be sure to retain any files thus pointed to.

When using comment pointers, the user should also not set {var PRETTYFLG} ({PageRef Var PRETTYFLG}) to {lisp NIL} or call {fn MAKEFILE} with option {lisp FAST}, since this will prevent functions from being prettyprinted, and hence not get the text of the comment copied into the new file.


If the user changes the value of {var COMMENTFLG}{index COMMENTFLG Var} but still wishes to use the comment pointer feature, the new {var COMMENTFLG} should be given the same read-macro definition in {var FILERDTBL} as {lisp *} has, and the same entry be put on {var PRETTYPRINTMACROS}.  For example, if {var COMMENTFLG} is reset to be "{lisp ;}", then {lisp (SETSYNTAX '; '* FILERDTBL)} should be performed, and {lisp (; . PRINTCOMMENT)} added to {var PRETTYPRINTMACROS}.

}{End SubSec Comment Pointers}



{Begin SubSec Converting Comments to Lower Case}
{Title Converting Comments to Lower Case}
{Text

{index *BEGIN* lower case comments}

{Tag LowerCaseComments}


This section is for users operating on terminals without lower case, e.g. model 33 teletypes, who nevertheless would like their comments to be converted to lower case for more readable line-printer listings.  If the second atom in a comment is {lisp %%}, the text of the comment is converted to lower case so that it looks like English instead of LISP.  Note that comments are converted {it only} when they are actually written to a file by {fn PRETTYPRINT}.


The algorithm for conversion to lower case is the following:  If the first character in an atom is {lisp ↑},{index ↑ (use in comments)} do not change the atom (but remove the {lisp ↑}).  If the first character is {lisp %},{index % (use in comments)} convert the atom to lower case.{foot 
User must type {lisp %%} as {lisp %} is the escape character.
}{comment endfootnote}
If the atom (minus any trailing punctuation marks) is an Interlisp word,{foot 
i.e., is a bound or free variable for the function containing the comment, or has a top level value, or is a defined function, or has a non-{lisp NIL} property list.
}{comment endfootnote}
do not change it.
Otherwise, convert the atom to lower case.
Conversion only affects the upper case alphabet, i.e., atoms already converted to lower case are not changed if the comment is converted again.
When converting, the first character in the comment and the first character following each period are left capitalized.
After conversion, the comment is physically modified to be the lower case text minus the {lisp %%}{index %% (use in comments)} flag, so that conversion is thus only performed once (unless the user edits the comment inserting additional upper case text and another {lisp %%} flag).

{VarDef {Name LCASELST}
{Text
Words on {var LCASELST}{index LCASELST Var} will always be converted to lower case.  {var LCASELST} is initialized to contain words which are Interlisp functions but also appear frequently in comments as English words ({lisp AND}, {lisp EVERY}, {lisp GET}, {lisp GO}, {lisp LAST},  {lisp LENGTH}, {lisp LIST}, etc.).  Therefore, if one wished to type a comment including the lisp fuction {fn GO}, it would be necessary to type {lisp ↑GO} in order that it might be left in upper case.
}}

{VarDef {Name UCASELST}
{Text
Words on {var UCASELST}{index UCASELST Var} (that do not appear on {var LCASELST}) will be left in upper case.  {var UCASELST} is initialized to {lisp NIL}.
}}

{VarDef {Name ABBREVLST}
{Text
{var ABBREVLST}{index *PRIMARY* ABBREVLST Var} is used to distinguish between abbreviations and words that end in periods.  Normally, words that end in periods and occur more than halfway to the right margin cause carriage-returns.  Furthermore, during conversion to lowercase, words ending in periods, except for those on {var ABBREVLST}, cause the first character in the {it next} word to be capitalized.  {var ABBREVLST} is initialized to the upper and lower case forms of {lisp ETC.}, {lisp I.E.}, and {lisp E.G.}.
}}


{index *END* lower case comments}
{index *END* comments (in listings)}

}{End SubSec Converting Comments to Lower Case}


{Begin SubSec Special Prettyprint Controls}
{Title Special Prettyprint Controls}
{Text


{VarDef {Name PRETTYTABFLG}
{Text
{index PRETTYTABFLG Var}In order to save space on files, tabs are used instead of spaces for the inital spaces on each line, assuming that each tab corresponds to 8 spaces.  This results in a reduction of file size by about 30%.  Tabs are not used if {var PRETTYTABFLG} is set to {lisp NIL} (initially {lisp T}).
}}


{VarDef {Name #RPARS}
{Text
Controls the number of right parentheses necessary for square bracketing to occur.{index square brackets inserted by PRETTYPRINT}{index [,] inserted by PRETTYPRINT}
If {var #RPARS}={lisp NIL}, no brackets are used.  {var #RPARS} is initialized to 4.
}}



{VarDef {Name FIRSTCOL}
{Text
The starting column for comments.  Initial setting is 48.
Comments run between {var FIRSTCOL} and {fn LINELENGTH}.
If a word in a comment ends with a "{lisp .}" and is not on the list {index ABBREVLST Var}{var ABBREVLST}, and the position is greater than halfway between {var FIRSTCOL} and {fn LINELENGTH}, the next word in the comment begins on a new line.  Also, if a list is encountered in a comment, and the position is greater than halfway, the list begins on a new line.
}}


{VarDef {Name PRETTYLCOM}
{Text
If a comment is bigger (using {fn COUNT}) than {var PRETTYLCOM} in size, it is printed starting at column 10, instead of {var FIRSTCOL}.  {var PRETTYLCOM} is initialized to 14 (arrived at empirically).  Comments are also printed starting at column 10 if their second element is also a {lisp *}, i.e., comments of the form {lisp (* * --)}.
}}


{VarDef {Name #CAREFULCOLUMNS}
{Text
In the interests of efficiency, {fn PRETTYPRINT} approximates the number of characters in each atom, rather than calling {fn NCHARS}, when computing how much will fit on a line.  This procedure works satisfactorily in most cases.  However, users with unusually long atoms in their programs, e.g., such as produced by {fn CLISPIFY}, may occasionlly encounter some glitches in the output produced by {fn PRETTYPRINT}.  The value of {var #CAREFULCOLUMNS} tells {fn PRETTYPRINT} how many columns (counting from the right hand margin) in which to actually compute {fn NCHARS}
instead of approximating.  Setting {var #CAREFULCOLUMNS} to 20 or 30 will eliminate the glitches, although it will slow down {fn PRETTYPRINT} slightly.  {var #CAREFULCOLUMNS} is initially 0.
}}


{FnDef {FnName WIDEPAPER} {FnArgs FLG}
{Text
{lisp (WIDEPAPER T)} sets {var FILELINELENGTH}{index FILELINELENGTH Var} to 120, {index FIRSTCOL Var}{var FIRSTCOL} to 80, and {index PRETTYLCOM Var}{var PRETTYLCOM} to 28.  These are useful settings for prettyprinting files to be listed on wide paper.  {lisp (WIDEPAPER)} restores these parameters to their initial values.  The value of {fn WIDEPAPER} is its previous setting.
}}



{note should PRETTYFLG be moved near PRINTDEF (in PRETTYDEF section) ??}

{VarDef {Name PRETTYFLG}
{Text
If {var PRETTYFLG} is {lisp NIL}, {index PRINTDEF FN}{fn PRINTDEF} uses {fn PRIN2} instead of prettyprinting.
This is useful for producing a fast symbolic dump{index fast symbolic dump}  (see {lisp FAST} option of {fn MAKEFILE}, {PageRef Fn MAKEFILE}).
Note that the file loads the same as if it were prettyprinted.  {var PRETTYFLG} is initially set to {lisp T}.  {var PRETTYFLG} should not be set to {lisp NIL} if comment pointers ({PageRef tag CommentPointer}) are being used.
}}


{VarDef {Name CLISPIFYPRETTYFLG}
{Text
Used to inform {fn PRETTYPRINT} to call {fn CLISPIFY} on selected function definitions before printing them (see {PageRef Var CLISPIFYPRETTYFLG}).
}}


{VarDef {Name PRETTYPRINTMACROS}
{Text
An association-list that enables the user to control the formatting of selected expressions.  {fn CAR} of each expression being {fn PRETTYPRINT}ed is looked up on {var PRETTYPRINTMACROS}, and if found, {fn CDR} of the corresponding entry is applied to the expression.  If the result of this application is {lisp NIL}, {fn PRETTYPRINT} ignores the expression; i.e., it prints nothing, assuming that the prettyprintmacro has done any desired printing.  If the result of applying the prettyprint macro is non-{lisp NIL}, the result is prettyprinted in the normal fashion.  This gives the user the option of computing some other expression to be prettyprinted in its place.

Note:  "prettyprinted in the normal fashion" includes processing prettyprint macros, unless the prettyprint macro returns a structure {lisp EQ} to the one it was handed, in which case the potential recursion is broken.
}}


{VarDef {Name PRETTYPRINTYPEMACROS}
{Text
A list of elements of the form {lisp ({arg TYPENAME} . {arg FN})}.  For types other than lists and atoms, the type name of each datum to be prettyprinted is looked up on {var PRETTYPRINTYPEMACROS}, and if found, the corresponding function is applied to the datum about to be printed, instead of simply printing it with {fn PRIN2}.
}}


{VarDef {Name PRETTYEQUIVLST}
{Text
An association-list that tells {fn PRETTYPRINT} to treat a {fn CAR}-of-form the same as some other {fn CAR}-of-form.  For example, if {lisp (QLAMBDA . LAMBDA)} appears on {var PRETTYEQUIVLST}, then expressions beginning with {lisp QLAMBDA} are prettyprinted the same as {lisp LAMBDA}s.  Currently, {var PRETTYEQUIVLST} only allows (i.e., supports in an interesting way) equivalences to forms that {fn PRETTYPRINT} internally handles.  Equivalence to forms for which the user has specified a prettyprint macro should be made by adding further entries to {var PRETTYPRINTMACROS}
}}


{index *PRIMARY* CHANGECHAR Var}

{VarDef {Name CHANGECHAR}
{Text
If non-{lisp NIL}, and {fn PRETTYPRINT} is printing to a file or display terminal, {fn PRETTYPRINT} prints {var CHANGECHAR} in the right hand margin while printing those expressions marked by the editor as having been changed (see {PageRef Tag EditorChangeMarks}).  {var CHANGECHAR} is initially {lisp |}.{index *PRIMARY* | (change character)}
}}


}{End SubSec Special Prettyprint Controls}



{Begin SubSec Font Package}
{Title Font Package}
{Text

{Tag FontPackage}
{Tag FontProfile}

{index *BEGIN* font package}

{note this needs to be EXTENSIVELY revised.  This has been changed drastically in Interlisp-D. (First cut taken, 15 Feb 84, Beau Sheil - more needed.)}

{fn PRETTYPRINT} contains a facility for printing different elements (user functions, system functions, clisp words, comments, etc.) in different fonts to emphasize (or deemphasize) their importance, and in general to provide for a more pleasing appearance.  Of course, in order to be useful, this facility requires that the user is printing on a device (such as a bitmapped display or a laser printer) which supports multiple fonts.

{fn PRETTYPRINT} signals font changes by inserting into the file a user-defined escape sequence (the value of the variable {var FONTESCAPECHAR}) followed by the character {it code} which specifies, by number, which font to use, i.e. {lisp ↑A} for font number 1, etc. Thus, if {var FONTESCAPECHAR} were the character {lisp ↑F}, {lisp ↑F↑C} would be output to change to font 3, {lisp ↑F↑A} to change to font 1, etc.  If {var FONTESCAPECHAR} consists of characters which are separator charactors in {var FILERDTBL}, then a file with font changes in it can also be loaded back in.

Currently, {fn PRETTYPRINT} uses the following font classes.  The user can specify separate fonts for each of these classes, or use the same font for several different classes.



{note Are these 'font classes' actually variables?  Should they be specified with VarDef's rather than a 'labeledlist'? Ans:  They are, but only incidentally. This format is right.}

{Begin LabeledList font classes}

{Label {lisp LAMBDAFONT}}
{Text
{index LAMBDAFONT (font class)}The font for printing the name of the function being prettyprinted, before the actual definition (usually a large font).
}

{Label {lisp CLISPFONT}}
{Text
{index CLISPFONT (font class)}If {var CLISPFLG} is on, the font for printing any clisp words, i.e. atoms with property {prop CLISPWORD}.
}

{Label {lisp COMMENTFONT}}
{Text
{index COMMENTFONT (font class)}The font used for comments.
}

{Label {lisp USERFONT}}
{Text
{index USERFONT (font class)}The font for the name of any function in the file, or any member of the list {var FONTFNS}.{index FONTFNS Var}
}

{Label {lisp SYSTEMFONT}}
{Text
{index SYSTEMFONT (font class)}The font for any other (defined) function.
}

{Label {lisp CHANGEFONT}}
{Text
{index CHANGEFONT (font class)}The font for an expression marked by the editor as having been changed.
}

{Label {lisp PRETTYCOMFONT}}
{Text
{index PRETTYCOMFONT (font class)}The font for the operand of a file package command.
}

{Label {lisp DEFAULTFONT}}
{Text
{index DEFAULTFONT (font class)}The font for everything else.
}

{End LabeledList font classes}


Note that not all combinations of fonts will be aesthetically pleasing (or even readable!) and the user may have to experiment to find a compatible set.


Although in some implementations {lisp LAMBDAFONT} et al. may be defined as variables, one should not set them directly, but should indicate what font is to be used for each class by including an appropriate entry in {var FONTPROFILE}.  {fn FONTSET} will then define the data structures that contain the necessary information for performing font changes.


{VarDef {Name FONTPROFILE}
{Text
A list of elements which defines the correspondence between font classes and specific fonts.  In Interlisp-D, {var FONTPROFILE} is a list of the form {lisp ({arg FONTCLASS} {arg FONT#} {lisp dspfontname} {lisp pressfontname} {lisp interpressfontname})}.  In Interlisp-10, {var FONTPROFILE} is a list of the form {lisp ({arg FONTCLASS} {arg FONT#})}.  In both cases, {arg FONTCLASS} is a font class and {arg FONT#} is the font number for that class.  For each font class, the escape sequence will consist of {var FONTESCAPECHAR} followed by the character {it code} for the font number, e.g. {lisp ↑A} for font number 1, etc.

If {arg FONT#} is {lisp NIL} for any fontclass, the {lisp DEFAULTFONT} (which must always be specified) is used.  Alternatively, if {arg FONT#} is the name of a previously defined fontclass, this fontclass will be equivalenced to the previously defined one.

In Interlisp-D, {lisp dspfontname}, {lisp pressfontname}, and {lisp interpressfontname} are font specifications (of the form accepted by {fn FONTCREATE}) for the fonts to use when printing to the display and to files respectively.  (Most users are more comfortable with a larger font on the display than on listings).  In Interlisp-10, it is assumed that the user has some way (external to Lisp) of communicating to the printing device the correspondence between font numbers and fonts.  

}}



Printing with multiple fonts is affected by a large number of parameters, e.g. {var FILELINELENGTH}, etc. plus the various font classes themselves.  To facilitate switching back and forth between various configurations, the font package allows the user to set the various parameters to their desired values, and then use the function {fn FONTNAME} to package up and save this configuration.  Subsequently, the user invokes this configuration by performing {lisp (FONTSET {arg NAME})}. The user may also want to reset {var FILELINELENGTH} ({PageRef Var FILELINELENGTH}), {var PRETTYLCOM} ({PageRef Var PRETTYLCOM}), and {var FIRSTCOL} ({PageRef Var FIRSTCOL}) as a part of various font configurations.



{FnDef {FnName FONTNAME} {FnArgs NAME}
{Text
Performs some processing on {var FONTPROFILE}, and then collects names and values of variables on {var FONTDEFSVARS}, and saves them on {var FONTDEFS}.
}}


{FnDef {FnName FONTSET} {FnArgs NAME}
{Text
Installs font configuration for {arg NAME}.  Generates an error if {arg NAME} not previously defined.
}}

{VarDef {Name FONTDEFSVARS}
{Text
The list of variables to be packaged by a {fn FONTNAME}.  Initially {var FONTCHANGEFLG}, {var FILELINELENGTH}, {var COMMENTLINELENGTH}, {var FIRSTCOL}, {var PRETTYLCOM}, {var LISTFILESTR}, and {var FONTPROFILE}.
}}


{VarDef {Name FONTDEFS}
{Text
The dictionary of font configurations.  {var FONTDEFS} is a list of elements of form {lisp ({arg NAME} . {arg PARAMETER-PAIRS})}.  To save a configuration on a file after performing a {fn FONTNAME} to define it, the user could either save the entire value of {var FONTDEFS}, or simply use an {filecom ALISTS} file package command ({PageRef FileCom ALISTS}) to dump out just the one configuration.
}}


{VarDef {Name FONTESCAPECHAR}
{Text
The character or string used to signal the start of a font escape sequence.
}}

{VarDef {Name FONTCHANGEFLG}
{Text
If {lisp T}, enables fonts, if {lisp NIL}, disables fonts, i.e. no font changes are performed when prettyprinting.
}}


{VarDef {Name LISTFILESTR}
{Text
In Interlisp-10, passed to the operating system by {fn LISTFILES} ({PageRef Fn LISTFILES}).  Can be used to specify subcommands to the {lisp LIST} command, e.g. to establish correspondance between font number and font name.
}}


{VarDef {Name COMMENTLINELENGTH}
{Text
Since comments are usually printed in a smaller font, {var COMMENTLINELENGTH} is provided to offset the fact that Interlisp does not know about font widths.  When {var FONTCHANGEFLG}={lisp T}, {fn CAR} of {var COMMENTLINELENGTH} is the linelength used to print short comments, i.e. those printed in the right margin, and {fn CDR} is the linelength used when printing full width comments.
}}



{FnDef {FnName CHANGEFONT} {FnArgs FONTCLASS FILE}
{Text
Executes the operations on {arg FILE} to change to {arg FONTCLASS}.  Note that {arg FONTCLASS} is a class, not a class name, so one should use {lisp (CHANGEFONT LAMBDAFONT FILE)}, not {lisp (CHANGEFONT 'LAMBDAFONT FILE)}.  For use in {var PRETTYPRINTMACROS}.
}}



{Begin Note}
Date: 18 May 1982 12:09 pm PDT (Tuesday)
From: JonL.PA

Points on the mail manual, not previously sent to MANUAL:
  2) P14.51ff, for "fontsets" -- I think a fontset should be described as a
     conceptual object with components (more like a DATATYPE or RECORD).
     That will make it more apparent that FONTESCAPECHAR is not a component
     of a fontset, whereas many of the other GLOBALVARS in this section
     are in fact to be viewed as components.  This touches on the sticky problem
     of using GLOBALVARS where one meant SPECIAL vars, as shown up by
     the multiprocessing problem; viewing a FONTSET as a compound object
     from the very beginning bypasses this problem.
     Questions: 
       2a) Does FONTNAME really mean "create a FontSet"?
       2b) Does FONTSET  mean "set the current (or default?) font
            configuration to be that of argument"?
       2c) CHANGEFONT, then, only retrieves information from the profile of
            the current font configuration, right? and then outputs a font
            change character sequence?
{End Note}


}{End SubSec Font Package}



}{End SubSec Prettyprint}