%TITLE 'Verify and collect attributes for .STYLE <entity> commands'
MODULE STYLE (	IDENT = 'V04-000'
    		%BLISS32[, ADDRESSING_MODE( EXTERNAL    = LONG_RELATIVE
    					   ,NONEXTERNAL = LONG_RELATIVE)]
		) =
BEGIN
!
!****************************************************************************
!*									    *
!*  COPYRIGHT (c) 1978, 1980, 1982, 1984 BY				    *
!*  DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS.		    *
!*  ALL RIGHTS RESERVED.						    *
!* 									    *
!*  THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED   *
!*  ONLY IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE   *
!*  INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR  ANY  OTHER   *
!*  COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY   *
!*  OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE IS  HEREBY   *
!*  TRANSFERRED.							    *
!* 									    *
!*  THE INFORMATION IN THIS SOFTWARE IS  SUBJECT TO CHANGE WITHOUT NOTICE   *
!*  AND  SHOULD  NOT  BE  CONSTRUED AS  A COMMITMENT BY DIGITAL EQUIPMENT   *
!*  CORPORATION.							    *
!* 									    *
!*  DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE  OR  RELIABILITY OF ITS   *
!*  SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.		    *
!* 									    *
!*									    *
!****************************************************************************
!
!++
! FACILITY:	 DSR (Digital Standard RUNOFF) / DSRPLUS
!
! ABSTRACT: Processes the attributes of a .STYLE <entity> command.
!
! ENVIRONMENT: Transportable
!
! AUTHOR: Keith Dawson	CREATION DATE: April 1982
!

%SBTTL 'Revision History'
!
! MODIFIED BY:
!
!	011	REM00011	Ray Marshall	21-Jul-1983
!		The pass/return linkages for non-BLISS32 were incorrect.  They
!		  were made to match the way they are defined in ATTRIB.BLI.
!		There was also a missing comma in that same code (above) in the
!		  original that caused a compilation error on TOPS-20.  But,
!		  seeing as that code was replaced, it no longer matters.
!
!	010	KFA00010	Ken Alden	17-May-1983
!		Fixed testpage bug.
!
!	009	REM00009	Ray Marshall	07-Mar-1983
!		Global edit of all modules. Updated module names, idents,
!		copyright dates. Changed require files to BLISS library.
!
!--

%SBTTL 'Module Level Declarations'
!
! TABLE OF CONTENTS:
!
LINKAGE
%IF (%BLISS(BLISS32) OR %BLISS(BLISS16)) %THEN
    pass_1_return_1 = 
	CALL (REGISTER=1; REGISTER=2),
    pass_4_return_1 = 
	CALL (REGISTER=1, REGISTER=2, REGISTER=3, REGISTER=4; REGISTER=5),
    pass_2_return_2 = 
	CALL (REGISTER=1, REGISTER=2; REGISTER=3, REGISTER=4);
%ELSE 
    pass_1_return_1 = 
	PUSHJ (; REGISTER=2) : LINKAGE_REGS (15,13,1),
    pass_4_return_1 = 
	PUSHJ (; REGISTER=2) : LINKAGE_REGS (15,13,1),
    pass_2_return_2 = 
	PUSHJ (; REGISTER=2, REGISTER=3) : LINKAGE_REGS (15,13,1);
%FI

! INCLUDE FILES:
!

LIBRARY 'NXPORT:XPORT';			! XPORT Library
REQUIRE 'REQ:RNODEF';			! RUNOFF variant definitions

%IF DSRPLUS %THEN
LIBRARY 'REQ:DPLLIB';			! DSRPLUS BLISS Library
%ELSE
LIBRARY 'REQ:DSRLIB';			! DSR BLISS Library
%FI

FORWARD ROUTINE
    STYLE,			!Processes .STYLE { EXAMPLE | FIGURE | TABLE | HEADER } commands.
    SET_STHL      : NOVALUE	!Sets up ECC from .STHL command.
%IF DSRPLUS %THEN
			   ,
    SET_ONE_STYLE : NOVALUE,	!For one attribute, stores KWS information in the proper ECC.
    CHECK_HL_VALUES	   ,	!Range-checks supplied HL-level values.
    INIT_STYLE_KW : NOVALUE;	!Initializes the $KWS_BLOCKVECTOR for the STYLE <entity> commands.
%ELSE
			   ;
%FI

!
! MACROS:
!
! OWN STORAGE:
!

%IF DSRPLUS %THEN
OWN
    FIRST_TIME : INITIAL (1),	!Have we ever set up keywords?
    HLS_CHECKED,		!Have we checked HL-range validity during this call?
    KEYWORDS : $KWS_BLOCKVECTOR;
%FI

!
! EXTERNAL REFERENCES:
!

EXTERNAL
    ECC : $ECC_BLOCKVECTOR,
    FS01 : FIXED_STRING,
    HLC : HLC_DEFINITION,
    HLLIST : COUNTED_LIST,
    IRA : FIXED_STRING,
    KHAR;

EXTERNAL LITERAL				!Error messages
%IF DSRPLUS %THEN
    RNFTMA,		! too many attributes
%FI
    RNFILE;

EXTERNAL ROUTINE
%IF DSRPLUS %THEN
    ATTSYN : pass_1_return_1,	!Verifies syntax of attribute list.
    DOATTR : pass_4_return_1,	!Collects one attribute and sets its value.
    ENDCMT,
    SKPSEP,
%FI
    ECCINI,
    ERMS,
    STHL;

