::::::::::
help.dis
::::::::::
--
-- Source programs (in compilation order) for the HELP
--  Online Documentation System
--
-- After compiling, the modules to link are HELP, HELP_ANALYZE,
--   and HELP_BUILD.
--
-- The documentation refers to program names, like PHELP.
--  These names are symbols which represent the "RUN XXX"
--  commands under VMS which actually execute the tools.
--  For instance, the PHELP symbol is defined as:
--		PHELP :== "RUN HELP"
--  A directory reference is usually placed before the HELP
--  in "RUN HELP" so that PHELP can be executed from anywhere
--  on the system.
--
help_sysdep.ada
help.ada
help_analyze.ada
help_build.ada
--
-- Documentation file (user-oriented)
--
help.doc
help.rno
::::::::::
help_sysdep.ada
::::::::::

--|MODULE: HELP_SYSDEP
--|AUTHOR: CONN
--|LOCATION: PDL-TOOLS
--|SEE_ALSO: HELP
--|SEE_ALSO: HELP_ANALYZE
--|SEE_ALSO: HELP_BUILD
--|IEEE_PDL: SUPPORT_MODULE
--|DESIGN_STATUS         : DONE
--|IMPLEMENTATION_STATUS : DONE
--|DOCUMENTATION_STATUS  : DONE
--|DATE_RELEASED         : 9 Sep 85
--|DATE_LAST_MODIFIED    : 2 Mar 86
--|ABSTRACT:
--|     HELP_SYSDEP is a Systems-Dependency package for the HELP
--| system of programs.  It contains terminal-specific information
--| (such as the number of lines on a screen and number of columns).
--| Other information is also provided, including a CLEAR_SCREEN
--| routine.  If more than one terminal is to be used and/or a
--| clear screen or different clear screen sequences are used or
--| not available, simply make the body of this routine a "null;";
--| if only one terminal is used or several terminal types with the
--| same clear screen sequence, set up the CLEAR_SCREEN routine to
--| issue this sequence.  
-- 
with DIRECT_IO; 
package HELP_SYSDEP is 

-- 
-- HELP_FILE_NAME is the default name of the help file
-- It may be a fully-qualified file name (which includes directory reference)
-- so that the program will find it from any directory in which the program
-- resides.
--
-- This string should be no longer than MAX_HELP_LENGTH characters.
-- 
  MAX_HELP_LENGTH : constant NATURAL := 200;
      -- maximum number of characters in FILE_NAME string
      -- returned by HELP_FILE procedure
  HELP_FILE_NAME : constant STRING := "DBA4:[CONTR13.EXE]SIMTEL20.HLP";

  -- 
  -- SCREEN_WIDTH and SCREEN_LENGTH are terminal attributes
  -- 
  SCREEN_WIDTH   : constant NATURAL := 75; 
  SCREEN_LENGTH  : constant NATURAL := 23; 

  -- 
  -- Description of a screen
  -- 
  subtype SCREEN_TEXT is STRING(1 .. SCREEN_WIDTH); 
  type SCREEN_LINE is 
    record
      LINE : SCREEN_TEXT; 
      LAST : NATURAL; 
    end record; 
  type SCREEN_LINE_ARRAY is array(1 .. SCREEN_LENGTH) of SCREEN_LINE; 
  type SCREEN is 
    record
      LINES : SCREEN_LINE_ARRAY; 
      LAST  : NATURAL; 
    end record; 

--
-- This procedure returns the name of the help file to be used.
-- It may return the HELP_FILE_NAME defined above as a minimum
-- or it may be more exotic, perhaps scanning the user's command
-- path for any one of a number of help files and returning the
-- first help file found.  This is the help file which will be
-- processed by the programs as the default help file.
--
	procedure HELP_FILE (FILE_NAME : out STRING;
		             LAST : out NATURAL);

    -- 
    -- System-Dependent (Terminal-Dependent) Clear Screen routine
    -- If not implemented, should contain a body of "null;"
    -- 
  procedure CLEAR_SCREEN; 

  -- 
  -- Random-Access File I/O for HELP programs
  -- 
  package SDIRECT is 
    new DIRECT_IO(ELEMENT_TYPE => SCREEN); 

end HELP_SYSDEP; 

