Displays output.
Synopsis
WRITE:pc writeargument,...
W:pc writeargument,...
where writeargument can be
f
expression
*integer-expression
Arguments
pc Optional — A postconditional expression.
f Optional — One or more format control code characters that position the output on the target device. Format control characters include !, #, ?, and /.
expression Optional — The value to write to the output device. Any valid Caché ObjectScript expression, including literals, variables, object methods, and object properties that evaluates to either a numeric or a quoted string.
*integer-expression Optional — The decimal code for a character to write to the output device. For ASCII, integers in the range 0 to 255; for Unicode, integers in the range 0 to 65534. Any valid Caché ObjectScript expression that evaluates to an integer in the appropriate range. The asterisk is mandatory.
Description
The WRITE command displays the specified output on the current I/O device. (To set the current I/O device, use the USE command, which sets the value of the $IO special variable.) WRITE has two forms:
WRITE without an Argument
WRITE without an argument lists the names and values of all defined variables in the local environment. It presents these variables as follows:
varname1=value1
varname2=value2
Note that an argumentless WRITE automatically provides formatting to separate the listed variables. It lists string values enclosed in double quotation marks.
A postconditional expression can be specified with an argumentless WRITE. An argumentless WRITE must be separated by at least two blank spaces from a command following it on the same line.
WRITE with Arguments
WRITE expression displays the sequence of characters identified by the expression. Expression can evaluate to a number or a quoted string.
WRITE *integer-expression displays the character represented by the integer expression.
A WRITE command can take any combination of expression, *integer-expression, and f arguments. WRITE arguments are separated by commas.
You must use the f argument and blank spaces within strings to provide any desired output formatting; WRITE with arguments provides no automatic formatting to separate argument values or indicate strings. For example:
   WRITE "numbers",1,2,3
   WRITE "letters","ABC"
 
displays as numbers123lettersABC.
Arguments
pc
An optional postconditional expression. Caché executes the command if the postconditional expression is true (evaluates to a non-zero numeric value). Caché does not execute the command if the postconditional expression is false (evaluates to zero). You can specify a postconditional expression for an argumentless WRITE or a WRITE with arguments. For further details, refer to Command Postconditional Expressions in Using Caché ObjectScript.
f
A format control to position the output on the target device. You can specify any combination of format control characters without intervening commas, but you must use a comma to separate a format control from an expression. For example, when you issue the following WRITE to a terminal:
   WRITE #!!!?6,"Hello",!,"world!"