%sbttl 'STYLE -- process all attributes for .STYLE <entity> command'
GLOBAL ROUTINE STYLE (HANDLER) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	STYLE verifies the .STYLE <entity> attributes given by the user.
!	It writes descriptions of the verified attributes into the ECC 
!	global area.
!
!	AFTER[=n]	leave n blank lines after each caption.
!	ALLCAP		make caption all-caps.
!	BEFORE[=n]	leave n blank lines before each caption.
!	BETWEEN[=n]	leave n blank lines between 'CHAPTER' or 'APPENDIX' & caption.
!	BOLD 		make entity caption bold.
!	BREAK		start a new line between the counter and caption.
!	CENTER		center entity caption (and don't run in).
!	DEFAULTS	return all values to initial defaults.
!	FIRSTCAP	make entity caption initial-caps.
!	LEAVECASE	do not change case of entity caption.
!	LEFT		make the counter and caption left-justified.
!	LEVEL=n		(.STHL only) command applies to HL n.
!	NORUNIN		do not run in caption with text.
!	NOBOLD		do not make entity caption bold.
!	NOBREAK		do not start a new line after the counter.
!	NOPAGE		do not start a new page before a CHAPTER, etc.
!	NOTOCPAGE	do not insert a page number in the TOC.
!	NOSTARTODD	do not force the first page of a chapter on an odd page. 
!	NOUNDERLINE	do not underline this entity caption.
!	NUMBERED	display counter for this entity.
!	PAGE		start a new page before CHAPTER or APPENDIX.
!	RUNIN		run in caption with text (and don't center).
!	SPACES[=n]	leave n spaces between counter and caption.
!	STARTODD	force the first page of a chapter to start on an odd page.
!	TESTPAGE[=n]	issue implicit test-page n.
!	TOCPAGE	insert a page number in the TOC.
!	UNDERLINE 	make entity caption underlined.
!	UNNUMBERED	do not display counter for this entity.
!
! FORMAL PARAMETERS:
!
!	HANDLER		specifies which command is being processed:
!			.STYLE EXAMPLE, .STYLE FIGURE, .STYLE TABLE,
!			.STYLE APPENDIX, .STYLE CHAPTER or .STYLE HEADERS.
!
! IMPLICIT INPUTS:	None
!
! IMPLICIT OUTPUTS:
!
!	The routine updates the ECC block corresponding to the handler code.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	The routine returns 0 for normal completion. It returns -1 if 
!	the user-supplied attributes cannot be deciphered (mismatched 
!	delimiters).
!
! SIDE EFFECTS:		None
!--

    BEGIN

%IF DSRPLUS %THEN
    STACKLOCAL
	first_keyword,		!First legal keyword in the tables for this command.
	last_keyword,		!Last legal keyword for this command.
	number_of_keywords,	!How many keywords are legal for this command.
	kw_offset,		!Offset into the KEYWORDS tables, pointing to the first 
				! legal keyword for this command.
	end_delimiter,		!The matching ) ] > }.
	match,			!Index of which keyword was found, from DOATTR.
	ecc_offset,		!Offset into the ECC block, pointing to data for this entity.
	old_syntax_sthl,	!True if command is an .STHL in the old, 9-number syntax.
	result,			!Completion code from ATTSYN and DOATTR.
	start_where;		!Assures that giving no attributes re-establishes defaults.

!+
! Initialize 
!-
    init_style_kw (.handler);	!Set up KWS structure for this STYLE command.

    hls_checked = 0;		!Indicate that we have not checked a HL-range yet.

    end_delimiter = %C')';	!Preset the terminator character.

    SELECT .handler OF 
	SET

	[h_style_appendi, h_style_chapter] :
	   	BEGIN
	    	first_keyword = kws$k_first_chapp;
		last_keyword = kws$k_last_chapp;	   
	    	END;			

	[h_style_appendi] :     ecc_offset = append_offset;

	[h_style_chapter] :	ecc_offset = chap_offset;

	[h_style_example, h_style_figure, h_style_table] :
		BEGIN
		first_keyword = kws$k_first_entity;
		last_keyword = kws$k_last_entity;
		END;

	[h_style_example] :	ecc_offset = examp_offset;

	[h_style_figure] :	ecc_offset = figur_offset;

	[h_style_table] :	ecc_offset = table_offset;

	[h_style_headers] :
		!
		BEGIN
		ecc_offset = hcoll_offset;
		first_keyword = kws$k_first_header;
		last_keyword = kws$k_last_header;
		!
%FI
		!Initialize the ECC collecting area for .STYLE HEADERS commands.
		eccini (hcoll_offset, hcoll_offset, false);

%IF DSRPLUS %THEN
		END;
	TES;
%FI

%IF NOT DSRPLUS %THEN
!+
! This command must be .STYLE HEADERS (the only legal .STYLE command 
! handled by this module for DSR). It is an old-syntax .STHL, with up 
! to 9 numeric arguments.
!-
    IF .handler EQL h_style_headers	!Defensive check.
    THEN
	BEGIN
	sthl (.handler);		!Process the .STHL in the old way.
	set_sthl (ecc, 1, 6, true);
	RETURN 0;
	END
    ELSE
	erms (rnfile, CH$PTR(UPLIT('STYLE1')), 6);
%FI

%IF DSRPLUS %THEN
    !
    ! Set the number of keywords legal for this command.
    number_of_keywords = .last_keyword - .first_keyword + 1;
    !
    ! Assume that any .STHL command will be in the new, keyworded format.
    old_syntax_sthl = false;
    !
    ! Preset starting point for attribute search.
    start_where = .first_keyword;
    !
    ! Preset the offset into the keyword tables that applies for this command.
    ! This allows DOATTR not to have to know the structure of the keyword tables.
    kw_offset = .first_keyword * (kws$k_length * %UPVAL);

!+
! Verify the syntax of the attribute-list.
!-
    result = attsyn (.handler; end_delimiter);

    CASE .result FROM min_attcc TO max_attcc OF
	SET

	[attcc_ok] : 0;

	[attcc_dcf_error] : 
	    !
	    BEGIN
	    endcmt ();			!Skip rest of text in the input.
	    RETURN -1;
	    END;	

	[attcc_mmd_error] : 
	    !
	    BEGIN
	    endcmt ();			!Skip rest of text in the input.
	    RETURN -1;
	    END;

	[attcc_leading_number] :	!Old-syntax .STHL was given.
	    !
	    IF .handler EQL h_style_headers	!Defensive check -- ATTRIB is supposed
	    THEN				!to return this code only for .STHL commands.
		BEGIN
		sthl (.handler);		!Process the .STHL in the old way.
		old_syntax_sthl = true;
		start_where = max_keywords + 1;
		END
	    ELSE
		erms (rnfile, CH$PTR(UPLIT('STYLE1')), 6);

	[attcc_none] :			!No attributes were supplied. 
	    !
	    !Do not try to get any keywords; act as if user had given DEFAULTS keyword.
	    start_where = max_keywords + 1;

	[INRANGE, OUTRANGE] : erms (rnfile, CH$PTR(UPLIT('STYLE2')), 6);

	TES;