with TEXT_IO; 
package body HELP_SYSDEP is 

  procedure CLEAR_SCREEN is 
  begin
    TEXT_IO.PUT(ASCII.SUB);  -- ^Z
    -- TEXT_IO.PUT(ASCII.ESC);  -- for VT100 
    -- TEXT_IO.PUT_LINE("[2J"); 
    -- TEXT_IO.PUT(ASCII.ESC); 
    -- TEXT_IO.PUT("[1;1H"); 
  end CLEAR_SCREEN; 

  procedure HELP_FILE (FILE_NAME : out STRING;
                       LAST      : out NATURAL) is
  begin
    FILE_NAME(FILE_NAME'FIRST .. FILE_NAME'FIRST +
      HELP_FILE_NAME'LENGTH - 1) := HELP_FILE_NAME;
    LAST := HELP_FILE_NAME'LENGTH;
  end HELP_FILE;

end HELP_SYSDEP; 
::::::::::
help.ada
::::::::::


--|MODULE : HELP
--|AUTHOR : CONN
--|LOCATION : PDL-TOOLS
--|SEE_ALSO : HELP_ANALYZE
--|SEE_ALSO : HELP_BUILD
--|REQUIRES : HELP_SYSDEP
--|IEEE_PDL : DESIGN_INFORMATION_RETRIEVAL
--|IEEE_PDL : INTERACTIVE_DOCUMENTATION_REVIEW_SYSTEM
--|DESIGN_STATUS         : DONE
--|IMPLEMENTATION_STATUS : DONE
--|DOCUMENTATION_STATUS  : DONE
--|DATE_RELEASED         :  9 Sep 85
--|DATE_LAST_MODIFIED    : 2 Mar 86
--|ABSTRACT:
--|     HELP is an online documentation system.  It reads data
--| from a direct-access file generated by HELP_BUILD and builds
--| a tree which may be as wide as desired and up to ten levels
--| deep.  This tree contains sets of screen displays on various
--| topics.  After building this tree, HELP displays a menu of
--| the topics at the highest level, and the user can select a
--| desired topic by typing enough characters to uniquely identify
--| it.
--|     Once a desired topic is selected, HELP displays the screens
--| associated with this topic, allowing the user to move to the
--| next screen, last screen, up to the menu he came from, and
--| (if lower levels of information exist) display a menu of the
--| topics at the next lower level.  From this new menu, the process
--| is repeated (topics are selected, scanned, and lower levels of
--| menus may be accessed.
--|    The current topic may be printed out to a text file by
--| selecting the P)rint option which reviewing a topic.
--|
with TEXT_IO; 
with HELP_SYSDEP; use HELP_SYSDEP; 
procedure HELP is 

  VERSION : constant STRING(1 .. 3) := "1.3"; 

  package NAT_IO is 
    new TEXT_IO.INTEGER_IO(NATURAL); 

    -- 
    -- Key, global variables and constants
    -- 
  SOURCE_FILE     : SDIRECT.FILE_TYPE; 
  CURRENT_SCREEN  : SCREEN; 
  NEW_LINE        : SCREEN_LINE; 
  TOPIC_LIMIT     : constant NATURAL := 60;  -- max number of topics on scr
  TOPIC_SIZE      : constant NATURAL := 20;  -- max number of chars/topic
  TOPICS_PER_LINE : constant NATURAL := SCREEN_WIDTH/(TOPIC_SIZE + 2); 
  DEF_HELP_FILE   : STRING(1..MAX_HELP_LENGTH);
  DEF_HELP_LAST   : NATURAL;

  -- 
  -- Exceptions
  -- 
  STOP            : exception; 
  ABORT_HELP      : exception; 

  -- 
  -- These are the commands recognized by GET_COMMAND
  -- 
  type COMMAND_VERB is (EXIT_PROGRAM, UP_LEVEL, NEXT_SCREEN, LAST_SCREEN, 
    REFRESH_SCREEN, DISPLAY_MENU, PRINT_TOPIC, UNKNOWN); 

  -- 
  -- Each node of the tree is structured as follows:
  -- 
  type TOPIC; 
  type TOPIC_ACCESS is access TOPIC; 
  type TOPIC is 
    record
      TOPIC_HEADER : SCREEN_LINE; 
      NEXT_TOPIC   : TOPIC_ACCESS; 
      LAST_TOPIC   : TOPIC_ACCESS; 
      NEXT_LEVEL   : TOPIC_ACCESS; 
      LAST_LEVEL   : TOPIC_ACCESS; 
      INDEX_START  : SDIRECT.POSITIVE_COUNT; 
      INDEX_STOP   : SDIRECT.POSITIVE_COUNT; 
    end record; 

    -- 
    -- Pointers used in conjunction with the tree
    --      FIRST_TOPIC points to the first node of the tree
    -- 
  FIRST_TOPIC   : TOPIC_ACCESS; 
  CURRENT_TOPIC : TOPIC_ACCESS; 

  -- 
  -- Provided for Forward Reference Purposes
  -- 
  procedure PROCESS_MENU(LEVEL    : in NATURAL; 
                         MENU_PTR : in TOPIC_ACCESS); 

  -- 
  -- Error Routine
  -- 
  procedure ERROR(STR : in STRING) is 
    INLINE : SCREEN_LINE; 
  begin
    TEXT_IO.NEW_LINE; 
    TEXT_IO.PUT("**** ERROR ****  "); 
    TEXT_IO.PUT(STR); 
    TEXT_IO.PUT("    Strike Any Key "); 
    TEXT_IO.GET_LINE(INLINE.LINE, INLINE.LAST); 
    TEXT_IO.NEW_LINE; 
  end ERROR; 

  -- 
  -- TO_UPPER capitalizes the passed character
  -- 
  function TO_UPPER(CH : in CHARACTER) return CHARACTER is 
  begin
    if (CH >= 'a') and (CH <= 'z') then 
      return CHARACTER'VAL(CHARACTER'POS('A') + CHARACTER'POS(CH) - CHARACTER'
        POS('a')); 
    else 
      return CH; 
    end if; 
  end TO_UPPER; 

  -- 
  -- CAPSTR capitalizes the passed string
  -- 
  procedure CAPSTR(STR : in out STRING) is 
  begin
    for I in STR'FIRST .. STR'LAST loop
      STR(I) := TO_UPPER(STR(I)); 
    end loop; 
  end CAPSTR; 

  -- 
  -- IS_DIGIT determines if the passed character is in the range '0'..'9'
  -- 
  function IS_DIGIT(CH : in CHARACTER) return BOOLEAN is 
  begin
    if (CH >= '0') and (CH <= '9') then 
      return TRUE; 
    else 
      return FALSE; 
    end if; 
  end IS_DIGIT; 

  -- 
  -- VERB_CHECK determines if the passed string matches one of the verbs
  -- and returns the COMMAND_VERB which indicates the nature of the match
  -- 
  function VERB_CHECK(STR : in STRING) return COMMAND_VERB is 
  begin
    if STR'LENGTH = 1 then 
      case STR(1) is 
        when 'E' | 'X' => 
          return EXIT_PROGRAM; 
        when 'P' => 
          return PRINT_TOPIC; 
        when 'N' => 
          return NEXT_SCREEN; 
        when 'L' => 
          return LAST_SCREEN; 
        when 'U' => 
          return UP_LEVEL; 
        when 'M' => 
          return DISPLAY_MENU; 
        when '?' => 
          return REFRESH_SCREEN; 
        when others => 
          return UNKNOWN; 
      end case; 
    end if; 
    if STR'LENGTH = 2 then 
      if STR(STR'FIRST .. STR'LAST) = "UP" then 
        return UP_LEVEL; 
      else 
        return UNKNOWN; 
      end if; 
    end if; 
    if STR'LENGTH = 4 then 
      if STR(STR'FIRST .. STR'LAST) = "EXIT" then 
        return EXIT_PROGRAM; 
      end if; 
      if STR(STR'FIRST .. STR'LAST) = "NEXT" then 
        return NEXT_SCREEN; 
      end if; 
      if STR(STR'FIRST .. STR'LAST) = "LAST" then 
        return LAST_SCREEN; 
      end if; 
      if STR(STR'FIRST .. STR'LAST) = "MENU" then 
        return DISPLAY_MENU; 
      end if; 
    end if; 
    if STR'LENGTH = 5 then 
      if STR(STR'FIRST .. STR'LAST) = "PRINT" then 
        return PRINT_TOPIC; 
      end if; 
    end if; 
    return UNKNOWN; 
  end VERB_CHECK; 

  -- 
  -- GET_COMMAND inputs a command from the user
  --      The command is returned as a COMMAND_VERB and a SCREEN_LINE
  --      (text)
  -- 
  procedure GET_COMMAND(COMMAND : out COMMAND_VERB; 
                        CSTR    : out SCREEN_LINE) is 
    INLINE : SCREEN_LINE; 
  begin
    TEXT_IO.GET_LINE(INLINE.LINE, INLINE.LAST); 
    if INLINE.LAST > 0 then 
      CAPSTR(INLINE.LINE(1 .. INLINE.LAST)); 
    end if; 
    CSTR := INLINE; 
    if INLINE.LAST = 0 then 
      COMMAND := NEXT_SCREEN; 
    else 
      COMMAND := VERB_CHECK(INLINE.LINE(1 .. INLINE.LAST)); 
    end if; 
  end GET_COMMAND; 

  -- 
  -- Print Current Topic
  --     The indicated topic is printed onto the indicated file
  -- 
  procedure PRINT_CURRENT_TOPIC(FILE_NAME : in STRING; 
                                CT        : in TOPIC_ACCESS) is 
    FD         : TEXT_IO.FILE_TYPE; 
    SAVE_INDEX : SDIRECT.POSITIVE_COUNT; 
  begin
    TEXT_IO.NEW_LINE; 
    TEXT_IO.PUT_LINE("  Printing into file " & FILE_NAME); 
    SAVE_INDEX := SDIRECT.INDEX(SOURCE_FILE); 
    TEXT_IO.CREATE(FD, TEXT_IO.OUT_FILE, FILE_NAME); 
    for INDEX in CT.INDEX_START .. CT.INDEX_STOP loop
      SDIRECT.SET_INDEX(SOURCE_FILE, INDEX); 
      SDIRECT.READ(SOURCE_FILE, CURRENT_SCREEN); 
      if CURRENT_SCREEN.LAST > 0 then 
        for I in 1 .. CURRENT_SCREEN.LAST loop
          TEXT_IO.PUT_LINE(FD, CURRENT_SCREEN.LINES(I).LINE(1 .. CURRENT_SCREEN.
            LINES(I).LAST)); 
        end loop; 
      end if; 
    end loop; 
    TEXT_IO.CLOSE(FD); 
    SDIRECT.SET_INDEX(SOURCE_FILE, SAVE_INDEX); 
    SDIRECT.READ(SOURCE_FILE, CURRENT_SCREEN); 
  end PRINT_CURRENT_TOPIC; 

  -- 
  -- Display Current Screen
  --      The global CURRENT_SCREEN contains the screen to display
  -- 
  procedure DISPLAY_CURRENT_SCREEN is 
  begin
    CLEAR_SCREEN; 
    if CURRENT_SCREEN.LAST > 0 then 
      for I in 1 .. CURRENT_SCREEN.LAST loop
        TEXT_IO.PUT_LINE(CURRENT_SCREEN.LINES(I).LINE(1 .. CURRENT_SCREEN.LINES(
          I).LAST)); 
      end loop; 
    end if; 
    if CURRENT_SCREEN.LAST < SCREEN_LENGTH then 
      for I in CURRENT_SCREEN.LAST + 1 .. SCREEN_LENGTH loop
        TEXT_IO.NEW_LINE; 
      end loop; 
    end if; 
  end DISPLAY_CURRENT_SCREEN; 

  -- 
  -- Display Screens of Current Topic (CT)
  -- 
  procedure DISPLAY_CURRENT_TOPIC(LEVEL : in NATURAL; 
                                  CT    : in TOPIC_ACCESS) is 
    INDEX          : SDIRECT.POSITIVE_COUNT; 
    COMMAND        : COMMAND_VERB; 
    CSTR           : SCREEN_LINE; 
    FILE_NAME_LINE : SCREEN_LINE; 
    -- 
    -- Display Prompt for DISPLAY_CURRENT_TOPIC
    -- 
    procedure PROMPT is 
    begin
      TEXT_IO.PUT("Level "); 
      NAT_IO.PUT(LEVEL, 2); 
      TEXT_IO.PUT(" Topic: "); 
      TEXT_IO.PUT(CT.TOPIC_HEADER.LINE(1 .. CT.TOPIC_HEADER.LAST)); 
      TEXT_IO.PUT(" (Print, Exit, Up"); 
      if SDIRECT.POSITIVE_COUNT'POS(INDEX) /= SDIRECT.POSITIVE_COUNT'POS(CT.
        INDEX_STOP) then 
        TEXT_IO.PUT(", Next"); 
      end if; 
      if SDIRECT.POSITIVE_COUNT'POS(INDEX) /= SDIRECT.POSITIVE_COUNT'POS(CT.
        INDEX_START) then 
        TEXT_IO.PUT(", Last"); 
      end if; 
      if CT.NEXT_LEVEL /= null then 
        TEXT_IO.PUT(", Menu"); 
      end if; 
      TEXT_IO.PUT(")  "); 
    end PROMPT; 
    -- 
    -- Body of DISPLAY_CURRENT_TOPIC
    -- 
  begin
    INDEX := CT.INDEX_START; 
    loop

      -- 
      -- Position to screen, read screen, and display screen
      -- 
      SDIRECT.SET_INDEX(SOURCE_FILE, INDEX); 
      SDIRECT.READ(SOURCE_FILE, CURRENT_SCREEN); 
      DISPLAY_CURRENT_SCREEN; 

      -- 
      -- Prompt, get command, and process command
      -- 
      PROMPT; 
      GET_COMMAND(COMMAND, CSTR); 
      case COMMAND is 
        when PRINT_TOPIC => 
          TEXT_IO.NEW_LINE; 
          TEXT_IO.PUT("  Name of File to Print into? "); 
          TEXT_IO.GET_LINE(FILE_NAME_LINE.LINE, FILE_NAME_LINE.LAST); 
          if FILE_NAME_LINE.LAST > 0 then 
            PRINT_CURRENT_TOPIC(FILE_NAME_LINE.LINE(1 .. FILE_NAME_LINE.LAST), 
              CT); 
          end if; 
        when EXIT_PROGRAM => 
          raise ABORT_HELP; 
        when UP_LEVEL => 
          exit; 
        when NEXT_SCREEN => 
          if SDIRECT.POSITIVE_COUNT'POS(INDEX) = SDIRECT.POSITIVE_COUNT'POS(CT.
            INDEX_STOP) then 
            ERROR("At Last Screen"); 
          else 
            INDEX := SDIRECT.POSITIVE_COUNT'SUCC(INDEX); 
          end if; 
        when LAST_SCREEN => 
          if SDIRECT.POSITIVE_COUNT'POS(INDEX) = SDIRECT.POSITIVE_COUNT'POS(CT.
            INDEX_START) then 
            ERROR("At First Screen"); 
          else 
            INDEX := SDIRECT.POSITIVE_COUNT'PRED(INDEX); 
          end if; 
        when REFRESH_SCREEN => 
          null; 
        when DISPLAY_MENU => 
          if CT.NEXT_LEVEL = null then 
            ERROR("No Menu Available"); 
          else 
            PROCESS_MENU(LEVEL + 1, CT.NEXT_LEVEL); 
          end if; 
        when others => 
          ERROR("Unknown command -- " & CSTR.LINE(1 .. CSTR.LAST) & " --"); 
      end case; 
    end loop; 
  end DISPLAY_CURRENT_TOPIC; 

  -- 
  -- PROCESS_MENU processes a menu of the topics pointed to by the
  -- passed pointer
  -- 
  procedure PROCESS_MENU(LEVEL    : in NATURAL; 
                         MENU_PTR : in TOPIC_ACCESS) is 
    FIRST_MENU   : BOOLEAN; 
    TOPIC        : TOPIC_ACCESS; 
    NEXT_MENU    : TOPIC_ACCESS; 
    CURRENT_MENU : TOPIC_ACCESS; 
    COMMAND      : COMMAND_VERB; 
    CSTR         : SCREEN_LINE; 
    -- 
    -- Function FIND_HELP searches through the current menu (beginning at
    -- MENU_PTR) for the passed string
    -- 
    function FIND_HELP(STR : in SCREEN_LINE) return TOPIC_ACCESS is 
      ROVER : TOPIC_ACCESS; 
      -- 
      -- Compare strings (str vs topic header)
      -- 
      function COMPARE(STR1 : in STRING; 
                       STR2 : in STRING) return BOOLEAN is 
      begin
        if STR1'LENGTH + 2 > STR2'LENGTH then 
          return FALSE; 
        else 
          for I in 1 .. STR1'LENGTH loop
            if TO_UPPER(STR1(I)) /= TO_UPPER(STR2(I + 2)) then 
              return FALSE; 
            end if; 
          end loop; 
          return TRUE; 
        end if; 
      end COMPARE; 
      -- 
      -- Body of FIND_HELP
      --      This routine moves thru all topics at the level of the topic
      --      pointed to by MENU_PTR until end of list or match of STR to
      -- TOPIC_HEADER
      -- 
    begin
      ROVER := MENU_PTR; 
      while ROVER /= null loop
        exit when COMPARE(STR.LINE(1 .. STR.LAST), ROVER.TOPIC_HEADER.LINE(1 .. 
          ROVER.TOPIC_HEADER.LAST)); 
        ROVER := ROVER.NEXT_TOPIC; 
      end loop; 
      return ROVER; 
    end FIND_HELP; 

    -- 
    -- PROMPT prints the menu prompt
    -- 
    procedure PROMPT is 
    begin
      TEXT_IO.PUT("Level "); 
      NAT_IO.PUT(LEVEL, 2); 
      TEXT_IO.PUT(" Menu: "); 
      TEXT_IO.PUT("(Exit"); 
      if MENU_PTR.LAST_LEVEL /= null then 
        TEXT_IO.PUT(", Up"); 
      end if; 
      if NEXT_MENU /= null then 
        TEXT_IO.PUT(", Next Menu Screen"); 
      end if; 
      if not FIRST_MENU then 
        TEXT_IO.PUT(", Last Menu Screen"); 
      end if; 
      TEXT_IO.PUT(", Selection)  "); 
    end PROMPT; 
    -- 
    -- Display current menu
    -- 
    procedure DISPLAY_MENU is 
      ROVER       : TOPIC_ACCESS; 
      TOPIC_COUNT : NATURAL; 
      LINE_COUNT  : NATURAL; 
      -- 
      -- PRINT_TOPIC prints the topic pointed to by ROVER
      -- 
      procedure PRINT_TOPIC is 
        CHAR_LIMIT : NATURAL; 
      begin
        if ROVER.TOPIC_HEADER.LAST > TOPIC_SIZE + 2 then 
          CHAR_LIMIT := TOPIC_SIZE; 
        else 
          if ROVER.TOPIC_HEADER.LAST > 2 then 
            CHAR_LIMIT := ROVER.TOPIC_HEADER.LAST - 2; 
          else 
            CHAR_LIMIT := 0; 
          end if; 
        end if; 
        if CHAR_LIMIT > 0 then 
          TEXT_IO.PUT(ROVER.TOPIC_HEADER.LINE(3 .. CHAR_LIMIT + 2)); 
        end if; 
        if CHAR_LIMIT < TOPIC_SIZE then 
          for I in CHAR_LIMIT + 1 .. TOPIC_SIZE loop
            TEXT_IO.PUT(' '); 
          end loop; 
        end if; 
        TEXT_IO.PUT("  "); 
      end PRINT_TOPIC; 
      -- 