The format controls position to the top of a new screen (#), then issue three line returns (!!!), then indent six columns (?6). The WRITE then displays the string Hello, issues a line return, then displays the string world!. Note that the line return repositions to column 1; thus in this example, Hello is displayed indented, but world! is not.
Format control characters cannot be used with an argumentless WRITE.
For further details, see Using Format Controls with WRITE .
expression
The value you wish to output. Most commonly this is either a quoted string or a numeric. However, expression can be any valid Caché ObjectScript expression, including literals, variables, object methods, and object properties. For more information on expressions, see Using Caché ObjectScript.
*integer-expression
Any valid Caché ObjectScript expression that evaluates to an integer that corresponds to a character. An integer-expression in the range of 0 through 255 evaluates to the corresponding 8-bit ASCII character. An integer-expression in the range of 256 through 65534 evaluates to the corresponding 16-bit Unicode character. Integer expressions can be used to display accented characters. For example to display the word “Caché” you can use:
   WRITE "Cach",*233
 
To write the name of the composer Anton Dvorak with the proper Czech accent marks, use:
   WRITE "Anton Dvo",*345,*225,"k"
 
Integer expressions can also be used to insert control characters (such as the line feed: *12) which govern the appearance of the display, or special characters such as *7, which rings the bell on a terminal.
Note:
An integer expression does not change the $X special variable when writing to a terminal. Thus, WRITE "a" and WRITE $CHAR(97) both increment the column number value contained in $X, but WRITE *97 does not increment $X. For further details, see the $X special variable, and “Terminal I/O” in Caché I/O Device Guide.
Examples
In the following example, the WRITE command sends the current value in variable var1 to the current output device.
  SET var1="hello world"
  WRITE var1
 
In the following example, both WRITE commands display the Unicode character for pi. The first uses an expression, the second an integer-expression:
   WRITE !,$CHAR(960)
   WRITE !,*960
 
The following example writes first name and last name values along with an identifying text for each. The WRITE command combines multiple arguments on the same line. It is equivalent to the two WRITE commands in the example that follows it. The ! character is a format control that produces a line break. (Note that the ! line break character is still needed when the text is output by two different WRITE commands.)
   SET fname="Bertie"
   SET lname="Wooster"
   WRITE "First name: ",fname,!,"Last name: ",lname
 
is equivalent to:
   SET fname="Bertie"
   SET lname="Wooster"
   WRITE "First name: ",fname,!
   WRITE "Last name: ",lname
 
In the following example, assume that the current device is the user's terminal. The READ command prompts the user for first name and last name and stores the input values in variables fname and lname, respectively. The WRITE command displays the values in fname and lname for the user's confirmation. The string containing a space character (" ") is included to separate the output names.
Test
  READ !,"First name: ",fname
  READ !,"Last name: ",lname
  WRITE !,fname," ",lname
  READ !,"Is this correct? (Y or N) ",check#1
  IF "Nn"[check {
    GOTO Test 
  }
The following example writes the current values in the ^client(1,n) nodes.
   SET ^client(1,1)="Mary Smith"
   SET ^client(1,2)="123 Primrose Path"
   SET ^client(1,3)="Johnson City"
   SET ^client(1,4)="TN"
   SET n=1
Elements
    IF $DATA(^client(1,n)) { 
      WRITE ^client(1,n),! 
      SET n=n+1 
      GOTO Elements
      }
    ELSE { QUIT }
 
The following command writes the current value of an object property:
   WRITE person.LastName
where person is the object reference, and LastName is the object property name. Note that dot syntax is used in object expressions; a dot is placed between the object reference and the object property name or object method name.
The following command writes the value returned by the object method TotalLines():
   WRITE invoice.TotalLines()
A write command for objects can take an expression with cascading dot syntax, as shown in the following example:
   WRITE patient.Doctor.Hospital.Name
In this example, the patient.Doctor object property references the Hospital object, which contains the Name property. Thus, this command writes the name of the hospital affiliated with the doctor of the specified patient. The same cascading dot syntax can be used with object methods.
A write command for objects can be used with system-level methods, such as the following data type property method:
   WRITE patient.AdmitDateIsValid(date)
In this example, the AdmitDateIsValid() property method returns its result for the current patient object. AdmitDateIsValid() is a boolean method for data type validation of the AdmitDate property. Thus, this command writes a 1 if the specified date is a valid date, and writes 0 if the specified date is not a valid date.
Note that any object expression can be further specified by declaring the class or superclass to which the object reference refers. Thus, the above examples could also be written:
   WRITE ##class(Patient)patient.Doctor.Hospital.Name
   WRITE ##class(Patient)patient.AdmitDateIsValid(date)
Notes
WRITE with $X and $Y
A WRITE displays the characters resulting from the expression evaluation one at a time in left-to-right order. Caché records the current output position in the $X and $Y special variables, with $X defining the current column position and $Y defining the current row position. As each character is displayed, $X is incremented by one.
In the following example, the WRITE command gives the column position after writing the 11–character string Hello world.
   WRITE "Hello world"," "_$X," is the column number"
Note that writing a blank space between the displayed string and the $X value (," ",$X) would cause that blank space to increment $X before it is evaluated; but concatenating a blank space to $X (," "_$X) displays the blank space, but does not increment the value of $X before it is evaluated.
Even using a concatenated blank, the display from $X or $Y does, of course, increment $X, as shown in the following example:
   WRITE $Y," "_$X
   WRITE $X," "_$Y
In the first WRITE, the value of $X is incremented by the number of digits in the $Y value (which is probably not what you wanted). In the second WRITE, the value of $X is 0.
With $X you can display the current column position during a WRITE command. To control the column position during a WRITE command, you can use the ? format control character. The ? format character is only meaningful when $X is at column 0. In the following WRITE commands, the ? performing indenting:
   WRITE !?5,"Hello world"
   WRITE "Hello",!?5,"world"
 
WRITE with Integer Expressions
The *integer-expression form allows you to write an integer code to the current device. Note that integer-expression can specify an arithmetic expression or variable name (local variable, process-private global, or global). The only requirement is that the resulting value be a positive integer. Integers in the range 0 to 255 correspond to the ASCII character set. Integers in the range 0 to 65534 correspond to the Unicode character set.
The following examples all return the word “Caché”:
   WRITE !,"Cach",*233
   WRITE !,*67,*97,*99,*104,*233
   SET accent=233
   WRITE !,"Cach",*accent  ; variables are evaluated
   WRITE !,"Cach",*232+1   ; arithmetic operations are evaluated
   WRITE !,"Cach",*00233.999 ; numbers are evaluated to integers
 
The integer resulting from the expression evaluation may correspond to a control character. Such characters are interpreted according to the target device. For example, if the current device is a terminal, the integer is interpreted as ASCII control characters. The following commands send ASCII codes 7 and 12 to the terminal.
   WRITE *7 ; Sounds the bell
   WRITE *12 ; Form feed (blank line)
Here's an example using the form feed character:
   WRITE "stepping",*12,"down",*12,"the",*12,"stairs"
Using Format Controls with WRITE
The f argument allows you to include any of the following format control characters. When used with output to the terminal, these controls determine where the output data appears on the screen. You can specify any combination of format control characters.
! Format Control Character
Advances one line and positions to column 0 ($Y is incremented by 1 and $X is set to 0). The actual control code sequence is device-dependent; it generally either ASCII 13 (RETURN), or ASCII 13 and ASCII 10 (LINE FEED).
Caché does not perform an implicit new line sequence for WRITE with arguments. When writing to a terminal it is a good general practice to begin (or end) every WRITE command with a ! format control character.
You can specify multiple ! format controls. For example, to advance five lines, WRITE !!!!!. You can combine ! format controls with other format controls. However, note that the following combinations, though permitted, are not in most cases meaningful: !# or !,# (advance one line, then advance to the top of a new screen, resetting $Y to 0) and ?5,! (indent by 5, then advance one line, undoing the increment). The combination ?5! is not legal.
If the current device is a TCP device, ! does not output a RETURN and LINE FEED. Instead, it flushes any characters that remain in the buffer and sends them across the network to the target system.
# Format Control Character
Outputs a FORM FEED (ASCII 12) character. On a terminal, it clears the current screen and starts at the top of the new screen in column 0. ($Y and $X are reset to 0.)
You can combine # format controls with other format controls. However, note that the following combinations, though permitted, are not in most cases meaningful: !# or !,# (advance one line, then advance to the top of a new screen, resetting $Y to 0) and ?5,# (indent by 5, then advance to the top of a new screen, undoing the increment). The combination ?5# is not legal.
?n Format Control Character
This format control consists of a question mark (?) followed by an integer, or an expression that evaluates to an integer. It positions output at the nth column location (counting from column 0) and resets $X. If this integer is less than or equal to the current column location (n<$X), this format control has no effect. You can reference the $X special variable (current column) when setting a new column position. For example, ?$X+3.
/mnemonic Format Control Character
This format control consists of a slash (/) followed by a mnemonic keyword, and (optionally) a list parameters to be passed to the mnemonic.
/mnemonic(param1,param2,...)
Caché interprets mnemonic as an entrypoint name defined in the active mnemonic space. This format control is used to perform such device functions as rewinding a magnetic tape or positioning the cursor on a screen. If there is no active mnemonic space, an error results. Amnemonic may (or may not) require a parameter list.
You can establish the active mnemonic space in either of the following ways:
The following are some examples of mnemonic device functions:
Mnemonic Description
/IC(n) Inserts spaces for n characters at the current cursor location, moving the rest of the line to the right
/DC(n) Deletes n characters to the right of the cursor and collapses the line
/EC(n) Erases n characters to the right of the cursor, leaving blanks in their stead
For further details on mnemonics, see the Caché I/O Device Guide.
Specifying a Sequence of Format Controls
Caché allows you to specify a sequence of format controls and to intersperse format controls and expressions. When specifying a sequence of format controls it is not necessary to include the comma separator between them (though commas are permitted.) A comma separator is required to separate format controls from expressions.
In the following example, the WRITE command advances the output by two lines and positions the first output character at the column location established by the input for the READ command.
   READ !,"Enter the number: ",num
   SET col=$X
   SET ans=num*num*num
   WRITE !!,"Its cube is: ",?col,ans
Thus, the output column varies depending on the number of characters input for the READ.
Escape Sequences with WRITE
The WRITE command, like the READ command, provides support for escape sequences. Escape sequences are typically used in format and control operations. Their interpretation is specific to the current device type.
To output an escape sequence, use the form:
   WRITE *27,"char"
where *27 is the ASCII code for the escape character, and char is a literal string consisting of one or more control characters. The enclosing double quotes are required.
For example, if the current device is a VT-100 compatible terminal, the following command erases all characters from the current cursor position to the end of the line.
   WRITE *27,"[2J"
To provide device independence for a program that can run on multiple platforms, use the SET command at the start of the program to assign the necessary escape sequences to variables. In your program code, you can then reference the variables instead of the actual escape sequences. To adapt the program for a different platform, simply make the necessary changes to the escape sequences defined with the SET command.
Device Controls
Caché supports the use of negative integer expressions as device controls. For example, in VMS, the following command rewinds and unloads the tape on the current magnetic tape device.
   WRITE *-13
The following sections describe these controls for terminal and magnetic tape devices.
Terminal Devices
Caché implementations support the *-1 control for terminal devices. This control clears the input buffer of any characters that have not been input by previous READ commands.
An input buffer holds characters as they arrive from the keyboard, even those the user types before the routine executes a READ command. In this way, the user can answer questions even before they appear on the screen. When the READ command takes characters from the buffer, Caché echoes them to the terminal so that questions and answers appear together. When a routine detects errors it may cancel these answers. For further details, see Terminal I/O in the Caché I/O Device Guide.
Magnetic Tape Devices
Caché platforms support a number of controls for magnetic tape devices. The following table lists these controls and their functions. For further details, see Magnetic Tape I/O in the Caché I/O Device Guide.
Code Function Effect
-1 Backspace Backspaces tape one block. (Not supported for cartridge tape.)
-2 Forward Space Advances tape one block (skipping labels) so that WRITE * 2 at the beginning of the tape (BOT) skips volume and header labels as well as the first data block. (Not supported for cartridge tape.)
-3 Write Tape Mark Writes a tape mark. If the buffer contains unwritten data, that data is written out first.
-4 Write Block Writes out the current buffer. If the format specifies labels and the tape is at BOT, header labels of the appropriate format are written before the data block.
-5 Rewind Rewinds the tape. Any unwritten data (in addition to trailer labels and tape marks required by the format) is written before rewinding occurs.
-6 Read Block Reads the next block. If the tape is at BOT, skips header labels before reading.
-7 Read Label Reads the next block whether or not it is a label. (Not supported for cartridge tape.)
-8 Write Header Label If the format specifies labels, writes header labels. If the tape is at BOT, writes a volume label before the header labels. (Not supported for cartridge tape.)
-9 Write EOF Label Writes any unwritten data. If the format specifies labels, writes the appropriate trailer label. Writes two tape marks and backspaces over the second. (Not supported for cartridge tape.)
-13 Rewind and Unload For OpenVMS only: performs all the function WRITE *-5, then unloads the tape. This control lets you create an output set that spans more than one tape volume.
When writing block-oriented data to magnetic tape, the $ZB special variable contains the number of bytes remaining in the I/O buffer. Refer to $ZB for further details.
See Also