!+
! Collect one or more attributes.
!-
    INCR K FROM .START_WHERE TO .LAST_KEYWORD DO
	BEGIN
	MATCH = -1;		!Assume we will not find the keyword.
	!
	RESULT = DOATTR (.HANDLER, .END_DELIMITER, (KEYWORDS + .KW_OFFSET), 
			 .NUMBER_OF_KEYWORDS; MATCH);
	!
	CASE .RESULT FROM MIN_ATTCC TO MAX_ATTCC OF
	    SET

	    !We take no action for the following errors; they were already
	    !reported by DOATTR.
	    !
	    [ATTCC_AMA_ERROR, ATTCC_IKW_ERROR] : 0;
	    [ATTCC_NNA_ERROR, ATTCC_MQS_ERROR] : 0;

	    [ATTCC_OK, ATTCC_NVS_ERROR] :
		!
		!It's ok not to specify a value; the effect is to invoke the default value.
		SET_ONE_STYLE (.ECC_OFFSET, ECC [.ECC_OFFSET, 0,0,0,0], (.MATCH + .FIRST_KEYWORD) );

	    [ATTCC_NONE] : EXITLOOP;	!End of attribute list detected.

	    [INRANGE, OUTRANGE] : ERMS (RNFILE, CH$PTR(UPLIT('STYLE2')), 6);

	    TES;
	!
	END;				! End of processing for 1 attribute.
!+
! Process defaulted arguments of extra keywords (unless the user issued
! an old-syntax .STHL command).
!-
    IF NOT .old_syntax_sthl  THEN
	BEGIN
	!
	! If the user specified no attributes, act as if DEFAULT has been specified.
	!
	IF .START_WHERE NEQ .FIRST_KEYWORD  THEN
	    !User supplied no attributes. Act as if he gave the DEFAULTS keyword.
	    SET_ONE_STYLE (.ECC_OFFSET, ECC [.ECC_OFFSET, 0,0,0,0], KWS$K_DEFAULTS)
	ELSE
	    !User supplied some attributes; we should have processed all of them 
	    !by now. If any remain, skip over them and note the error.
	    BEGIN
	    IF .KHAR NEQ .END_DELIMITER  THEN
		BEGIN
		FS_INIT (FS01);
		WHILE .KHAR NEQ .END_DELIMITER DO
		    BEGIN
		    KCNS ();
		    FS_WCHAR (FS01, .KHAR);
		    END;
		!
		!'Too many attributes; "..." ignored'. The "-1" assures that the
		!end-delimiter is not included in the error message.
		ERMS (RNFTMA, .FS_START (FS01), .FS_LENGTH (FS01) - 1);
		END
	    ELSE
		!End of string; get the terminator and position past the 
		!attributes string.
		BEGIN
		KCNS ();
		SKPSEP (IRA);
		END;
	    END;
	END;
!+
! An .STHL command gets processed through its own action routine.
!-
    !
    IF .handler EQL h_style_headers  THEN
	BEGIN
	LOCAL
	    first, last;
	!
	! The ARG_LENGTH value is used to store the second number of a range.
	! If no range was given, this value is zero.
	!
	IF .keywords [kws$k_level,kws$h_arg_length] EQL 0  THEN
	    first = (last = .keywords [kws$k_level,kws$h_arg_value])
	ELSE
	    ! User did supply a range.
	    BEGIN
	    first = .keywords [kws$k_level,kws$h_arg_value];
	    last = .keywords [kws$k_level,kws$h_arg_length];
	    END;
    !+
    ! Check the order of FIRST and LAST, flipping if necessary; range-check 
    ! the numbers. The routine returns FALSE if either number is out of 
    ! range; in this case no STHL values are set.
    !_
	IF check_hl_values (first, last)  THEN
	    set_sthl (ecc, .first, .last, .old_syntax_sthl);
    !+
    ! The value(s) given by the user are OK. Perform the style change.
    !-
	END;
%FI
    RETURN 0;

    END;					!End of STYLE
%IF DSRPLUS %THEN

%SBTTL 'SET_ONE_STYLE -- set ECC information for one valid attribute'
ROUTINE SET_ONE_STYLE (OFFSET, STYLE_BLOCK, MATCH) : NOVALUE =
!++
!
! FUNCTIONAL DESCRIPTION:
!
!	SET_ONE_STYLE	is the action routine for attributes. It is called, 
!			when a legal attribute is processed, to set the proper
!			ECC values.
!
! FORMAL PARAMETERS:
!
!	OFFSET		indicates which command is being processed: it is the 
!			offset into the ECC blockvector pointing to the command.
!
!	STYLE_BLOCK	is the address of the $ECC_BLOCK to update.
!
!	MATCH		is the index into the $KWS_BLOCK that corresponds 
!			to the attribute we are processing.
!
! IMPLICIT INPUTS:	None
!
! IMPLICIT OUTPUTS:
!
!	One piece of ECC information is updated.
!
! ROUTINE VALUE:
! COMPLETION CODES:	None
!
! SIDE EFFECTS:		None
!--
    BEGIN

    BIND KW = KEYWORDS [.MATCH, 0,0,0,0] : $KWS_BLOCK;

    BIND SB = .STYLE_BLOCK : $ECC_BLOCK;

    LOCAL
	NUMBER,
	SIGN;

    NUMBER = .KW [KWS$H_ARG_VALUE];
    SIGN = .KW [KWS$H_ARG_SIGN];