-- Mainline of DISPLAY_MENU moves thru all topics of CURRENT_MENU, displaying
      -- at most TOPIC_LIMIT of them at a time on one or more screens
      -- 
    begin
      ROVER := CURRENT_MENU; 
      TOPIC_COUNT := 0; 
      LINE_COUNT := 0; 
      CLEAR_SCREEN; 
      for I in 1 .. TOPIC_LIMIT loop
        exit when ROVER = null; 
        PRINT_TOPIC; 
        TOPIC_COUNT := TOPIC_COUNT + 1; 
        if TOPIC_COUNT = TOPICS_PER_LINE then 
          TOPIC_COUNT := 0; 
          LINE_COUNT := LINE_COUNT + 1; 
          TEXT_IO.NEW_LINE; 
        end if; 
        ROVER := ROVER.NEXT_TOPIC; 
      end loop; 
      NEXT_MENU := ROVER; 
      if LINE_COUNT < SCREEN_LENGTH then 
        for I in LINE_COUNT + 1 .. SCREEN_LENGTH loop
          TEXT_IO.NEW_LINE; 
        end loop; 
      end if; 
    end DISPLAY_MENU; 
    -- 
    -- Mainline of PROCESS_MENU
    -- Display menu screens, allow movement between screens, allow selection of
    -- menu topics
    -- 
  begin
    FIRST_MENU := TRUE; 
    CURRENT_MENU := MENU_PTR; 
    NEXT_MENU := null; 
    loop
      DISPLAY_MENU; 
      PROMPT; 
      GET_COMMAND(COMMAND, CSTR); 
      case COMMAND is 
        when EXIT_PROGRAM => 
          raise ABORT_HELP; 
        when UP_LEVEL => 
          if LEVEL /= 0 then 
            exit; 
          else 
            ERROR("At Top Level Menu - No Upper Level"); 
          end if; 
        when NEXT_SCREEN => 
          if NEXT_MENU = null then 
            ERROR("No More Menu Screens"); 
          else 
            CURRENT_MENU := NEXT_MENU; 
          end if; 
        when LAST_SCREEN => 
          if CURRENT_MENU = MENU_PTR then 
            ERROR("At First Menu Screen"); 
          else 
            for I in 1 .. TOPIC_LIMIT loop
              CURRENT_MENU := CURRENT_MENU.LAST_TOPIC; 
            end loop; 
          end if; 
        when REFRESH_SCREEN => 
          null; 
        when others => 
          TOPIC := FIND_HELP(CSTR); 
          if TOPIC = null then 
            ERROR("Topic " & CSTR.LINE(1 .. CSTR.LAST) & " Not Found"); 
          else 
            DISPLAY_CURRENT_TOPIC(LEVEL, TOPIC); 
          end if; 
      end case; 
    end loop; 
  end PROCESS_MENU; 

  -- 
  -- INIT initializes the 4-link list of the HELP file
  -- 
  procedure INIT is 
    INLINE : SCREEN_LINE; 
    -- 
    -- INIT_NEXT_LEVEL sets up the linked list for the next tree level
    -- 
    procedure INIT_NEXT_LEVEL(LEVEL      : in CHARACTER; 
                              LAST_LEVEL : in TOPIC_ACCESS) is 
      NEW_TOPIC       : TOPIC_ACCESS; 
      CURRENT_TOPIC   : TOPIC_ACCESS; 
      FIRST_NEW_TOPIC : BOOLEAN; 
      -- 
      -- Back up to previous screen in source
      -- 
      procedure BACKUP_FILE is 
      begin
        SDIRECT.SET_INDEX(SOURCE_FILE, SDIRECT.POSITIVE_COUNT'PRED(SDIRECT.INDEX
          (SOURCE_FILE))); 
      end BACKUP_FILE; 
      -- 
      -- Return index of current screen
      -- 
      function CURRENT_SCREEN_INDEX return SDIRECT.POSITIVE_COUNT is 
      begin
        return SDIRECT.INDEX(SOURCE_FILE); 
      end CURRENT_SCREEN_INDEX; 
      -- 
      -- Return index of previous screen
      -- 
      function PREVIOUS_SCREEN_INDEX return SDIRECT.POSITIVE_COUNT is 
      begin
        return SDIRECT.POSITIVE_COUNT'PRED(CURRENT_SCREEN_INDEX); 
      end PREVIOUS_SCREEN_INDEX; 
      -- 
      -- Determine if CURRENT_TOPIC.INDEX_STOP has been set
      -- 
      function CURRENT_INDEX_STOP_NOT_SET return BOOLEAN is 
      begin
        if SDIRECT.POSITIVE_COUNT'POS(CURRENT_TOPIC.INDEX_STOP) = 1 then 
          return TRUE; 
        else 
          return FALSE; 
        end if; 
      end CURRENT_INDEX_STOP_NOT_SET; 
      -- 
      -- Move thru the data file, building topic list
      -- 
    begin
      FIRST_NEW_TOPIC := TRUE; 
      CURRENT_TOPIC := null; 
      while not SDIRECT.END_OF_FILE(SOURCE_FILE) loop

        -- 
        -- Read next screen
        -- 
        SDIRECT.READ(SOURCE_FILE, CURRENT_SCREEN); 
        NEW_LINE := CURRENT_SCREEN.LINES(1); 

        -- 