!+
! We have a legal attribute. Set information in the ECC structure.
!-
    SELECT .MATCH OF
	SET

	[KWS$K_AFTER] : 
		!
		BEGIN
		LOCAL
		    res_number;

		res_number =
		    (IF   .sign EQL 0  THEN   .number
		     ELSE   .sb [ecc$h_after] + .number );

		IF .RES_NUMBER LSS 0  THEN
		    RES_NUMBER = 0;

		SB [ECC$H_AFTER] = .RES_NUMBER;
		END;

	[KWS$K_ALLCAP] : SB [ECC$H_CASE] = ECC$K_ALLCAP;

	[KWS$K_BEFORE] : 
		!
		BEGIN
		LOCAL
		    RES_NUMBER;

		RES_NUMBER =
		    (IF .SIGN EQL 0 THEN .NUMBER
		     ELSE .SB [ECC$H_BEFORE] + .NUMBER);

		IF .RES_NUMBER LSS 0  THEN
		    RES_NUMBER = 0;

		SB [ECC$H_BEFORE] = .RES_NUMBER;
		END;

	[KWS$K_BETWEEN] : 
		!
		BEGIN
		LOCAL
		    RES_NUMBER;

		RES_NUMBER =
		    (IF .SIGN EQL 0 THEN .NUMBER
		     ELSE .SB [ECC$H_BETWEEN] + .NUMBER);

		IF  .RES_NUMBER LSS 0  THEN
		    RES_NUMBER = 0;

		SB [ECC$H_BETWEEN] = .RES_NUMBER;
		IF  .RES_NUMBER GTR 0  THEN
		    SB [ECC$V_BREAK] = TRUE;
		END;

	[KWS$K_BOLD] : SB [ECC$V_BOLD] = TRUE;

	[KWS$K_BREAK] : 
		!
		BEGIN
		SB [ECC$V_BREAK] = TRUE;
		SB [ECC$H_RUNIN] = 0;
		END;

	[KWS$K_CENTER] : 
		!
		BEGIN		
		SB [ECC$H_POSITION] = ECC$K_CENTER;
		SB [ECC$H_RUNIN] = 0;
		END;

	[KWS$K_DEFAULTS] :
		!
		IF  .OFFSET NEQ HCOLL_OFFSET  THEN	! Initialize style info.
		    ECCINI (.OFFSET, .OFFSET, FALSE)	! for one <entity>.
		ELSE
		    BEGIN				!Initialize style information for 
		    LOCAL				! one or a range of header-levels.
			FIRST, LAST;
		    !
		    ! The ARG_LENGTH value is used to store the second number of a range.
		    ! If no range was given, this value is zero.
		    !
		    IF .KEYWORDS [KWS$K_LEVEL,KWS$H_ARG_LENGTH] EQL 0  THEN
			FIRST = (LAST = .KEYWORDS [KWS$K_LEVEL,KWS$H_ARG_VALUE])
		    ELSE
			! User did supply a range.
			BEGIN
			FIRST = .KEYWORDS [KWS$K_LEVEL, KWS$H_ARG_VALUE];
			LAST = .KEYWORDS [KWS$K_LEVEL, KWS$H_ARG_LENGTH];
			END;
		    !
		    ! Range-check the HL values.
		    IF  CHECK_HL_VALUES (FIRST, LAST)  THEN
			BEGIN
			FIRST = .FIRST + HCOLL_OFFSET;
			LAST = .LAST + HCOLL_OFFSET;
			ECCINI (.FIRST, .LAST, FALSE);
			END;
		    END;

	[KWS$K_FIRSTCAP] : SB [ECC$H_CASE] = ECC$K_FIRSTCAP;

	[KWS$K_LEAVECASE] : SB [ECC$H_CASE] = ECC$K_LEAVECASE;

	[KWS$K_LEFT]	: SB [ECC$H_POSITION] = ECC$K_LEFT;
	
	[KWS$K_NOBOLD] 	: SB [ECC$V_BOLD] = FALSE;

	[KWS$K_NOBREAK]	: SB [ECC$V_BREAK] = FALSE;
	
	[KWS$K_NOPAGE]	:
		!
		BEGIN
		SB [ECC$V_PAGE] = FALSE;
		SB [ECC$V_STARTODD] = FALSE;
		END;

	[KWS$K_NOTOCPAGE] : SB [ECC$V_TOCPAGE] = FALSE;

	[KWS$K_NOUNDERLINE] : SB [ECC$V_UNDERLINE] = FALSE;

	[KWS$K_NORUNIN] : SB [ECC$H_RUNIN] = 0;

	[KWS$K_NOSTARTODD] : SB [ECC$V_STARTODD] = FALSE;

	[KWS$K_NUMBERED] : SB [ECC$V_UNNUMBERED] = FALSE;

	[KWS$K_PAGE]	: SB [ECC$V_PAGE] = TRUE;

	[KWS$K_RIGHT] : 
		!
		BEGIN		
		SB [ECC$H_POSITION] = ECC$K_RIGHT;
		SB [ECC$H_RUNIN] = 0;
		END;

	[KWS$K_RUNIN] :
		!
		BEGIN		
		SB [ECC$H_RUNIN] = 1;
		SB [ECC$H_POSITION] = ECC$K_LEFT;
		END;

	[KWS$K_SPACES] : 
		!
		BEGIN
		LOCAL
		    RES_NUMBER;

		RES_NUMBER =
		    (IF .SIGN EQL 0 THEN .NUMBER
		     ELSE .SB [ECC$H_SPACES] + .NUMBER);

		IF  .RES_NUMBER LSS 0  THEN
		    RES_NUMBER = 0;

		SB [ECC$H_SPACES] = .RES_NUMBER;
		END;

	[KWS$K_STARTODD] :
		!
		BEGIN
		SB [ECC$V_STARTODD] = TRUE;
		SB [ECC$V_PAGE] = TRUE;
		END;

	[KWS$K_TESTPAGE] : 
		!
		BEGIN
		LOCAL
		    RES_NUMBER;
		!If this is for a chapter-like header, NOPAGE must be in effect.
		IF (.offset NEQ chap_offset)	OR 
    		   (.offset NEQ append_offset)	OR
		   (.OFFSET GEQ CHAP_OFFSET AND  .SB [ECC$V_PAGE] = FALSE) 
 		THEN 
		   BEGIN		
		   RES_NUMBER =
		       (IF .SIGN EQL 0 THEN .NUMBER
		        ELSE .SB [ECC$H_TESTPAGE] + .NUMBER);

		   IF  .RES_NUMBER LSS 0  THEN
		       RES_NUMBER = 0;

		   SB [ECC$H_TESTPAGE] = .RES_NUMBER;
		   END;
		END;

	[KWS$K_TOCPAGE] : SB [ECC$V_TOCPAGE] = TRUE;

	[KWS$K_UNDERLINE] : SB [ECC$V_UNDERLINE] = TRUE;

	[KWS$K_UNNUMBERED] : SB [ECC$V_UNNUMBERED] = TRUE;

	[KWS$K_LEVEL] : 0;	!Nothing to do; the value already resides 
				!in the KWS, from which it will be picked
				!up by SET_STHL.

	[OTHERWISE] : ERMS (RNFILE, CH$PTR(UPLIT('SET_ONE_STYLE')), 13);

	TES;

    END;					! End of SET_ONE_STYLE
%FI

%SBTTL 'SET_STHL -- Set up ECC from one .STYLE HEADERS command'
ROUTINE SET_STHL (STYLE_BLOCK, FIRST_HL, LAST_HL, OLD_SYNTAX) : NOVALUE =
!++
!
! FUNCTIONAL DESCRIPTION:
!
!	SET_STHL	moves the collected .STYLE HEADER information from its
!			collecting place to the appropriate level of the ECC.
!			This is done in one of two ways:
!
!			1) For a new-syntax, keyworded .STHL, information is moved
!			   from ECC [HCOLL_OFFSET] to the proper level in the ECC.
!
!			2) For an old-syntax, numbered .STHL, information is picked
!			   up from the HLC structure and moved into the ECC.
!
! FORMAL PARAMETERS:
!
!	STYLE_BLOCK	is the address of the $ECC_BLOCK to update.
!
!	FIRST_HL	is the number of the first level of header to update (from 1 to 6).
!
!	LAST_HL		is the number of the last level to update (from .FIRST_HL to 6).
!
!	OLD_SYNTAX	is TRUE if the .STHL command was in the old, numbered syntax.
!
! IMPLICIT INPUTS:	None
!
! IMPLICIT OUTPUTS:
!
!	One or more ECC fields are updated (new-syntax .STHL), or the entire
!	header portion of the ECC_BLOCKVECTOR -- 6 $ECC_BLOCKs -- is replaced.
!
! ROUTINE VALUE:
! COMPLETION CODES:	None
!
! SIDE EFFECTS:		None
!--

    BEGIN

    MAP
	STYLE_BLOCK : REF $ECC_BLOCKVECTOR;

    BIND
	COL_BL	= STYLE_BLOCK [HCOLL_OFFSET, 0,0,0,0]
		: $ECC_BLOCK,		!Keyword information has been collected here.

	OLD_BV	= STYLE_BLOCK [HCOLL_OFFSET, 0,0,0,0]
		: $ECC_BLOCKVECTOR;	!Overwrite here, if an old-syntax .STHL.

    MACRO
	move_bit (offset) =
	    NEW_BL [offset] = (.NEW_BL [offset] OR .COL_BL [offset]) %,

	move_numeric (offset) =
	    IF .COL_BL [offset] NEQ -1  THEN
		NEW_BL [offset] = .COL_BL [offset] %;


    IF NOT .OLD_SYNTAX  THEN
!+
! The user issued a new-syntax, keyworded .STHL command. We have collected 
! information from his keywords in the HCOLL_OFFSET of the ECC. Now move the 
! collected information into the target ECC area.
!-
	INCR I FROM .FIRST_HL TO .LAST_HL DO
	    !
	    BEGIN
	    !Transfer collected keyword information to here.
	    BIND NEW_BL	= 
		STYLE_BLOCK [HCOLL_OFFSET + .I, 0,0,0,0] : $ECC_BLOCK;
	!+
	! First move the bit information.
	!-
	    MOVE_BIT (ECC$V_BOLD);
	    MOVE_BIT (ECC$V_UNDERLINE);
	    MOVE_BIT (ECC$V_UNNUMBERED);
	    MOVE_BIT (ECC$V_BREAK);
	    MOVE_BIT (ECC$V_PAGE);
	    MOVE_BIT (ECC$V_TOCPAGE);
	    MOVE_BIT (ECC$V_STARTODD);
	!+
	! Now move the numeric-value information.
	!-
	    MOVE_NUMERIC (ECC$H_RUNIN);
	    MOVE_NUMERIC (ECC$H_CASE);
	    MOVE_NUMERIC (ECC$H_POSITION);
	    MOVE_NUMERIC (ECC$H_AFTER);
	    MOVE_NUMERIC (ECC$H_BEFORE);
	    MOVE_NUMERIC (ECC$H_BETWEEN);
	    MOVE_NUMERIC (ECC$H_SPACES);
	    MOVE_NUMERIC (ECC$H_TESTPAGE);
	    END
    ELSE
!+
! The user gave an old-syntax, numbered .STHL command. Overwrite the entire
! ECC header area -- all 6 levels -- with the results of that old .STHL.
! Note that this means the user loses the benefit of some of the advanced-
! syntax, keyword features: bolding and underlining, for example, are undone.
!-
	INCR I FROM 1 TO 6 DO
	    BEGIN

	    OLD_BV [.I, ECC$V_BOLD] = FALSE;
	    OLD_BV [.I, ECC$V_UNDERLINE] = FALSE;
	    OLD_BV [.I, ECC$V_UNNUMBERED] = (.I GEQ .HLC_NO_NUMBER);

	    OLD_BV [.I, ECC$H_RUNIN] = (.I GEQ .HLC_RUNON);

	    OLD_BV [.I, ECC$H_CASE] =
		(IF  .I LEQ .HLC_UPPER  THEN 
		    ECC$K_ALLCAP
		 ELSE
		    IF  .I LEQ .HLC_CAP  THEN
			ECC$K_FIRSTCAP
		    ELSE
			ECC$K_LEAVECASE);

	    OLD_BV [.I, ECC$H_POSITION] =
		(IF .I GEQ .HLC_CENTER  THEN
		    ECC$K_CENTER
		 ELSE
		    ECC$K_LEFT);

	    OLD_BV [.I, ECC$H_AFTER] = .HLC_HEADLC;
	    OLD_BV [.I, ECC$H_BEFORE] = .HLC_HEADLB;
	    OLD_BV [.I, ECC$H_SPACES] = .HLC_HEADSP;
	    OLD_BV [.I, ECC$H_TESTPAGE] = .HLC_HEADLT;

	    END;

    END;					! End of SET_STHL