-- Do following processing if the screen is a new topic (begins with "N text")
        -- 
        if NEW_LINE.LAST > 1 then 
          if IS_DIGIT(NEW_LINE.LINE(1)) and (NEW_LINE.LINE(2) = ' ') then 

            -- 
            -- The screen is a new topic, so process
            -- 
            if LEVEL > NEW_LINE.LINE(1) then 

              -- 
-- If lower level than previous topic, exit and return to called to continue
              -- at lower level
              -- 
              BACKUP_FILE; 
              if CURRENT_TOPIC /= null then 
                if CURRENT_INDEX_STOP_NOT_SET then 
                  CURRENT_TOPIC.INDEX_STOP := PREVIOUS_SCREEN_INDEX; 
                end if; 
              end if; 
              exit; 
            end if; 
            if LEVEL < NEW_LINE.LINE(1) then 

              -- 
-- If at higher level than previous topic, make recursive call for new
              -- processing at this higher level
              -- 
              BACKUP_FILE; 
              if CURRENT_TOPIC /= null then 
                if CURRENT_INDEX_STOP_NOT_SET then 
                  CURRENT_TOPIC.INDEX_STOP := PREVIOUS_SCREEN_INDEX; 
                end if; 
              end if; 
              INIT_NEXT_LEVEL(NEW_LINE.LINE(1), CURRENT_TOPIC); 
            else 
              NEW_TOPIC := new TOPIC; 
              if FIRST_NEW_TOPIC then 
                if LAST_LEVEL /= null then 
                  LAST_LEVEL.NEXT_LEVEL := NEW_TOPIC; 
                end if; 
                FIRST_NEW_TOPIC := FALSE; 
              end if; 
              NEW_TOPIC.TOPIC_HEADER := NEW_LINE; 
              NEW_TOPIC.NEXT_TOPIC := null; 
              NEW_TOPIC.LAST_TOPIC := CURRENT_TOPIC; 
              NEW_TOPIC.NEXT_LEVEL := null; 
              NEW_TOPIC.LAST_LEVEL := LAST_LEVEL; 
              NEW_TOPIC.INDEX_START := PREVIOUS_SCREEN_INDEX; 
              NEW_TOPIC.INDEX_STOP := 1; 
              if CURRENT_TOPIC /= null then 
                if CURRENT_INDEX_STOP_NOT_SET then 
                  CURRENT_TOPIC.INDEX_STOP := SDIRECT.POSITIVE_COUNT'PRED(
                    NEW_TOPIC.INDEX_START); 
                end if; 
                CURRENT_TOPIC.NEXT_TOPIC := NEW_TOPIC; 
              end if; 
              CURRENT_TOPIC := NEW_TOPIC; 
              if FIRST_TOPIC = null then 
                FIRST_TOPIC := CURRENT_TOPIC; 
              end if; 
            end if; 
          end if; 
        end if; 
      end loop; 
      if CURRENT_INDEX_STOP_NOT_SET then 
        CURRENT_TOPIC.INDEX_STOP := PREVIOUS_SCREEN_INDEX; 
      end if; 
    end INIT_NEXT_LEVEL; 
    -- 
    -- INIT mainline follows
    -- 
  begin
    TEXT_IO.PUT("Help File (RETURN for Default)> "); 
    TEXT_IO.GET_LINE(INLINE.LINE, INLINE.LAST); 
    begin
      if INLINE.LAST = 0 then 
        HELP_FILE (DEF_HELP_FILE, DEF_HELP_LAST);
        SDIRECT.OPEN(SOURCE_FILE, SDIRECT.IN_FILE, 
          DEF_HELP_FILE(1..DEF_HELP_LAST));
      else 
        SDIRECT.OPEN(SOURCE_FILE, SDIRECT.IN_FILE, INLINE.LINE(1 .. INLINE.LAST)
          ); 
      end if; 
    exception
      when others => 
        TEXT_IO.PUT_LINE("Help File not Found"); 
        raise STOP; 
    end; 
    FIRST_TOPIC := null; 
    CURRENT_TOPIC := null; 
    INIT_NEXT_LEVEL('1', null); 
    SDIRECT.RESET(SOURCE_FILE); 
  end INIT; 

  -- 
  -- Deinitialize system for exit
  -- 
  procedure DEINIT is 
  begin
    SDIRECT.CLOSE(SOURCE_FILE); 
  end DEINIT; 

-- 
-- HELP mainline follows
-- 
begin
  TEXT_IO.PUT_LINE("HELP, Version " & VERSION); 
  INIT; 
  if FIRST_TOPIC /= null then 
    PROCESS_MENU(0, FIRST_TOPIC); 
  else 
    ERROR("Help File is Empty"); 
  end if; 
  DEINIT; 
exception
  when ABORT_HELP => 
    DEINIT; 
  when others => 
    TEXT_IO.PUT_LINE("Unexpected Fatal Error"); 
end HELP; 
::::::::::
help_analyze.ada
::::::::::

--|MODULE: HELP_ANALYZE
--|AUTHOR: CONN
--|LOCATION: PDL-TOOLS
--|SEE_ALSO : HELP
--|SEE_ALSO : HELP_BUILD
--|REQUIRES : HELP_SYSDEP
--|IEEE_PDL : SUPPORT_MODULE
--|DESIGN_STATUS         : DONE
--|IMPLEMENTATION_STATUS : DONE
--|DOCUMENTATION_STATUS  : DONE
--|DATE_RELEASED         : 9 Sep 85
--|DATE_LAST_MODIFIED    : 2 Mar 86
--|ABSTRACT :
--|     HELP_ANALYZE performs an analysis of a direct-access
--| file created by HELP_BUILD.  It indicates each of the topics
--| contained in the file, and, by indentation, shows their
--| hierarchical relationship.  HELP_ANALYZE also displays, using
--| the symbols "Start =" and "Stop =", the beginning and ending
--| record numbers of each topic.
--|
with TEXT_IO; 
with HELP_SYSDEP; use HELP_SYSDEP; 
procedure HELP_ANALYZE is 

  package NAT_IO is 
    new TEXT_IO.INTEGER_IO(NATURAL); 
  package C_IO is 
    new TEXT_IO.INTEGER_IO(SDIRECT.COUNT); 

    -- 
    -- Important constants and global variables
    -- 
  VERSION        : constant STRING(1 .. 3) := "1.1"; 
  SOURCE_FILE    : SDIRECT.FILE_TYPE; 
  CURRENT_SCREEN : SCREEN; 
  NEW_LINE       : SCREEN_LINE; 
  TOPIC_LIMIT    : constant NATURAL := 60;  -- max number of topics on scr
  TOPIC_SIZE     : constant NATURAL := 20;  -- max number of chars/topic
  DEF_HELP_FILE  : STRING(1..MAX_HELP_LENGTH);
  DEF_HELP_LAST  : NATURAL;

  -- 
  -- Exceptions
  -- 
  STOP           : exception; 

  -- 
  -- Nodes of the tree to be build in performing the analysis
  -- 
  type TOPIC; 
  type TOPIC_ACCESS is access TOPIC; 
  type TOPIC is 
    record
      TOPIC_HEADER : SCREEN_LINE; 
      NEXT_TOPIC   : TOPIC_ACCESS; 
      LAST_TOPIC   : TOPIC_ACCESS; 
      NEXT_LEVEL   : TOPIC_ACCESS; 
      LAST_LEVEL   : TOPIC_ACCESS; 
      INDEX_START  : SDIRECT.POSITIVE_COUNT; 
      INDEX_STOP   : SDIRECT.POSITIVE_COUNT; 
    end record; 

    -- 
    -- These variables define the tree
    --      FIRST_TOPIC points to the first node
    -- 
  FIRST_TOPIC   : TOPIC_ACCESS; 
  CURRENT_TOPIC : TOPIC_ACCESS; 

  -- 
  -- IS_DIGIT determines if the indicated character is a digit
  -- 
  function IS_DIGIT(CH : in CHARACTER) return BOOLEAN is 
  begin
    if (CH >= '0') and (CH <= '9') then 
      return TRUE; 
    else 
      return FALSE; 
    end if; 
  end IS_DIGIT; 

  -- 
  -- Initialize and build the tree
  -- 
  procedure INIT is 
    INLINE : SCREEN_LINE; 
    -- 
    -- Build tree at next level
    -- 
    procedure INIT_NEXT_LEVEL(LEVEL      : in CHARACTER; 
                              LAST_LEVEL : in TOPIC_ACCESS) is 
      NEW_TOPIC       : TOPIC_ACCESS; 
      CURRENT_TOPIC   : TOPIC_ACCESS; 
      FIRST_NEW_TOPIC : BOOLEAN; 
      -- 
      -- Back up to previous screen in source
      -- 
      procedure BACKUP_FILE is 
      begin
        SDIRECT.SET_INDEX(SOURCE_FILE, SDIRECT.POSITIVE_COUNT'PRED(SDIRECT.INDEX
          (SOURCE_FILE))); 
      end BACKUP_FILE; 
      -- 
      -- Return index of current screen
      -- 
      function CURRENT_SCREEN_INDEX return SDIRECT.POSITIVE_COUNT is 
      begin
        return SDIRECT.INDEX(SOURCE_FILE); 
      end CURRENT_SCREEN_INDEX; 
      -- 
      -- Return index of previous screen
      -- 
      function PREVIOUS_SCREEN_INDEX return SDIRECT.POSITIVE_COUNT is 
      begin
        return SDIRECT.POSITIVE_COUNT'PRED(CURRENT_SCREEN_INDEX); 
      end PREVIOUS_SCREEN_INDEX; 
      -- 
      -- Determine if CURRENT_TOPIC.INDEX_STOP has been set
      -- 
      function CURRENT_INDEX_STOP_NOT_SET return BOOLEAN is 
      begin
        if SDIRECT.POSITIVE_COUNT'POS(CURRENT_TOPIC.INDEX_STOP) = 1 then 
          return TRUE; 
        else 
          return FALSE; 
        end if; 
      end CURRENT_INDEX_STOP_NOT_SET; 
      -- 
      -- Read each screen of the data file and build tree
      -- 
    begin
      FIRST_NEW_TOPIC := TRUE; 
      CURRENT_TOPIC := null; 
      while not SDIRECT.END_OF_FILE(SOURCE_FILE) loop

        -- 
        -- Read next screen and determine if it is a new topic
        -- 
        SDIRECT.READ(SOURCE_FILE, CURRENT_SCREEN); 
        NEW_LINE := CURRENT_SCREEN.LINES(1); 
        if NEW_LINE.LAST > 1 then 
          if IS_DIGIT(NEW_LINE.LINE(1)) and (NEW_LINE.LINE(2) = ' ') then 

            -- 
            -- Screen is a new topic
            -- 
            if LEVEL > NEW_LINE.LINE(1) then 

              -- 
              -- New topic is at a lower level, so back up and return to caller
              -- (who is at lower level)
              -- 
              BACKUP_FILE; 
              if CURRENT_TOPIC /= null then 
                if CURRENT_INDEX_STOP_NOT_SET then 
                  CURRENT_TOPIC.INDEX_STOP := PREVIOUS_SCREEN_INDEX; 
                end if; 
              end if; 
              exit; 
            end if; 
            if LEVEL < NEW_LINE.LINE(1) then 

              -- 
-- New topic is at higher level, so recursively call INIT_NEXT_LEVEL
              -- and build tree at this new level
              -- 
              BACKUP_FILE; 
              if CURRENT_TOPIC /= null then 
                if CURRENT_INDEX_STOP_NOT_SET then 
                  CURRENT_TOPIC.INDEX_STOP := PREVIOUS_SCREEN_INDEX; 
                end if; 
              end if; 
              INIT_NEXT_LEVEL(NEW_LINE.LINE(1), CURRENT_TOPIC); 
            else 
              NEW_TOPIC := new TOPIC; 
              if FIRST_NEW_TOPIC then 
                if LAST_LEVEL /= null then 
                  LAST_LEVEL.NEXT_LEVEL := NEW_TOPIC; 
                end if; 
                FIRST_NEW_TOPIC := FALSE; 
              end if; 
              NEW_TOPIC.TOPIC_HEADER := NEW_LINE; 
              NEW_TOPIC.NEXT_TOPIC := null; 
              NEW_TOPIC.LAST_TOPIC := CURRENT_TOPIC; 
              NEW_TOPIC.NEXT_LEVEL := null; 
              NEW_TOPIC.LAST_LEVEL := LAST_LEVEL; 
              NEW_TOPIC.INDEX_START := PREVIOUS_SCREEN_INDEX; 
              NEW_TOPIC.INDEX_STOP := 1; 
              if CURRENT_TOPIC /= null then 
                if CURRENT_INDEX_STOP_NOT_SET then 
                  CURRENT_TOPIC.INDEX_STOP := SDIRECT.POSITIVE_COUNT'PRED(
                    NEW_TOPIC.INDEX_START); 
                end if; 
                CURRENT_TOPIC.NEXT_TOPIC := NEW_TOPIC; 
              end if; 
              CURRENT_TOPIC := NEW_TOPIC; 
              if FIRST_TOPIC = null then 
                FIRST_TOPIC := CURRENT_TOPIC; 
              end if; 
            end if; 
          end if; 
        end if; 
      end loop; 
      if CURRENT_INDEX_STOP_NOT_SET then 
        CURRENT_TOPIC.INDEX_STOP := PREVIOUS_SCREEN_INDEX; 
      end if; 
    end INIT_NEXT_LEVEL; 
    -- 
    -- INIT mainline follows
    -- 
  begin
    TEXT_IO.PUT("Help File (RETURN for Default)> "); 
    TEXT_IO.GET_LINE(INLINE.LINE, INLINE.LAST); 
    begin
      if INLINE.LAST = 0 then 
        HELP_FILE (DEF_HELP_FILE, DEF_HELP_LAST);
        SDIRECT.OPEN(SOURCE_FILE, SDIRECT.IN_FILE, 
          DEF_HELP_FILE(1..DEF_HELP_LAST));
      else 
        SDIRECT.OPEN(SOURCE_FILE, SDIRECT.IN_FILE, INLINE.LINE(1 .. INLINE.LAST)
          ); 
      end if; 
    exception
      when others => 
        TEXT_IO.PUT_LINE("Help File not Found"); 
        raise STOP; 
    end; 
    FIRST_TOPIC := null; 
    CURRENT_TOPIC := null; 
    INIT_NEXT_LEVEL('1', null); 
    SDIRECT.RESET(SOURCE_FILE); 
  end INIT; 

  -- 
  -- Deinitialize system for exit
  -- 
  procedure DEINIT is 
  begin
    SDIRECT.CLOSE(SOURCE_FILE); 
  end DEINIT; 

  -- 
  -- Generate report at indicated level
  -- 
  procedure TEST_HELP(FIRST_TOPIC : in TOPIC_ACCESS; 
                      INDENT      : in NATURAL) is 
    TOPIC : TOPIC_ACCESS; 
  begin
    TOPIC := FIRST_TOPIC; 
    while TOPIC /= null loop
      if INDENT > 0 then 
        for I in 1 .. INDENT loop
          TEXT_IO.PUT(' '); 
        end loop; 
      end if; 
      TEXT_IO.PUT(TOPIC.TOPIC_HEADER.LINE(1 .. TOPIC.TOPIC_HEADER.LAST)); 
      TEXT_IO.PUT(": Start = "); 
      C_IO.PUT(TOPIC.INDEX_START, 3); 
      TEXT_IO.PUT("   Stop = "); 
      C_IO.PUT(TOPIC.INDEX_STOP, 3); 
      TEXT_IO.NEW_LINE; 
      if TOPIC.NEXT_LEVEL /= null then 
        TEST_HELP(TOPIC.NEXT_LEVEL, INDENT + 3); 
      end if; 
      TOPIC := TOPIC.NEXT_TOPIC; 
    end loop; 
  end TEST_HELP; 