%IF DSRPLUS %THEN

%SBTTL 'CHECK_HL_VALUES -- verify order and range of HL-level values'
ROUTINE CHECK_HL_VALUES (FIRST_HL, LAST_HL) =
!++
!
! FUNCTIONAL DESCRIPTION:
!
!	CHECK_HL_VALUES	Makes sure two supplied HL-level numbers are in 
!	ascending order, and range-checks them to make sure they are in the 
!	range from 1 to 6.
!
! FORMAL PARAMETERS:
!
!	FIRST_HL, LAST_HL are the addresses of the two values to check.
!
! IMPLICIT INPUTS:	None
!
! IMPLICIT OUTPUTS:
!
!	If the two values were not in ascending order, they are reversed 
!	and the new, properly ordered values are "pushed back" through the 
!	routine formals.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	The routine returns TRUE if the two values were in range, and FALSE 
!	otherwise.
!
! SIDE EFFECTS:		None
!--
    BEGIN

    EXTERNAL ROUTINE
	CONVBB;

    EXTERNAL LITERAL			!Error messages
	RNFINM,
	RNFNNA;

    LOCAL
	SWITCH,
	DIGITS : VECTOR [10],
	LEN;

    OWN
	FS_ALLOCATE (STRING, 5);

    BIND
	FIR = .FIRST_HL,
	LAS = .LAST_HL;

    !+
    ! If this subroutine has been called yet during this invocation of STYLE, 
    ! then there is nothing more to check.
    !-
    IF .HLS_CHECKED EQL -1  THEN	! Have we checked already, and failed?
	RETURN FALSE
    ELSE
	IF .HLS_CHECKED EQL 1  THEN	!If not, have we checked and all was ok?
	    RETURN TRUE
	ELSE
	    HLS_CHECKED = 1;	!Haven't yet checked. Indicate that now we have.

    FS_INIT (STRING);

    !+
    ! Switch the two numbers if they are not monotone increasing.
    !-
    IF .FIR GTR .LAS  THEN
	    BEGIN		! User gave a range like "LEVEL=3:1" -- which 
	    SWITCH = .LAS;	! is legal -- so rationalize it.
	    LAS = .FIR;
	    FIR = .SWITCH;
	    END;
    !+
    ! Range-check the supplied level-number(s).
    !-
    SELECT TRUE OF
	SET

	[.FIR EQL 0] :
	    !
	    ERMS (RNFINM, CH$PTR (UPLIT('0')), 1);	!'Illegal number value'

	[.LAS EQL 0] :
	    !
	    ERMS (RNFINM, CH$PTR (UPLIT('0')), 1);	!'Illegal number value'

	[.FIR LSS 0] :
	    !
	    BEGIN
	    CONVBB (.FIR, DIGITS, LEN, 10);
	    FS_WCHAR (STRING, %C'-');
	    DECR I FROM (MIN (5, .LEN)) TO 1 DO
		FS_WCHAR (STRING, CH$PTR(.DIGITS[.I-1]));
	    ERMS (RNFNNA, .FS_START (STRING), .FS_LENGTH (STRING));	!'Negative number not allowed'
	    FS_INIT (STRING);
	    END;

	[.LAS LSS 0] :
	    !
	    BEGIN
	    CONVBB (.LAS, DIGITS, LEN, 10);
	    FS_WCHAR (STRING, %C'-');
	    DECR I FROM (MIN (5, .LEN)) TO 1 DO
		FS_WCHAR (STRING, CH$PTR(.DIGITS[.I-1]));
	    ERMS (RNFNNA, .FS_START (STRING), .FS_LENGTH (STRING));	!'Negative number not allowed'
	    FS_INIT (STRING);
	    END;

	[.FIR GTR 6] :
	    !
	    BEGIN
	    CONVBB (.FIR, DIGITS, LEN, 10);
	    DECR I FROM (MIN (5, .LEN)) TO 1 DO
		FS_WCHAR (STRING, CH$PTR(.DIGITS[.I-1]));
	    ERMS (RNFINM, .FS_START (STRING), .FS_LENGTH (STRING));	!'Illegal number value'
	    FS_INIT (STRING);
	    END;

	[.LAS GTR 6] :
	    !
	    BEGIN
	    CONVBB (.LAS, DIGITS, LEN, 10);
	    DECR I FROM (MIN (5, .LEN)) TO 1 DO
		FS_WCHAR (STRING, CH$PTR(.DIGITS[.I-1]));
	    ERMS (RNFINM, .FS_START (STRING), .FS_LENGTH (STRING));	!'Illegal number value'
	    FS_INIT (STRING);
	    END;

	[(.FIR LEQ 0) OR (.LAS GTR 6)] :
	    !
	    BEGIN
	    HLS_CHECKED = -1;
	    RETURN FALSE;
	    END;

	[OTHERWISE] :
	    !
	    RETURN TRUE;

	TES;

    TRUE
    END;					!End of CHECK_HL_VALUES

%SBTTL 'INIT_STYLE_KW -- Initialize $KWS_BLOCKVECTOR for STYLE commands'
ROUTINE INIT_STYLE_KW (HANDLER) : NOVALUE =
!++
!
! FUNCTIONAL DESCRIPTION:
!
!	INIT_STYLE_KW	initializes the $KWS_BLOCKVECTOR for STYLE commands.
!
! FORMAL PARAMETERS:
!
!	HANDLER		tells which command is being processed.
!
! IMPLICIT INPUTS:
!
!	The module-level OWN variable FIRST_TIME controls whether the keyword 
!	data is initialized.
!
! IMPLICIT OUTPUTS:
!
!	The module-level OWN variable KEYWORDS is initialized to represent 
!	the legal keywords for this .STYLE command.
!
! ROUTINE VALUE:
! COMPLETION CODES:	None
!
! SIDE EFFECTS:		None
!--
    BEGIN

    INCR I FROM 0 TO COUNT_STYL_KEYWORDS - 1 DO
	BEGIN
	KEYWORDS [.I, KWS$H_ARG_VALUE] = 0;
	KEYWORDS [.I, KWS$H_ARG_SIGN] = 0;
	KEYWORDS [.I, KWS$A_ARG_POINTER] = 0;
	KEYWORDS [.I, KWS$H_ARG_LENGTH] = 0;
	END;