-- 
-- HELP_analyze mainline follows
-- 
begin
  TEXT_IO.PUT_LINE("HELP Analyzer, Version " & VERSION); 
  INIT; 
  TEST_HELP(FIRST_TOPIC, 0); 
  DEINIT; 
end HELP_ANALYZE; 
::::::::::
help_build.ada
::::::::::

--|MODULE : HELP_BUILD
--|AUTHOR : CONN
--|LOCATION : PDL-TOOLS
--|SEE_ALSO : HELP
--|SEE_ALSO : HELP_ANALYZE
--|REQUIRES : HELP_SYSDEP
--|IEEE_PDL : SUPPORT_MODULE
--|DESIGN_STATUS         : DONE
--|IMPLEMENTATION_STATUS : DONE
--|DOCUMENTATION_STATUS  : DONE
--|DATE_RELEASED         : 9 Sep 85
--|DATE_LAST_MODIFIED    : 2 Mar 86
--|ABSTRACT :
--|     HELP_BUILD is used to create a direct-access file that
--| can be processed by HELP and HELP_ANALYZE.  HELP_BUILD accepts
--| as input a conventional text file and generates a direct-access
--| file in which each record is a screen display (size is specified
--| by HELP_SYSDEP values).  Screens are defined as follows:
--|
--|             1. when the number of text lines specified by
--| HELP_SYSDEP.SCREEN_LENGTH is exceeded, the current screen is
--| completed and a new screen is started
--|             2. when a screen-break command is encountered, the
--| current screen is completed and a new screen is started; the
--| screen-break command is a line containing only a period in column
--| one
--|             3. when a new topic is encountered, the current
--| screen is completed and a new screen is started; a topic is a
--| line with a digit in column 1, a space in column 2, and text
--| following
--|
--|     Topic levels and subordinate relationships are indicated by
--| the leading digits on a topic line.
--|     The following illustrates a simple help file text:
--|
--|     0 MAIN_TOPIC_1
--|             Text
--|     1 SUB_TOPIC_1
--|     1 SUB_TOPIC_2
--|     1 SUB_SUB_TOPIC_1
--|             Text, page 1
--|     .
--|             Text, page 2 (previous line caused screen-break)
--|     2 SUB_SUB_TOPIC_2
--|     2 SUB_SUB_TOPIC_3
--|     1 SUB_TOPIC_3
--|     0 MAIN_TOPIC_2
--|
--|     Topic level numbering does not have to be in sequence.
--| The numbers associated with subordinate topics need only
--| be greater than their parents.  For instance:
--|
--|     1 MAIN_TOPIC
--|     5 SUB_TOPIC
--|
--| is valid.
--|
with TEXT_IO; 
with HELP_SYSDEP; use HELP_SYSDEP; 
procedure HELP_BUILD is 

  package NAT_IO is 
    new TEXT_IO.INTEGER_IO(NATURAL); 

    -- 
    -- Constants, global variables, and special data
    -- 
  VERSION          : constant STRING(1 .. 3) := "1.1"; 
  SOURCE_FILE      : TEXT_IO.FILE_TYPE; 
  DESTINATION_FILE : SDIRECT.FILE_TYPE; 
  CURRENT_SCREEN   : SCREEN; 
  NEW_LINE         : SCREEN_LINE; 
  SCREEN_COUNT     : NATURAL; 
  HEADER_COUNT     : NATURAL; 
  DEF_HELP_FILE    : STRING (1..MAX_HELP_LENGTH);
  DEF_HELP_LAST    : NATURAL;

  -- 
  -- Exceptions
  -- 
  STOP             : exception; 

  -- 
  -- Identify source and destination files, init counters
  -- 
  procedure INIT is 
    INLINE : SCREEN_LINE; 
  begin
    TEXT_IO.PUT("Source Text File                       > "); 
    TEXT_IO.GET_LINE(INLINE.LINE, INLINE.LAST); 
    if INLINE.LAST = 0 then 
      raise STOP; 
    end if; 
    begin
      TEXT_IO.OPEN(SOURCE_FILE, TEXT_IO.IN_FILE, INLINE.LINE(1 .. INLINE.LAST))
        ; 
    exception
      when others => 
        TEXT_IO.PUT_LINE(" Source file not found"); 
        raise STOP; 
    end; 
    TEXT_IO.PUT("Help File to Build (RETURN for Default)> "); 
    TEXT_IO.GET_LINE(INLINE.LINE, INLINE.LAST); 
    begin
      if INLINE.LAST = 0 then 
        HELP_FILE (DEF_HELP_FILE, DEF_HELP_LAST);
        SDIRECT.CREATE(DESTINATION_FILE, SDIRECT.OUT_FILE, 
          DEF_HELP_FILE(1..DEF_HELP_LAST));
      else 
        SDIRECT.CREATE(DESTINATION_FILE, SDIRECT.OUT_FILE, INLINE.LINE(1 .. 
          INLINE.LAST)); 
      end if; 
    exception
      when others => 
        TEXT_IO.PUT_LINE(" Cannot create destination file"); 
        raise STOP; 
    end; 
    SCREEN_COUNT := 0; 
    HEADER_COUNT := 0; 
  end INIT; 

  -- 
  -- Deinit cleanup
  -- 
  procedure DEINIT is 
  begin
    TEXT_IO.CLOSE(SOURCE_FILE); 
    SDIRECT.CLOSE(DESTINATION_FILE); 
  end DEINIT; 

  -- 
  -- Establish new screen
  -- 
  procedure NEW_SCREEN is 
  begin
    CURRENT_SCREEN.LAST := 0; 
  end NEW_SCREEN; 

  -- 
  -- Write current screen to output data file
  -- 
  procedure DUMP_SCREEN is 
  begin
    if CURRENT_SCREEN.LAST > 0 then 
      SDIRECT.WRITE(DESTINATION_FILE, CURRENT_SCREEN); 
      SCREEN_COUNT := SCREEN_COUNT + 1; 
    end if; 
    NEW_SCREEN; 
  end DUMP_SCREEN; 

  -- 
  -- Determine if text line begins with a number which identifies it as
  -- a topic
  -- 
  function LEADING_NUMBER(LINE : in STRING) return BOOLEAN is 

    function IS_DIGIT(CH : in CHARACTER) return BOOLEAN is 
    begin
      if (CH >= '0') and (CH <= '9') then 
        return TRUE; 
      else 
        return FALSE; 
      end if; 
    end IS_DIGIT; 

  begin
    if LINE'LENGTH = 0 then 
      return FALSE; 
    end if; 

    if not IS_DIGIT(LINE(LINE'FIRST)) then 
      return FALSE; 
    end if; 

    for I in LINE'FIRST .. LINE'LAST loop
      if LINE(I) = ' ' then 
        return TRUE; 
      end if; 
      if not IS_DIGIT(LINE(I)) then 
        return FALSE; 
      end if; 
    end loop; 
    return FALSE; 
  end LEADING_NUMBER; 

  -- 
  -- Mainline
  -- 
begin
  TEXT_IO.PUT_LINE("HELP File Builder, Version " & VERSION); 
  INIT; 
  NEW_SCREEN; 

  -- 
  -- Loop thru source file
  -- 
  while not TEXT_IO.END_OF_FILE(SOURCE_FILE) loop

    -- 
    -- Get new line
    -- 
    TEXT_IO.GET_LINE(SOURCE_FILE, NEW_LINE.LINE, NEW_LINE.LAST); 

    -- 
    -- If new topic, dump current screen and begin new header/screen
    -- 
    if LEADING_NUMBER(NEW_LINE.LINE(1 .. NEW_LINE.LAST)) then 
      DUMP_SCREEN; 
      HEADER_COUNT := HEADER_COUNT + 1; 
    end if; 

    -- 
    -- If page break command (line containing only a dot), dump current screen
    -- 
    if (NEW_LINE.LAST = 1) and (NEW_LINE.LINE(1) = '.') then 
      DUMP_SCREEN; 
    else 

      -- 
      -- If not page break, add line to current screen and dump current screen
      -- if screen fills
      -- 
      CURRENT_SCREEN.LAST := CURRENT_SCREEN.LAST + 1; 
      CURRENT_SCREEN.LINES(CURRENT_SCREEN.LAST) := NEW_LINE; 
      if CURRENT_SCREEN.LAST = SCREEN_LENGTH then 
        DUMP_SCREEN; 
      end if; 
    end if; 
  end loop; 

  -- 
  -- Dump last screen and print report
  -- 
  DUMP_SCREEN; 
  TEXT_IO.PUT("Number of Screens Written: "); 
  NAT_IO.PUT(SCREEN_COUNT, 5); 
  TEXT_IO.NEW_LINE; 
  TEXT_IO.PUT("Number of Headers Written: "); 
  NAT_IO.PUT(HEADER_COUNT, 5); 
  TEXT_IO.NEW_LINE; 
  DEINIT; 
end HELP_BUILD; 
::::::::::
help.doc
::::::::::














             User Manual for Online Documentation System





              by Richard Conn, TI Ada Technology Branch















1  HELP



     HELP is an online documentation system.  It  reads  data  from  a

direct-access file generated by HELP_BUILD and builds a tree which may

be as wide as desired and up to ten levels deep.  This  tree  contains

sets  of screen displays on various topics.  After building this tree,

HELP displays a menu of the topics at the highest level, and the  user

can  select  a  desired  topic by typing enough characters to uniquely

identify it.



     Once a desired topic  is  selected,  HELP  displays  the  screens

associated  with  this  topic,  allowing  the user to move to the next

screen, last screen, up to the menu he came from, and (if lower levels

of  information  exist) display a menu of the topics at the next lower

level.  From this new  menu,  the  process  is  repeated  (topics  are

selected, scanned, and lower levels of menus may be accessed.







1.1  EXECUTION OF TOOL





VMS Command Required to Invoke Tool: PHELP

Input Files Required:

        Direct access help file

Output Files Generated: None

Notes:  PHELP is an interactive tool.









1.2  PROMPTS



     Two prompts are presented to the user during the execution of the

HELP  tool.   One  prompt  appears  when the user is viewing a menu of

topics he can select and the other appears when the  user  is  viewing

screens associated with a topic.

                                                                Page 2





     The full prompt which can appear when a menu of topics  is  being

displayed is:



Level  N Menu: (Exit, Up, Next Menu Screen, Last Menu Screen,

        Selection)



     The various parts of this prompt have the following meanings:



     1.  Level N - Indicates the level in the tree you are  at.   This

         part of the prompt always appears.



     2.  Menu:  - Indicates that you are viewing a menu as opposed  to

         screens of a topic.  This part of the prompt always appears.



     3.  Exit - Indicates that the  Exit  command  (X)  is  available.

         This part of the prompt always appears.



     4.  Up - Indicates that the Up command (U or  UP)  is  available.

         If you are at the top level, this part of the prompt does not

         appear.  If you are below the top level, it does.



     5.  Next Menu Screen - Indicates that more  menu  screens  follow

         the  one  you are viewing and the Next command (N or NEXT) is

         available.  This prompt optionally appears.



     6.  Last Menu Screen - Indicates that one or  more  menu  screens

         preceed  the  one  you are viewing and the Last command (L or

         LAST) is available.  This prompt optionally appears.



     7.  Selection - Indicates that you may select a topic from any of

         the  screens  associated  with this menu.  The topic does not

         have to appear on the menu screen you are currently  viewing.

         This prompt always appears.





     The full prompt which can appear while viewing screens associated

with a particular topic is:



Level  N Topic: XXX (Print, Exit, Up, Next, Last, Menu)



     Various parts of this prompt are optional, and  the  meanings  of

the sections of this prompt are:



     1.  Level N - Indicates the current level.   This  prompt  always

         appears.



     2.  Topic:  XXX -  Indicates  the  name  of  the  topic  you  are

         viewing.  This prompt always appears.



     3.  Print - Indicates that the user may print the  current  topic

         (all  screens)  to  a  file.  The user is prompted for a file

         name in response to the P or  PRINT  command.   If  the  user

         changes  his  mind, striking the RETURN key aborts the print.

         Typing in a file name prints into  the  file.   The  user  is

         returned to the current screen after the print is performed.

                                                                Page 3





     4.  Exit - Indicates that the  Exit  command  (X)  is  available.

         This prompt always appears.



     5.  Up - Indicates that the Up command (U or  UP)  is  available.

         This  command raises you to the next higher level (which is a

         menu).  This prompt always appears.



     6.  Next - Indicates that more screens on this topic follow.  The

         Next  command  (N  or  NEXT) displays the next screen to you.

         This prompt appears only if more  screens  follow.   Striking

         only the RETURN key has the same effect as the NEXT command.



     7.  Last - Indicates that one or more screens proceed the  screen

         you  are viewing on this topic.  The Last command (L or LAST)

         displays the previous screen to  you.   This  prompt  appears

         only if you are not at the first screen of a topic.



     8.  Menu - Indicates that a menu of subtopics under  the  current

         topic  is  available.   The  Menu  command  (M  or MENU) will

         display this menu to you.  This prompt appears only if one or

         more subtopics exist under the current topic.





     At any time, the ?  character (followed by a RETURN)  will  cause

the current screen to be refreshed.







1.3  ERROR MESSAGES



     Error messages generated by the HELP tool are  displayed  at  the

bottom of the screen with the following syntax:



        **** ERROR **** XXX Strike Any Key



     The possible error messages are:



     1.  At First Menu Screen.  The Last Screen command  (L  or  LAST)

         was  issued  when the user was already at the first screen of

         the menu display.



     2.  At First Screen.  The Last Screen command  (L  or  LAST)  was

         issued  when  the user was already at the first screen of the

         current topic.



     3.  At Last Screen.  The Next Screen  command  (N  or  NEXT)  was

         issued  when  the  user was already at the last screen of the

         current topic.



     4.  At Top Level Menu - No Upper Level.  The Up Level command  (U

         or  UP)  was issued when the user was at the highest level in

         the HELP tree.

                                                                Page 4





     5.  Help File is Empty.  The HELP tool was  told  to  process  an

         empty file.



     6.  No Menu Available.  The Display Menu command (M or MENU)  was

         issued when no menu was available under the current topic.



     7.  No More Menu Screens.  The Next Screen command  (N  or  NEXT)

         was  issued  during  a  menu  display  when  the current menu

         display is the last display of this menu.



     8.  Topic XXX Not Found.  The user's menu selection is not in the

         list  of  topics  available  at  the  current  menu.  This is

         probably caused by the user misspelling the desired topic.



     9.  Unexpected Fatal Error.  An error which was not expected  was

         encountered in the HELP file processing.



    10.  Unknown Command -- XXX --.  The indicated  command  (XXX)  is

         invalid.  This command is not one of the HELP commands.









2  HELP_ANALYZE



     HELP_ANALYZE performs an analysis of a direct-access file created

by HELP_BUILD.  It indicates each of the topics contained in the file,

and,  by   indentation,   shows   their   hierarchical   relationship.

HELP_ANALYZE  also displays, using the symbols "Start =" and "Stop =",

the beginning and ending record numbers of each topic.







2.1  EXECUTION OF TOOL





VMS Command Required to Invoke Tool: PHELP_ANALYZE

Input Files Required:

        Direct access help file

Output Files Generated: None

Notes:  PHELP_ANALYZE sends its report to the console.









2.2  ERROR MESSAGES



     "Help File Not Found" is the  only  error  message  generated  by

HELP_ANALYZE.







3  HELP_BUILD



     HELP_BUILD is used to create a direct-access  file  that  can  be

                                                                Page 5





processed  by  HELP  and  HELP_ANALYZE.  HELP_BUILD accepts as input a

conventional text file and generates a  direct-access  file  in  which

each record is a screen display.  Screens are defined as follows:



      *  When the number of text lines specified at installation  time

         is exceeded, the current screen is completed and a new screen

         is started.



      *  When a  screen-break  command  is  encountered,  the  current

         screen  is  completed  and  a  new  screen  is  started.  The

         screen-break command is a line containing only  a  period  in

         column one.



      *  When a new  topic  is  encountered,  the  current  screen  is

         completed  and  a  new  screen is started.  A topic is a line

         with a digit in column 1, a  space  in  column  2,  and  text

         following.









3.1  EXECUTION OF TOOL





VMS Command Required to Invoke Tool: PHELP_BUILD

Input Files Required:

        Text file in proper format

Output Files Generated:

        Direct access help data file

Notes:









3.2  HELP FILE STRUCTURE



     Topic levels and subordinate relationships are indicated  by  the

leading  digits  on  a topic line.  The following illustrates a simple

help file text:



        0 MAIN_TOPIC_1

                Text

        1 SUB_TOPIC_1

        1 SUB_TOPIC_2

        1 SUB_SUB_TOPIC_1

                Text, page 1

        .

                Text, page 2 (previous line caused screen-break)

        2 SUB_SUB_TOPIC_2

        2 SUB_SUB_TOPIC_3

        1 SUB_TOPIC_3

        0 MAIN_TOPIC_2

                                                                Page 6





     Topic level numbering does not  have  to  be  in  sequence.   The

numbers  associated  with subordinate topics need only be greater than

their parents.  For instance:



        1 MAIN_TOPIC

        5 SUB_TOPIC

and

        1 MAIN_TOPIC

        2 SUB_TOPIC



are valid and equivalent forms.







3.3  ERROR MESSAGES



     The following error messages may be displayed to the  console  by

HELP_BUILD:



     1.  Cannot Create Destination File.  The output  file  cannot  be

         created  for  some  reason.  Lack of disk space or an invalid

         file name are two possible reasons.



     2.  Source File Not Found.  The file specified  by  the  user  as

         source for HELP_BUILD does not exist.


::::::::::
help.rno
::::::::::
.ap
.figure 4
.center; User Manual for Online Documentation System
.figure 2
.center; by Richard Conn, TI Ada Technology Branch
.figure 4
.HEADER LEVEL 1 HELP
	HELP is an online documentation system.  It reads data
from a direct-access file generated by HELP__BUILD and builds
a tree which may be as wide as desired and up to ten levels
deep.  This tree contains sets of screen displays on various
topics.  After building this tree, HELP displays a menu of
the topics at the highest level, and the user can select a
desired topic by typing enough characters to uniquely identify
it.
	Once a desired topic is selected, HELP displays the screens
associated with this topic, allowing the user to move to the
next screen, last screen, up to the menu he came from, and
(if lower levels of information exist) display a menu of the
topics at the next lower level.  From this new menu, the process
is repeated (topics are selected, scanned, and lower levels of
menus may be accessed.
.HEADER LEVEL 2 EXECUTION OF TOOL
.literal

VMS Command Required to Invoke Tool: PHELP
Input Files Required:
	Direct access help file
Output Files Generated: None
Notes:  PHELP is an interactive tool.

.end literal
.HEADER LEVEL 2 PROMPTS
	Two prompts are presented to the user during the execution of
the HELP tool.  One prompt appears when the user is viewing a menu of
topics he can select and the other appears when the user is viewing
screens associated with a topic.
	The full prompt which can appear when a menu of topics is being
displayed is:
.literal

Level  N Menu: (Exit, Up, Next Menu Screen, Last Menu Screen,
	Selection)
.end literal
	The various parts of this prompt have the following meanings:
.no autoparagraph
.list
.LIST ELEMENT; Level N - Indicates the level in the tree you are at.
This part of the prompt always appears.
.LIST ELEMENT; Menu: - Indicates that you are viewing a menu as opposed to
screens of a topic.  This part of the prompt always appears.
.LIST ELEMENT; Exit - Indicates that the Exit command (X) is available.
This part of the prompt always appears.
.LIST ELEMENT; Up - Indicates that the Up command (U or UP) is available.
If you are at the top level, this part of the prompt does not appear.  If
you are below the top level, it does.
.LIST ELEMENT; Next Menu Screen - Indicates that more menu screens follow
the one you are viewing and the Next command (N or NEXT) is available.
This prompt optionally appears.
.LIST ELEMENT; Last Menu Screen - Indicates that one or more menu screens
preceed the one you are viewing and the Last command (L or LAST) is
available.  This prompt optionally appears.
.LIST ELEMENT; Selection - Indicates that you may select a topic from
any of the screens associated with this menu.  The topic does not have
to appear on the menu screen you are currently viewing.  This prompt always
appears.
.end list
.ap
	The full prompt which can appear while viewing screens associated
with a particular topic is:
.literal

Level  N Topic: XXX (Print, Exit, Up, Next, Last, Menu)
.end literal
	Various parts of this prompt are optional, and the meanings of
the sections of this prompt are:
.no autoparagraph
.list
.LIST ELEMENT; Level N - Indicates the current level.
This prompt always appears.
.LIST ELEMENT; Topic: XXX - Indicates the name of the topic you are viewing.
This prompt always appears.
.LIST ELEMENT; Print - Indicates that the user may print the current topic
(all screens) to a file.  The user is prompted for a file name in response
to the P or PRINT command.  If the user changes his mind, striking the
RETURN key aborts the print.  Typing in a file name prints into the file.
The user is returned to the current screen after the print is performed.
.LIST ELEMENT; Exit - Indicates that the Exit command (X) is available.
This prompt always appears.
.LIST ELEMENT; Up - Indicates that the Up command (U or UP) is available.
This command raises you to the next higher level (which is a menu).  This
prompt always appears.
.LIST ELEMENT; Next - Indicates that more screens on this topic follow.
The Next command (N or NEXT) displays the next screen to you.  This prompt
appears only if more screens follow.
Striking only the RETURN key has the same effect as the NEXT command.
.LIST ELEMENT; Last - Indicates that one or more screens proceed the
screen you are viewing on this topic.  The Last command (L or LAST) displays
the previous screen to you.  This prompt appears only if you are not at the
first screen of a topic.
.LIST ELEMENT; Menu - Indicates that a menu of subtopics under the current
topic is available.  The Menu command (M or MENU) will display this menu to
you.  This prompt appears only if one or more subtopics exist under the
current topic.
.end list
.ap
	At any time, the ? character (followed by a RETURN) will
cause the current screen to be refreshed.
.HEADER LEVEL 2 ERROR MESSAGES
	Error messages generated by the HELP tool are displayed at
the bottom of the screen with the following syntax:
.literal

	**** ERROR **** XXX Strike Any Key
.end literal
	The possible error messages are:
.no autoparagraph
.list
.LIST ELEMENT; At First Menu Screen.  The Last Screen command (L or LAST)
was issued when the user was already at the first screen of the menu display.
.LIST ELEMENT; At First Screen.  The Last Screen command (L or LAST)
was issued when the user was already at the first screen of the
current topic.
.LIST ELEMENT; At Last Screen.  The Next Screen command (N or NEXT)
was issued when the user was already at the last screen of the
current topic.
.LIST ELEMENT; At Top Level Menu - No Upper Level.  The Up Level command
(U or UP) was issued when the user was at the highest level in the HELP
tree.
.LIST ELEMENT; Help File is Empty.  The HELP tool was told to process an
empty file.
.LIST ELEMENT; No Menu Available.  The Display Menu command (M or MENU)
was issued when no menu was available under the current topic.
.LIST ELEMENT; No More Menu Screens.  The Next Screen command (N or NEXT)
was issued during a menu display when the current menu display is the
last display of this menu.
.LIST ELEMENT; Topic XXX Not Found.  The user's menu selection is not in
the list of topics available at the current menu.  This is probably
caused by the user misspelling the desired topic.
.LIST ELEMENT; Unexpected Fatal Error.  An error which was not expected
was encountered in the HELP file processing.
.LIST ELEMENT; Unknown Command -- XXX --.  The indicated command (XXX)
is invalid.  This command is not one of the HELP commands.
.end list
.ap

.HEADER LEVEL 1 HELP__ANALYZE
	HELP__ANALYZE performs an analysis of a direct-access
file created by HELP__BUILD.  It indicates each of the topics
contained in the file, and, by indentation, shows their
hierarchical relationship.  HELP__ANALYZE also displays, using
the symbols "Start =" and "Stop =", the beginning and ending
record numbers of each topic.
.HEADER LEVEL 2 EXECUTION OF TOOL
.literal

VMS Command Required to Invoke Tool: PHELP_ANALYZE
Input Files Required:
	Direct access help file
Output Files Generated: None
Notes:  PHELP_ANALYZE sends its report to the console.

.end literal
.HEADER LEVEL 2 ERROR MESSAGES
	"Help File Not Found" is the only error message generated
by HELP__ANALYZE.

.HEADER LEVEL 1 HELP__BUILD
	HELP__BUILD is used to create a direct-access file that
can be processed by HELP and HELP__ANALYZE.  HELP__BUILD accepts
as input a conventional text file and generates a direct-access
file in which each record is a screen display.
Screens are defined as follows:
.no autoparagraph
.list "*"
.LIST ELEMENT; When the number of text lines specified at installation
time is exceeded, the current screen is
completed and a new screen is started.
.LIST ELEMENT; When a screen-break command is encountered, the
current screen is completed and a new screen is started.  The
screen-break command is a line containing only a period in column
one.
.LIST ELEMENT; When a new topic is encountered, the current
screen is completed and a new screen is started.  A topic is a
line with a digit in column 1, a space in column 2, and text
following.
.end list
.ap
.HEADER LEVEL 2 EXECUTION OF TOOL
.literal

VMS Command Required to Invoke Tool: PHELP_BUILD
Input Files Required:
	Text file in proper format
Output Files Generated:
	Direct access help data file
Notes:

.end literal
.HEADER LEVEL 2 HELP FILE STRUCTURE
	Topic levels and subordinate relationships are indicated by
the leading digits on a topic line.
The following illustrates a simple help file text:
.literal

	0 MAIN_TOPIC_1
		Text
	1 SUB_TOPIC_1
	1 SUB_TOPIC_2
	1 SUB_SUB_TOPIC_1
		Text, page 1
	.
		Text, page 2 (previous line caused screen-break)
	2 SUB_SUB_TOPIC_2
	2 SUB_SUB_TOPIC_3
	1 SUB_TOPIC_3
	0 MAIN_TOPIC_2
.end literal
	Topic level numbering does not have to be in sequence.
The numbers associated with subordinate topics need only
be greater than their parents.  For instance:
.literal

	1 MAIN_TOPIC
	5 SUB_TOPIC
and
	1 MAIN_TOPIC
	2 SUB_TOPIC

.end literal
are valid and equivalent forms.
.HEADER LEVEL 2 ERROR MESSAGES
	The following error messages may be displayed to the console
by HELP__BUILD:
.no autoparagraph
.list
.LIST ELEMENT; Cannot Create Destination File.  The output file cannot
be created for some reason.  Lack of disk space or an invalid file
name are two possible reasons.
.LIST ELEMENT; Source File Not Found.  The file specified by the
user as source for HELP__BUILD does not exist.
.end list
.ap