!+
!  Set up default values for those keywords that take numeric parameters.
! This lets us reestablish the default if the user does not give a value.
!-
    KEYWORDS [KWS$K_AFTER, KWS$H_ARG_VALUE] = 
	(IF  .HANDLER EQL (H_STYLE_CHAPTER OR H_STYLE_APPENDI)
	     THEN 3
	     ELSE 1 );

    KEYWORDS [KWS$K_BEFORE, KWS$H_ARG_VALUE] = 
	(IF .HANDLER EQL H_STYLE_HEADERS 
	     THEN 2
	     ELSE 
	        IF .HANDLER EQL (H_STYLE_CHAPTER OR H_STYLE_APPENDI)
	 	    THEN 12
	 	    ELSE 1);

    KEYWORDS [KWS$K_SPACES, KWS$H_ARG_VALUE] = 2;

    KEYWORDS [KWS$K_BETWEEN, KWS$H_ARG_VALUE] = 1;

    KEYWORDS [KWS$K_LEVEL, KWS$H_ARG_VALUE] = .HLLIST [CL_INDEX];

    !
    ! The module-level OWN variable FIRST_TIME is initialized to 1 in its
    ! declaration; therefore, the first time this routine is called, the 
    ! keyword pointers and lengths are set up. On all subsequent calls, 
    ! only the keyword-value fields are initialized.
    !
    IF  .FIRST_TIME EQL 1  THEN
	FIRST_TIME = -1
    ELSE
	RETURN;

!+
! One-time-only initialization follows.
!-
    ! AFTER keyword
    KEYWORDS [KWS$K_AFTER, KWS$A_KW_POINTER] = CH$PTR(UPLIT('AFTER'));
    KEYWORDS [KWS$K_AFTER, KWS$H_KW_LENGTH] = 5;
    KEYWORDS [KWS$K_AFTER, KWS$H_ARG_TYPE] = KWS$K_NUMBER_OPTIONAL;
    !
    ! ALLCAP keyword
    KEYWORDS [KWS$K_ALLCAP, KWS$A_KW_POINTER] = CH$PTR(UPLIT('ALLCAP'));
    KEYWORDS [KWS$K_ALLCAP, KWS$H_KW_LENGTH] = 6;
    KEYWORDS [KWS$K_ALLCAP, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! BEFORE keyword
    KEYWORDS [KWS$K_BEFORE, KWS$A_KW_POINTER] = CH$PTR(UPLIT('BEFORE'));
    KEYWORDS [KWS$K_BEFORE, KWS$H_KW_LENGTH] = 6;
    KEYWORDS [KWS$K_BEFORE, KWS$H_ARG_TYPE] = KWS$K_NUMBER_OPTIONAL;
    !
    ! BETWEEN keyword
    KEYWORDS [KWS$K_BETWEEN, KWS$A_KW_POINTER] = CH$PTR(UPLIT('BETWEEN'));
    KEYWORDS [KWS$K_BETWEEN, KWS$H_KW_LENGTH] = 7;
    KEYWORDS [KWS$K_BETWEEN, KWS$H_ARG_TYPE] = KWS$K_NUMBER_OPTIONAL;
    !
    ! BOLD keyword
    KEYWORDS [KWS$K_BOLD, KWS$A_KW_POINTER] = CH$PTR(UPLIT('BOLD'));
    KEYWORDS [KWS$K_BOLD, KWS$H_KW_LENGTH] = 4;
    KEYWORDS [KWS$K_BOLD, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! BREAK keyword
    KEYWORDS [KWS$K_BREAK, KWS$A_KW_POINTER] = CH$PTR(UPLIT('BREAK'));
    KEYWORDS [KWS$K_BREAK, KWS$H_KW_LENGTH] = 5;
    KEYWORDS [KWS$K_BREAK, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! CENTER keyword
    KEYWORDS [KWS$K_CENTER, KWS$A_KW_POINTER] = CH$PTR(UPLIT('CENTER'));
    KEYWORDS [KWS$K_CENTER, KWS$H_KW_LENGTH] = 6;
    KEYWORDS [KWS$K_CENTER, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! DEFAULTS keyword
    KEYWORDS [KWS$K_DEFAULTS, KWS$A_KW_POINTER] = CH$PTR(UPLIT('DEFAULTS'));
    KEYWORDS [KWS$K_DEFAULTS, KWS$H_KW_LENGTH] = 8;
    KEYWORDS [KWS$K_DEFAULTS, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! FIRSTCAP keyword
    KEYWORDS [KWS$K_FIRSTCAP, KWS$A_KW_POINTER] = CH$PTR(UPLIT('FIRSTCAP'));
    KEYWORDS [KWS$K_FIRSTCAP, KWS$H_KW_LENGTH] = 8;
    KEYWORDS [KWS$K_FIRSTCAP, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! LEAVECASE keyword
    KEYWORDS [KWS$K_LEAVECASE, KWS$A_KW_POINTER] = CH$PTR(UPLIT('LEAVECASE'));
    KEYWORDS [KWS$K_LEAVECASE, KWS$H_KW_LENGTH] = 9;
    KEYWORDS [KWS$K_LEAVECASE, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! LEFT keyword
    KEYWORDS [KWS$K_LEFT, KWS$A_KW_POINTER] = CH$PTR(UPLIT('LEFT'));
    KEYWORDS [KWS$K_LEFT, KWS$H_KW_LENGTH] = 4;
    KEYWORDS [KWS$K_LEFT, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! LEVEL keyword
    KEYWORDS [KWS$K_LEVEL, KWS$A_KW_POINTER] = CH$PTR(UPLIT('LEVEL'));
    KEYWORDS [KWS$K_LEVEL, KWS$H_KW_LENGTH] = 5;
    KEYWORDS [KWS$K_LEVEL, KWS$H_ARG_TYPE] = KWS$K_RANGE_OF_NUMBERS;
    !
    ! NOBOLD keyword
    KEYWORDS [KWS$K_NOBOLD, KWS$A_KW_POINTER] = CH$PTR(UPLIT('NOBOLD'));
    KEYWORDS [KWS$K_NOBOLD, KWS$H_KW_LENGTH] = 6;
    KEYWORDS [KWS$K_NOBOLD, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! NOBREAK keyword
    KEYWORDS [KWS$K_NOBREAK, KWS$A_KW_POINTER] = CH$PTR(UPLIT('NOBREAK'));
    KEYWORDS [KWS$K_NOBREAK, KWS$H_KW_LENGTH] = 7;
    KEYWORDS [KWS$K_NOBREAK, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! NOPAGE keyword
    KEYWORDS [KWS$K_NOPAGE, KWS$A_KW_POINTER] = CH$PTR(UPLIT('NOPAGE'));
    KEYWORDS [KWS$K_NOPAGE, KWS$H_KW_LENGTH] = 6;
    KEYWORDS [KWS$K_NOPAGE, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! NORUNIN keyword
    KEYWORDS [KWS$K_NORUNIN, KWS$A_KW_POINTER] = CH$PTR(UPLIT('NORUNIN'));
    KEYWORDS [KWS$K_NORUNIN, KWS$H_KW_LENGTH] = 7;
    KEYWORDS [KWS$K_NORUNIN, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! NOSTARTODD keyword
    KEYWORDS [KWS$K_NOSTARTODD, KWS$A_KW_POINTER] = CH$PTR(UPLIT('NOSTARTODD'));
    KEYWORDS [KWS$K_NOSTARTODD, KWS$H_KW_LENGTH] = 11;
    KEYWORDS [KWS$K_NOSTARTODD, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! NOTOCPAGE keyword
    KEYWORDS [KWS$K_NOTOCPAGE, KWS$A_KW_POINTER] = CH$PTR(UPLIT('NOTOCPAGE'));
    KEYWORDS [KWS$K_NOTOCPAGE, KWS$H_KW_LENGTH] = 10;
    KEYWORDS [KWS$K_NOTOCPAGE, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! NOUNDERLINE keyword
    KEYWORDS [KWS$K_NOUNDERLINE, KWS$A_KW_POINTER] = CH$PTR(UPLIT('NOUNDERLINE'));
    KEYWORDS [KWS$K_NOUNDERLINE, KWS$H_KW_LENGTH] = 11;
    KEYWORDS [KWS$K_NOUNDERLINE, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! NUMBERED keyword
    KEYWORDS [KWS$K_NUMBERED, KWS$A_KW_POINTER] = CH$PTR(UPLIT('NUMBERED'));
    KEYWORDS [KWS$K_NUMBERED, KWS$H_KW_LENGTH] = 8;
    KEYWORDS [KWS$K_NUMBERED, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! PAGE keyword
    KEYWORDS [KWS$K_PAGE, KWS$A_KW_POINTER] = CH$PTR(UPLIT('PAGE'));
    KEYWORDS [KWS$K_PAGE, KWS$H_KW_LENGTH] = 4;
    KEYWORDS [KWS$K_PAGE, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! RIGHT keyword
    KEYWORDS [KWS$K_RIGHT, KWS$A_KW_POINTER] = CH$PTR(UPLIT('RIGHT'));
    KEYWORDS [KWS$K_RIGHT, KWS$H_KW_LENGTH] = 5;
    KEYWORDS [KWS$K_RIGHT, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! RUNIN keyword
    KEYWORDS [KWS$K_RUNIN, KWS$A_KW_POINTER] = CH$PTR(UPLIT('RUNIN'));
    KEYWORDS [KWS$K_RUNIN, KWS$H_KW_LENGTH] = 5;
    KEYWORDS [KWS$K_RUNIN, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! SPACES keyword
    KEYWORDS [KWS$K_SPACES, KWS$A_KW_POINTER] = CH$PTR(UPLIT('SPACES'));
    KEYWORDS [KWS$K_SPACES, KWS$H_KW_LENGTH] = 6;
    KEYWORDS [KWS$K_SPACES, KWS$H_ARG_TYPE] = KWS$K_NUMBER_OPTIONAL;
    !
    ! STARTODD keyword
    KEYWORDS [KWS$K_STARTODD, KWS$A_KW_POINTER] = CH$PTR(UPLIT('STARTODD'));
    KEYWORDS [KWS$K_STARTODD, KWS$H_KW_LENGTH] = 9;
    KEYWORDS [KWS$K_STARTODD, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! TESTPAGE keyword
    KEYWORDS [KWS$K_TESTPAGE, KWS$A_KW_POINTER] = CH$PTR(UPLIT('TESTPAGE'));
    KEYWORDS [KWS$K_TESTPAGE, KWS$H_KW_LENGTH] = 8;
    KEYWORDS [KWS$K_TESTPAGE, KWS$H_ARG_TYPE] = KWS$K_NUMBER_OPTIONAL;
    !
    ! TOCPAGE keyword
    KEYWORDS [KWS$K_TOCPAGE, KWS$A_KW_POINTER] = CH$PTR(UPLIT('TOCPAGE'));
    KEYWORDS [KWS$K_TOCPAGE, KWS$H_KW_LENGTH] = 8;
    KEYWORDS [KWS$K_TOCPAGE, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! UNDERLINE keyword
    KEYWORDS [KWS$K_UNDERLINE, KWS$A_KW_POINTER] = CH$PTR(UPLIT('UNDERLINE'));
    KEYWORDS [KWS$K_UNDERLINE, KWS$H_KW_LENGTH] = 9;
    KEYWORDS [KWS$K_UNDERLINE, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !
    ! UNNUMBERED keyword
    KEYWORDS [KWS$K_UNNUMBERED, KWS$A_KW_POINTER] = CH$PTR(UPLIT('UNNUMBERED'));
    KEYWORDS [KWS$K_UNNUMBERED, KWS$H_KW_LENGTH] = 10;
    KEYWORDS [KWS$K_UNNUMBERED, KWS$H_ARG_TYPE] = KWS$K_NO_ARGUMENTS;
    !

    END;					! End of INIT_STYLE_KW
%FI
END						!End of module
ELUDOM
